Skip to content
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

Update 1.5.0 #299

Merged
merged 21 commits into from
Dec 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
b1ded7b
Fix errors not being propagated during file watching initialization
arexon Sep 22, 2024
3650095
Report errors that occur during file watching loop
arexon Sep 22, 2024
e51e376
Merge pull request #295 from arexon/fix-file-watching-error-reporting
Nusiq Sep 25, 2024
1685858
Use fsnotify for file watching
arexon Sep 25, 2024
9409b9d
Generated CREDITS.csv
invalid-email-address Sep 25, 2024
76c4270
Update comment in DirWatcher
arexon Sep 25, 2024
adb4c97
Ignore file attribute events in DirWatcher
arexon Sep 26, 2024
05746a4
Clarify some stuff in DirWatcher
arexon Sep 26, 2024
c909a2b
Simplify file attribute event check in DirWatcher
arexon Sep 26, 2024
88d7fee
Re-add debouncing to DirWatcher
arexon Sep 27, 2024
e3c6903
Implement a lazy debouncer that ignores events after receiving an event
arexon Sep 29, 2024
74b3e02
Fix DirWatcher panic on Linux
arexon Sep 29, 2024
bd5b4e2
Generated CREDITS.csv
invalid-email-address Sep 29, 2024
2ee43d6
Fix file watcher not listening to events after `data` is copied/moved…
arexon Oct 12, 2024
4124cb0
Fix typos in comment
arexon Oct 12, 2024
ad507c7
Use a single DirWatcher instance and restart upon exporting
arexon Oct 14, 2024
7e61890
Remove redundant check
arexon Oct 14, 2024
524aa99
Handle setting `roots` up internally in DirWatcher
arexon Oct 14, 2024
0646a67
Update comment in DirWatcher
arexon Oct 14, 2024
e66dcdb
Preventing a potential issue of Regolith getting stuck in watch mode …
Nusiq Oct 14, 2024
25db602
Merge pull request #297 from arexon/fsnotify-dir-watcher
Nusiq Oct 14, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 2 additions & 32 deletions CREDITS.csv
Original file line number Diff line number Diff line change
@@ -1,56 +1,26 @@
cloud.google.com/go/compute/metadata,https://github.com/googleapis/google-cloud-go/blob/compute/v1.5.0/compute/LICENSE,Apache-2.0
cloud.google.com/go/iam,https://github.com/googleapis/google-cloud-go/blob/iam/v0.3.0/iam/LICENSE,Apache-2.0
cloud.google.com/go/internal,https://github.com/googleapis/google-cloud-go/blob/v0.100.2/LICENSE,Apache-2.0
cloud.google.com/go/storage,https://github.com/googleapis/google-cloud-go/blob/storage/v1.21.0/storage/LICENSE,Apache-2.0
github.com/Bedrock-OSS/go-burrito/burrito,https://github.com/Bedrock-OSS/go-burrito/blob/v1.0.3/LICENSE,MIT
github.com/Bedrock-OSS/regolith,https://github.com/Bedrock-OSS/regolith/blob/HEAD/LICENSE,MIT
github.com/alessio/shellescape,https://github.com/alessio/shellescape/blob/v1.4.1/LICENSE,MIT
github.com/antlr/antlr4/runtime/Go/antlr/v4,https://github.com/antlr/antlr4/blob/76fa05c21b12/runtime/Go/antlr/v4/LICENSE,BSD-3-Clause
github.com/aws/aws-sdk-go,https://github.com/aws/aws-sdk-go/blob/v1.43.25/LICENSE.txt,Apache-2.0
github.com/aws/aws-sdk-go/internal/sync/singleflight,https://github.com/aws/aws-sdk-go/blob/v1.43.25/internal/sync/singleflight/LICENSE,BSD-3-Clause
github.com/bgentry/go-netrc/netrc,https://github.com/bgentry/go-netrc/blob/9fd32a8b3d3d/LICENSE,MIT
github.com/arexon/fsnotify,https://github.com/arexon/fsnotify/blob/1ebdc44d4bc2/LICENSE,BSD-3-Clause
github.com/fatih/color,https://github.com/fatih/color/blob/v1.14.1/LICENSE.md,MIT
github.com/gammazero/deque,https://github.com/gammazero/deque/blob/v0.2.1/LICENSE,MIT
github.com/golang/groupcache/lru,https://github.com/golang/groupcache/blob/41bb18bfe9da/LICENSE,Apache-2.0
github.com/golang/protobuf,https://github.com/golang/protobuf/blob/v1.5.2/LICENSE,BSD-3-Clause
github.com/google/go-cmp/cmp,https://github.com/google/go-cmp/blob/v0.5.8/LICENSE,BSD-3-Clause
github.com/google/go-github/v39/github,https://github.com/google/go-github/blob/v39.2.0/LICENSE,BSD-3-Clause
github.com/google/go-querystring/query,https://github.com/google/go-querystring/blob/v1.1.0/LICENSE,BSD-3-Clause
github.com/googleapis/gax-go/v2,https://github.com/googleapis/gax-go/blob/v2.2.0/v2/LICENSE,BSD-3-Clause
github.com/hashicorp/go-cleanhttp,https://github.com/hashicorp/go-cleanhttp/blob/v0.5.2/LICENSE,MPL-2.0
github.com/hashicorp/go-getter,https://github.com/arikkfir/go-getter/blob/281b7670b734/LICENSE,MPL-2.0
github.com/hashicorp/go-safetemp,https://github.com/hashicorp/go-safetemp/blob/v1.0.0/LICENSE,MPL-2.0
github.com/hashicorp/go-version,https://github.com/hashicorp/go-version/blob/v1.4.0/LICENSE,MPL-2.0
github.com/jmespath/go-jmespath,https://github.com/jmespath/go-jmespath/blob/v0.4.0/LICENSE,Apache-2.0
github.com/klauspost/compress,https://github.com/klauspost/compress/blob/v1.15.1/LICENSE,Apache-2.0
github.com/klauspost/compress/internal/snapref,https://github.com/klauspost/compress/blob/v1.15.1/internal/snapref/LICENSE,BSD-3-Clause
github.com/klauspost/compress/zstd/internal/xxhash,https://github.com/klauspost/compress/blob/v1.15.1/zstd/internal/xxhash/LICENSE.txt,MIT
github.com/mattn/go-colorable,https://github.com/mattn/go-colorable/blob/v0.1.13/LICENSE,MIT
github.com/mattn/go-isatty,https://github.com/mattn/go-isatty/blob/v0.0.17/LICENSE,MIT
github.com/mitchellh/go-homedir,https://github.com/mitchellh/go-homedir/blob/v1.1.0/LICENSE,MIT
github.com/mitchellh/go-testing-interface,https://github.com/mitchellh/go-testing-interface/blob/v1.14.1/LICENSE,MIT
github.com/muhammadmuzzammil1998/jsonc,https://github.com/muhammadmuzzammil1998/jsonc/blob/v1.0.0/LICENSE,MIT
github.com/nightlyone/lockfile,https://github.com/nightlyone/lockfile/blob/v1.0.0/LICENSE,MIT
github.com/otiai10/copy,https://github.com/otiai10/copy/blob/v1.7.0/LICENSE,MIT
github.com/paul-mannino/go-fuzzywuzzy,https://github.com/paul-mannino/go-fuzzywuzzy/blob/54652b135d0e/LICENSE,GPL-3.0
github.com/spf13/cobra,https://github.com/spf13/cobra/blob/v1.6.1/LICENSE.txt,Apache-2.0
github.com/spf13/pflag,https://github.com/spf13/pflag/blob/v1.0.5/LICENSE,BSD-3-Clause
github.com/stirante/go-simple-eval,https://github.com/stirante/go-simple-eval/blob/9ed520afbec1/LICENSE,GPL-3.0
github.com/ulikunitz/xz,https://github.com/ulikunitz/xz/blob/v0.5.10/LICENSE,BSD-3-Clause
go.opencensus.io,https://github.com/census-instrumentation/opencensus-go/blob/v0.23.0/LICENSE,Apache-2.0
go.uber.org/atomic,https://github.com/uber-go/atomic/blob/v1.9.0/LICENSE.txt,MIT
go.uber.org/multierr,https://github.com/uber-go/multierr/blob/v1.8.0/LICENSE.txt,MIT
go.uber.org/zap,https://github.com/uber-go/zap/blob/v1.23.0/LICENSE.txt,MIT
golang.org/x/crypto,https://cs.opensource.google/go/x/crypto/+/v0.1.0:LICENSE,BSD-3-Clause
golang.org/x/exp,https://cs.opensource.google/go/x/exp/+/aae9b4e6:LICENSE,BSD-3-Clause
golang.org/x/mod/semver,https://cs.opensource.google/go/x/mod/+/v0.6.0:LICENSE,BSD-3-Clause
golang.org/x/net,https://cs.opensource.google/go/x/net/+/v0.1.0:LICENSE,BSD-3-Clause
golang.org/x/oauth2,https://cs.opensource.google/go/x/oauth2/+/6242fa91:LICENSE,BSD-3-Clause
golang.org/x/sys/unix,https://cs.opensource.google/go/x/sys/+/v0.4.0:LICENSE,BSD-3-Clause
golang.org/x/sys/unix,https://cs.opensource.google/go/x/sys/+/v0.13.0:LICENSE,BSD-3-Clause
golang.org/x/text,https://cs.opensource.google/go/x/text/+/v0.6.0:LICENSE,BSD-3-Clause
golang.org/x/xerrors,https://cs.opensource.google/go/x/xerrors/+/5ec99f83:LICENSE,BSD-3-Clause
google.golang.org/api,https://github.com/googleapis/google-api-go-client/blob/v0.73.0/LICENSE,BSD-3-Clause
google.golang.org/api/internal/third_party/uritemplates,https://github.com/googleapis/google-api-go-client/blob/v0.73.0/internal/third_party/uritemplates/LICENSE,BSD-3-Clause
google.golang.org/genproto/googleapis,https://github.com/googleapis/go-genproto/blob/acbaeb5b85eb/LICENSE,Apache-2.0
google.golang.org/grpc,https://github.com/grpc/grpc-go/blob/v1.45.0/LICENSE,Apache-2.0
google.golang.org/protobuf,https://github.com/protocolbuffers/protobuf-go/blob/v1.28.0/LICENSE,BSD-3-Clause
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ require (
github.com/stirante/go-simple-eval v0.0.0-20230131075324-9ed520afbec1
go.uber.org/zap v1.23.0
golang.org/x/mod v0.6.0
golang.org/x/sys v0.4.0
golang.org/x/sys v0.13.0
)

replace github.com/hashicorp/go-getter => github.com/arikkfir/go-getter v1.6.3-0.20220803164326-281b7670b734
Expand All @@ -27,6 +27,7 @@ require (
cloud.google.com/go/iam v0.3.0 // indirect
cloud.google.com/go/storage v1.21.0 // indirect
github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20221202181307-76fa05c21b12 // indirect
github.com/arexon/fsnotify v0.0.0-20240929211932-1ebdc44d4bc2 // indirect
github.com/aws/aws-sdk-go v1.43.25 // indirect
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect
github.com/gammazero/deque v0.2.1 // indirect
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ github.com/alessio/shellescape v1.4.1/go.mod h1:PZAiSCk0LJaZkiCSkPv8qIobYglO3FPp
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20221202181307-76fa05c21b12 h1:npHgfD4Tl2WJS3AJaMUi5ynGDPUBfkg3U3fCzDyXZ+4=
github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20221202181307-76fa05c21b12/go.mod h1:pSwJ0fSY5KhvocuWSx4fz3BA8OrA1bQn+K1Eli3BRwM=
github.com/arexon/fsnotify v0.0.0-20240929211932-1ebdc44d4bc2 h1:Y4fOHCKaIWeRXZ9+qqaB7UI0tjK/eMN6CZ9OCbY3FBY=
github.com/arexon/fsnotify v0.0.0-20240929211932-1ebdc44d4bc2/go.mod h1:fMK1EJDCm6IfeqTBptyizpl356fZy33nWqFKELbFouQ=
github.com/arikkfir/go-getter v1.6.3-0.20220803164326-281b7670b734 h1:csFUhbcumnsC5d0SMF8CvtR6Z/i4UeNgOZ6xUaQUYas=
github.com/arikkfir/go-getter v1.6.3-0.20220803164326-281b7670b734/go.mod h1:IZCrswsZPeWv9IkVnLElzRU/gz/QPi6pZHn4tv6vbwA=
github.com/aws/aws-sdk-go v1.15.78/go.mod h1:E3/ieXAlvM0XWO57iftYVDLLvQ824smPP3ATZkfNZeM=
Expand Down Expand Up @@ -473,6 +475,8 @@ golang.org/x/sys v0.0.0-20220517195934-5e4e11fc645e/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18=
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
Expand Down
21 changes: 0 additions & 21 deletions regolith/compatibility_other_os.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,27 +30,6 @@ func copyFileSecurityInfo(source string, target string) error {
return nil
}

type DirWatcher struct{}

func NewDirWatcher(path string) (*DirWatcher, error) {
return nil, burrito.WrappedError(notImplementedOnThisSystemError)
}

func (d *DirWatcher) WaitForChange() error {
return burrito.WrappedError(notImplementedOnThisSystemError)
}

func (d *DirWatcher) WaitForChangeGroup(
groupTimeout uint32, interruptionChannel chan string,
interruptionMessage string,
) error {
return burrito.WrappedError(notImplementedOnThisSystemError)
}

func (d *DirWatcher) Close() error {
return burrito.WrappedError(notImplementedOnThisSystemError)
}

func FindStandardMojangDir() (string, error) {
comMojang := os.Getenv("COM_MOJANG")
if comMojang == "" {
Expand Down
93 changes: 0 additions & 93 deletions regolith/compatibility_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,99 +53,6 @@ func copyFileSecurityInfo(source string, target string) error {
return nil
}

// DirWatcher is a struct that provides easy to use methods for watching a
// directory for changes. It uses FindFirstChangeNotification instead of
// ReadDirectoryChanges, so it doesn't provide any information about the
// changes, only the fact that something changed.
//
// Useful links:
// https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-findfirstchangenotificationa
//
// https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-findnextchangenotification
//
// https://pkg.go.dev/golang.org/x/[email protected]/windows
//
// https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-readdirectorychangesw
type DirWatcher struct {
handle windows.Handle
}

// NewDirWatcher creates a new DirWatcher for the given path. It filters out
// some of the less interesting events like FILE_NOTIFY_CHANGE_LAST_ACCESS.
func NewDirWatcher(path string) (*DirWatcher, error) {
var notifyFilter uint32 = (windows.FILE_NOTIFY_CHANGE_FILE_NAME |
windows.FILE_NOTIFY_CHANGE_DIR_NAME |
// windows.FILE_NOTIFY_CHANGE_ATTRIBUTES |
// windows.FILE_NOTIFY_CHANGE_SIZE |
windows.FILE_NOTIFY_CHANGE_LAST_WRITE |
// windows.FILE_NOTIFY_CHANGE_LAST_ACCESS |
// windows.FILE_NOTIFY_CHANGE_SECURITY |
windows.FILE_NOTIFY_CHANGE_CREATION)
handle, err := windows.FindFirstChangeNotification(
path, true, notifyFilter)
if err != nil {
return nil, err
}
return &DirWatcher{handle: handle}, nil
}

// WaitForChange locks the goroutine until a single change is detected. Note
// that some changes are reported multiple times, for example saving a file
// will cause a change to the file and a change to the directory. If you want
// to report cases like that as one event, see WaitForChangeGroup.
func (d *DirWatcher) WaitForChange() error {
_, err := windows.WaitForSingleObject(d.handle, windows.INFINITE)
if err != nil {
return err
}
err = windows.FindNextChangeNotification(d.handle)
if err != nil {
return err
}
return nil
}

// WaitForChangeGroup locks a goroutine until it receives a change notification.
// When that happens it sends the interruptionMessage to the
// interruptionChannel.
// Then it continues locking as long as other changes keep coming with
// intervals less than the given timeout, to group notifications that come
// in short intervals together.
func (d *DirWatcher) WaitForChangeGroup(
groupTimeout uint32, interruptionChannel chan string,
interruptionMessage string,
) error {
err := d.WaitForChange()
if err != nil {
return err
}
// Instantly report the change
interruptionChannel <- interruptionMessage
// Consume all changes for groupDelay duration
for {
event, err := windows.WaitForSingleObject(d.handle, groupTimeout)
if err != nil {
return err
}
// Possible options: WAIT_OBJECT_0, WAIT_ABANDONED, WAIT_TIMEOUT,
// WAIT_FAILED
if event == uint32(windows.WAIT_TIMEOUT) ||
event == uint32(windows.WAIT_ABANDONED) {
break
}
err = windows.FindNextChangeNotification(d.handle)
if err != nil {
return err
}
}
return nil
}

// Close closes DirWatcher handle.
func (d *DirWatcher) Close() error {
return windows.CloseHandle(d.handle)
}

// FindStandardMojangDir returns path to the com.mojang folder in the standard
// Minecraft build.
func FindStandardMojangDir() (string, error) {
Expand Down
74 changes: 20 additions & 54 deletions regolith/filter.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package regolith

import "github.com/Bedrock-OSS/go-burrito/burrito"
import (
"github.com/Bedrock-OSS/go-burrito/burrito"
)

type FilterDefinition struct {
Id string `json:"-"`
Expand All @@ -23,12 +25,18 @@ type RunContext struct {
DotRegolithPath string
Settings map[string]interface{}

// interruptionChannel is a channel that is used to notify about changes
// interruption is a channel that is used to notify about changes
// in the source files, in order to trigger a restart of the program in
// the watch mode. The string send to the channel is the name of the source
// of the change ("rp", "bp" or "data"), which may be used to handle
// some interruptions differently.
interruptionChannel chan string
interruption chan string

// fileWatchingError is used to pass any errors that may occur during
// file watching.
fileWatchingError chan error

fileWatchingStage chan string
}

// GetProfile returns the Profile structure from the context.
Expand All @@ -44,60 +52,18 @@ func (c *RunContext) GetProfile() (Profile, error) {
// IsInWatchMode returns a value that shows whether the context is in the
// watch mode.
func (c *RunContext) IsInWatchMode() bool {
return c.interruptionChannel == nil
return c.interruption != nil
}

// StartWatchingSourceFiles causes the Context to start goroutines that watch
// for changes in the source files and report that to the
func (c *RunContext) StartWatchingSourceFiles() error {
// TODO - if you want to be able to restart the watcher, you need to handle
// closing the channels somewhere. Currently the watching goroutines yield
// their messages until the end of the program. Sending to a closed channel
// would cause panic.
if c.interruptionChannel != nil {
return burrito.WrappedError("Files are already being watched.")
}

c.interruptionChannel = make(chan string)
yieldChanges := func(
watcher *DirWatcher, sourceName string,
) {
for {
err := watcher.WaitForChangeGroup(
100, c.interruptionChannel, sourceName)
if err != nil {
return
}
}
}

addWatcher := func(watchedPath, watcherString string) error {
watcher, err := NewDirWatcher(watchedPath)
if err != nil {
return burrito.PassError(err)
}
go yieldChanges(watcher, watcherString)
return nil
}

var err error
if c.Config.ResourceFolder != "" {
err = addWatcher(c.Config.ResourceFolder, "rp")
if err != nil {
return burrito.WrapError(err, "Could not create resource pack watcher.")
}
}
if c.Config.BehaviorFolder != "" {
err = addWatcher(c.Config.BehaviorFolder, "bp")
if err != nil {
return burrito.WrapError(err, "Could not create behavior pack watcher.")
}
}
if c.Config.DataPath != "" {
err = addWatcher(c.Config.DataPath, "data")
if err != nil {
return burrito.WrapError(err, "Could not create data watcher.")
}
c.interruption = make(chan string)
c.fileWatchingError = make(chan error)
c.fileWatchingStage = make(chan string)
err := NewDirWatcher(c.Config, c.interruption, c.fileWatchingError, c.fileWatchingStage)
if err != nil {
return err
}
return nil
}
Expand All @@ -106,11 +72,11 @@ func (c *RunContext) StartWatchingSourceFiles() error {
// unless the source of the interruption is on the list of ignored sources.
// This function does not block.
func (c *RunContext) IsInterrupted(ignoredSource ...string) bool {
if c.interruptionChannel == nil {
if c.interruption == nil {
return false
}
select {
case source := <-c.interruptionChannel:
case source := <-c.interruption:
for _, ignored := range ignoredSource {
if ignored == source {
return false
Expand Down
14 changes: 7 additions & 7 deletions regolith/filter_profile.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ type ProfileFilter struct {
func (f *ProfileFilter) Run(context RunContext) (bool, error) {
Logger.Infof("Running %q nested profile...", f.Profile)
return RunProfileImpl(RunContext{
Profile: f.Profile,
AbsoluteLocation: context.AbsoluteLocation,
Config: context.Config,
Parent: &context,
interruptionChannel: context.interruptionChannel,
DotRegolithPath: context.DotRegolithPath,
Settings: f.Settings,
Profile: f.Profile,
AbsoluteLocation: context.AbsoluteLocation,
Config: context.Config,
Parent: &context,
interruption: context.interruption,
DotRegolithPath: context.DotRegolithPath,
Settings: f.Settings,
})
}

Expand Down
Loading
Loading