-
Notifications
You must be signed in to change notification settings - Fork 413
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: run local --watch flag #5413
Changes from 8 commits
9b15223
3bb3f2f
e265dd5
423fafd
61bcafc
14eb108
8a7d8a2
9701f70
21d6605
8ea2c38
142bc12
80aa093
3ccfae2
0364052
64dffc8
52ca8e7
497df05
b09f63a
e0c82a8
28c34b7
edcc10f
563bdc3
c361a7d
6439229
e4c2f41
193b84e
6349e0c
dd9dd0b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package filetest | ||
|
||
import "github.com/fsnotify/fsnotify" | ||
|
||
// Double is a test double for file.RecursiveWatcher | ||
type Double struct { | ||
EventsFn func() <-chan fsnotify.Event | ||
ErrorsFn func() <-chan error | ||
} | ||
|
||
// Add is a no-op for Double. | ||
func (d *Double) Add(string) error { | ||
return nil | ||
} | ||
|
||
// Close is a no-op for Double. | ||
func (d *Double) Close() error { | ||
return nil | ||
} | ||
|
||
// Events calls the stubbed function. | ||
func (d *Double) Events() <-chan fsnotify.Event { | ||
if d.EventsFn == nil { | ||
return nil | ||
} | ||
return d.EventsFn() | ||
} | ||
|
||
// Errors calls the stubbed function. | ||
func (d *Double) Errors() <-chan error { | ||
if d.ErrorsFn == nil { | ||
return nil | ||
} | ||
return d.ErrorsFn() | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
//go:build !windows | ||
|
||
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package file | ||
|
||
import "path/filepath" | ||
|
||
// IsHiddenFile returns true if the file is hidden on non-windows. | ||
CaptainCarpensir marked this conversation as resolved.
Show resolved
Hide resolved
|
||
func IsHiddenFile(filename string) (bool, error) { | ||
return filepath.Base(filename)[0] == '.', nil | ||
CaptainCarpensir marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package file | ||
|
||
import ( | ||
"syscall" | ||
) | ||
|
||
// IsHiddenFile returns true if the file is hidden on windows. | ||
func IsHiddenFile(filename string) (bool, error) { | ||
pointer, err := syscall.UTF16PtrFromString(filename) | ||
if err != nil { | ||
return false, err | ||
} | ||
attributes, err := syscall.GetFileAttributes(pointer) | ||
if err != nil { | ||
return false, err | ||
} | ||
return attributes&syscall.FILE_ATTRIBUTE_HIDDEN != 0, nil | ||
} |
CaptainCarpensir marked this conversation as resolved.
Show resolved
Hide resolved
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package file | ||
|
||
import ( | ||
"io/fs" | ||
"os" | ||
"path/filepath" | ||
|
||
"github.com/fsnotify/fsnotify" | ||
) | ||
|
||
// RecursiveWatcher wraps an fsnotify Watcher to recursively watch all files in a directory. | ||
type RecursiveWatcher struct { | ||
fsnotifyWatcher *fsnotify.Watcher | ||
done chan struct{} | ||
closed bool | ||
events chan fsnotify.Event | ||
errors chan error | ||
} | ||
|
||
// NewRecursiveWatcher returns a RecursiveWatcher which notifies when changes are made to files inside a recursive directory tree. | ||
func NewRecursiveWatcher(dir string) (*RecursiveWatcher, error) { | ||
watcher, err := fsnotify.NewWatcher() | ||
CaptainCarpensir marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
rw := &RecursiveWatcher{ | ||
events: make(chan fsnotify.Event), | ||
errors: make(chan error), | ||
fsnotifyWatcher: watcher, | ||
done: make(chan struct{}), | ||
closed: false, | ||
} | ||
|
||
go rw.start() | ||
|
||
return rw, nil | ||
} | ||
|
||
// Add recursively adds a directory tree to the list of watched files. | ||
func (rw *RecursiveWatcher) Add(path string) error { | ||
if rw.closed { | ||
return fsnotify.ErrClosed | ||
} | ||
if err := filepath.WalkDir(path, func(path string, d fs.DirEntry, err error) error { | ||
if err != nil { | ||
return err | ||
} | ||
if d.IsDir() { | ||
return rw.fsnotifyWatcher.Add(path) | ||
} | ||
return nil | ||
}); err != nil { | ||
return err | ||
} | ||
return nil | ||
} | ||
|
||
// Remove recursively removes a directory tree from the list of watched files. | ||
func (rw *RecursiveWatcher) Remove(path string) error { | ||
if rw.closed { | ||
return nil | ||
} | ||
if err := filepath.WalkDir(path, func(path string, d fs.DirEntry, err error) error { | ||
if err != nil { | ||
return err | ||
} | ||
if d.IsDir() { | ||
return rw.fsnotifyWatcher.Remove(path) | ||
} | ||
return nil | ||
}); err != nil { | ||
return err | ||
} | ||
return nil | ||
} | ||
|
||
// Events returns the events channel. | ||
func (rw *RecursiveWatcher) Events() <-chan fsnotify.Event { | ||
return rw.events | ||
} | ||
|
||
// Errors returns the errors channel. | ||
func (rw *RecursiveWatcher) Errors() <-chan error { | ||
return rw.errors | ||
} | ||
|
||
// Close closes the RecursiveWatcher. | ||
func (rw *RecursiveWatcher) Close() error { | ||
rw.closed = true | ||
close(rw.done) | ||
return rw.fsnotifyWatcher.Close() | ||
} | ||
|
||
func (rw *RecursiveWatcher) start() { | ||
for { | ||
select { | ||
case event := <-rw.fsnotifyWatcher.Events: | ||
info, err := os.Stat(event.Name) | ||
CaptainCarpensir marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if err != nil { | ||
break | ||
CaptainCarpensir marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
if info.IsDir() { | ||
switch event.Op { | ||
CaptainCarpensir marked this conversation as resolved.
Show resolved
Hide resolved
|
||
case fsnotify.Create: | ||
err := rw.Add(event.Name) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It seems like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nope, |
||
if err != nil { | ||
rw.errors <- err | ||
} | ||
case fsnotify.Remove: | ||
err := rw.Remove(event.Name) | ||
if err != nil { | ||
rw.errors <- err | ||
} | ||
} | ||
} else { | ||
rw.events <- event | ||
} | ||
case err := <-rw.fsnotifyWatcher.Errors: | ||
rw.errors <- err | ||
case <-rw.done: | ||
close(rw.events) | ||
close(rw.errors) | ||
return | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we use this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah it's used in
run_local_test.go
but maybe the package name should be changed.