From 4d90b71e9881ddbf48891e0c5a2861f085fc0a4b Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 8 Apr 2024 16:06:18 +0200 Subject: [PATCH 1/9] Fixed a piece of code that wasn't passing the error up (using WrappedErrorf(...) instead of WrapErrorf(err, ...)). --- regolith/filter_remote.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/regolith/filter_remote.go b/regolith/filter_remote.go index 7c7943bc..5fc90730 100644 --- a/regolith/filter_remote.go +++ b/regolith/filter_remote.go @@ -342,8 +342,8 @@ func FilterDefinitionFromTheInternet( if version == "" { // "" locks the version to the latest version, err = GetRemoteFilterDownloadRef(url, name, version) if err != nil { - return nil, burrito.WrappedErrorf( - getRemoteFilterDownloadRefError, url, name, version) + return nil, burrito.WrapErrorf( + err, getRemoteFilterDownloadRefError, url, name, version) } version = trimFilterPrefix(version, name) } From 34d16d88a2cb8fa87fff4ae967302c2bc0688b6e Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 27 Apr 2024 00:01:40 +0200 Subject: [PATCH 2/9] Separated the regolith watch and run code and updated file watching code: - The regolith watch and regolith run only share the setup, but run from separate functions. - The file observers are created only if the path in the config is not an empty string. --- regolith/filter.go | 51 ++++++++++-------- regolith/main_functions.go | 107 ++++++++++++++++++++++--------------- 2 files changed, 95 insertions(+), 63 deletions(-) diff --git a/regolith/filter.go b/regolith/filter.go index d5c802c7..49fbab06 100644 --- a/regolith/filter.go +++ b/regolith/filter.go @@ -57,18 +57,7 @@ func (c *RunContext) StartWatchingSourceFiles() error { if c.interruptionChannel != nil { return burrito.WrappedError("Files are already being watched.") } - rpWatcher, err := NewDirWatcher(c.Config.ResourceFolder) - if err != nil { - return burrito.WrapError(err, "Could not create resource pack watcher.") - } - bpWatcher, err := NewDirWatcher(c.Config.BehaviorFolder) - if err != nil { - return burrito.WrapError(err, "Could not create behavior pack watcher.") - } - dataWatcher, err := NewDirWatcher(c.Config.DataPath) - if err != nil { - return burrito.WrapError(err, "Could not create data watcher.") - } + c.interruptionChannel = make(chan string) yieldChanges := func( watcher *DirWatcher, sourceName string, @@ -81,16 +70,36 @@ func (c *RunContext) StartWatchingSourceFiles() error { } } } - go yieldChanges(rpWatcher, "rp") - go yieldChanges(bpWatcher, "bp") - go yieldChanges(dataWatcher, "data") - return nil -} -// AwaitInterruption locks the goroutine with the interruption channel until -// the Config is interrupted and returns the interruption message. -func (c *RunContext) AwaitInterruption() string { - return <-c.interruptionChannel + 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.") + } + } + return nil } // IsInterrupted returns true if there is a message on the interruptionChannel diff --git a/regolith/main_functions.go b/regolith/main_functions.go index 10922899..27a61dc0 100644 --- a/regolith/main_functions.go +++ b/regolith/main_functions.go @@ -4,9 +4,11 @@ import ( "encoding/json" "fmt" "os" + "os/signal" "path/filepath" "strconv" "strings" + "syscall" "time" "github.com/Bedrock-OSS/go-burrito/burrito" @@ -212,11 +214,9 @@ func InstallAll(force, debug, refreshFilters bool) error { return sessionLockErr // Return the error from the defer function } -// runOrWatch handles both 'regolith run' and 'regolith watch' commands based -// on the 'watch' parameter. It runs/watches the profile named after -// 'profileName' parameter. The 'debug' argument determines if the debug -// messages should be printed or not. -func runOrWatch(profileName string, debug, watch bool) error { +// prepareRunContext prepares the context for the "regolith run" and +// "regolith watch" commands. +func prepareRunContext(profileName string, debug, watch bool) (*RunContext, error) { InitLogging(debug) if profileName == "" { profileName = "default" @@ -224,65 +224,59 @@ func runOrWatch(profileName string, debug, watch bool) error { // Load the Config and the profile configJson, err := LoadConfigAsMap() if err != nil { - return burrito.WrapError(err, "Could not load \"config.json\".") + return nil, burrito.WrapError(err, "Could not load \"config.json\".") } config, err := ConfigFromObject(configJson) if err != nil { - return burrito.WrapError(err, "Could not load \"config.json\".") + return nil, burrito.WrapError(err, "Could not load \"config.json\".") } profile, ok := config.Profiles[profileName] if !ok { - return burrito.WrappedErrorf( + return nil, burrito.WrappedErrorf( "Profile %q does not exist in the configuration.", profileName) } // Get dotRegolithPath dotRegolithPath, err := GetDotRegolith(".") if err != nil { - return burrito.WrapError( + return nil, burrito.WrapError( err, "Unable to get the path to regolith cache folder.") } err = os.MkdirAll(dotRegolithPath, 0755) if err != nil { - return burrito.WrapErrorf(err, osMkdirError, dotRegolithPath) + return nil, burrito.WrapErrorf(err, osMkdirError, dotRegolithPath) } - // Lock the session - unlockSession, sessionLockErr := acquireSessionLock(dotRegolithPath) - if sessionLockErr != nil { - return burrito.WrapError(sessionLockErr, acquireSessionLockError) - } - defer func() { sessionLockErr = unlockSession() }() // Check the filters of the profile err = CheckProfileImpl(profile, profileName, *config, nil, dotRegolithPath) if err != nil { - return err + return nil, err } path, _ := filepath.Abs(".") - context := RunContext{ + return &RunContext{ AbsoluteLocation: path, Config: config, Parent: nil, Profile: profileName, DotRegolithPath: dotRegolithPath, Settings: map[string]interface{}{}, + }, nil +} + +// Run handles the "regolith run" command. It runs selected profile and exports +// created resource pack and behavior pack to the target destination. +func Run(profileName string, debug bool) error { + // Get the context + context, err := prepareRunContext(profileName, debug, false) + if err != nil { + return burrito.PassError(err) } - if watch { // Loop until program termination (CTRL+C) - context.StartWatchingSourceFiles() - for { - err = RunProfile(context) - if err != nil { - Logger.Errorf( - "Failed to run profile %q: %s", - profileName, burrito.PassError(err).Error()) - } else { - Logger.Infof("Successfully ran the %q profile.", profileName) - } - Logger.Info("Press Ctrl+C to stop watching.") - context.AwaitInterruption() - Logger.Warn("Restarting...") - } - // return nil // Unreachable code + // Lock the session + unlockSession, sessionLockErr := acquireSessionLock(context.DotRegolithPath) + if sessionLockErr != nil { + return burrito.WrapError(sessionLockErr, acquireSessionLockError) } - err = RunProfile(context) + defer func() { sessionLockErr = unlockSession() }() + // Run the profile + err = RunProfile(*context) if err != nil { return burrito.WrapErrorf(err, "Failed to run profile %q", profileName) } @@ -290,17 +284,46 @@ func runOrWatch(profileName string, debug, watch bool) error { return sessionLockErr // Return the error from the defer function } -// Run handles the "regolith run" command. It runs selected profile and exports -// created resource pack and behavior pack to the target destination. -func Run(profileName string, debug bool) error { - return runOrWatch(profileName, debug, false) -} - // Watch handles the "regolith watch" command. It watches the project // directories, and it runs selected profile and exports created resource pack // and behavior pack to the target destination when the project changes. func Watch(profileName string, debug bool) error { - return runOrWatch(profileName, debug, true) + // Get the context + context, err := prepareRunContext(profileName, debug, false) + if err != nil { + return burrito.PassError(err) + } + // Lock the session + unlockSession, sessionLockErr := acquireSessionLock(context.DotRegolithPath) + if sessionLockErr != nil { + return burrito.WrapError(sessionLockErr, acquireSessionLockError) + } + defer func() { sessionLockErr = unlockSession() }() + // Setup the channel for stopping the watching + sigChan := make(chan os.Signal, 1) + signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM) + + // Run the profile + context.StartWatchingSourceFiles() + for { // Loop until program termination (CTRL+C) + err = RunProfile(*context) + if err != nil { + Logger.Errorf( + "Failed to run profile %q: %s", + profileName, burrito.PassError(err).Error()) + } else { + Logger.Infof("Successfully ran the %q profile.", profileName) + } + Logger.Info("Press Ctrl+C to stop watching.") + select { + case <-context.interruptionChannel: + // AwaitInterruption locks the goroutine with the interruption channel until + // the Config is interrupted and returns the interruption message. + Logger.Warn("Restarting...") + case <-sigChan: + return sessionLockErr // Return the error from the defer function + } + } } // ApplyFilter handles the "regolith apply-filter" command. From 058f8884e31193efcc9679cb751d6925f1da2d33 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 5 May 2024 21:12:20 +0200 Subject: [PATCH 3/9] Removed 'isInstall' argument from 'installFilters' function, which was used only to control whether or not to show an optional warning message. --- regolith/filter_remote.go | 4 ++-- regolith/install_add.go | 4 ++-- regolith/main_functions.go | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/regolith/filter_remote.go b/regolith/filter_remote.go index 5fc90730..fb1f8e15 100644 --- a/regolith/filter_remote.go +++ b/regolith/filter_remote.go @@ -547,10 +547,10 @@ func (f *RemoteFilterDefinition) InstalledVersion(dotRegolithPath string) (strin return versionStr, nil } -func (f *RemoteFilterDefinition) Update(force bool, dotRegolithPath string, isInstall, refreshFilters bool) error { +func (f *RemoteFilterDefinition) Update(force bool, dotRegolithPath string, refreshFilters bool) error { installedVersion, err := f.InstalledVersion(dotRegolithPath) installedVersion = trimFilterPrefix(installedVersion, f.Id) - if err != nil && (!isInstall || force) { + if err != nil && force { Logger.Warnf("Unable to get installed version of filter %q.", f.Id) } MeasureStart("Get remote filter download ref") diff --git a/regolith/install_add.go b/regolith/install_add.go index 213c1acb..a3f5c6e4 100644 --- a/regolith/install_add.go +++ b/regolith/install_add.go @@ -29,7 +29,7 @@ type parsedInstallFilterArg struct { // it returns an error unless the force flag is set. func installFilters( filterDefinitions map[string]FilterInstaller, force bool, - dataPath, dotRegolithPath string, isInstall, refreshFilters bool, + dataPath, dotRegolithPath string, refreshFilters bool, ) error { joinedPath := filepath.Join(dotRegolithPath, "cache/filters") err := os.MkdirAll(joinedPath, 0755) @@ -47,7 +47,7 @@ func installFilters( Logger.Infof("Downloading %q filter...", name) if remoteFilter, ok := filterDefinition.(*RemoteFilterDefinition); ok { // Download the remote filter, and its dependencies - err := remoteFilter.Update(force, dotRegolithPath, isInstall, refreshFilters) + err := remoteFilter.Update(force, dotRegolithPath, refreshFilters) if err != nil { return burrito.WrapErrorf(err, remoteFilterDownloadError, name) } diff --git a/regolith/main_functions.go b/regolith/main_functions.go index 27a61dc0..3b57f6c7 100644 --- a/regolith/main_functions.go +++ b/regolith/main_functions.go @@ -129,7 +129,7 @@ func Install(filters []string, force, refreshResolvers, refreshFilters, add bool } // Download the filter definitions err = installFilters( - filterInstallers, force, dataPath, dotRegolithPath, true, refreshFilters) + filterInstallers, force, dataPath, dotRegolithPath, refreshFilters) if err != nil { return burrito.WrapError(err, "Failed to install filters.") } @@ -206,7 +206,7 @@ func InstallAll(force, debug, refreshFilters bool) error { defer func() { sessionLockErr = unlockSession() }() // Install the filters err = installFilters( - config.FilterDefinitions, force, config.DataPath, dotRegolithPath, false, refreshFilters) + config.FilterDefinitions, force, config.DataPath, dotRegolithPath, refreshFilters) if err != nil { return burrito.WrapError(err, "Could not install filters.") } From c3c13515543ba8e8238bf1c81d22a692f4c5739f Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 5 May 2024 22:15:45 +0200 Subject: [PATCH 4/9] Refactoring code: The install function used to take an 'add' argument to determine whether the filter should be added to specified profiles or not. The list of profiles was used only when the add flag was set to true. If user didn't provide the profiles explicitly it was set to a list with a single item - 'default'. Now, the internal behavior is changed - there is no 'add' flag, but the 'default' profile is added to the list only if the user uses the --profiles flag in the command. The behavior of the program from the user point of view is the same. Internally the Install funciton expects an empty list if no profiles need to be updated. --- main.go | 7 ++++-- regolith/main_functions.go | 50 ++++++++++++++++--------------------- test/remote_filters_test.go | 3 +-- 3 files changed, 27 insertions(+), 33 deletions(-) diff --git a/main.go b/main.go index 254ed3f0..eb557454 100644 --- a/main.go +++ b/main.go @@ -221,7 +221,7 @@ func main() { &force, "force", "f", false, "Force the operation, overriding potential safeguards.") subcommands = append(subcommands, cmdInit) - profiles := []string{"default"} + profiles := []string{} // regolith install var update, resolverRefresh, filterRefresh bool cmdInstall := &cobra.Command{ @@ -233,7 +233,10 @@ func main() { cmd.Help() return } - err = regolith.Install(filters, force || update, resolverRefresh, filterRefresh, cmd.Flags().Lookup("profile").Changed, profiles, burrito.PrintStackTrace) + if cmd.Flags().Lookup("profile").Changed && len(profiles) == 0 { + profiles = append(profiles, "default") + } + err = regolith.Install(filters, force || update, resolverRefresh, filterRefresh, profiles, burrito.PrintStackTrace) }, } cmdInstall.Flags().BoolVarP( diff --git a/regolith/main_functions.go b/regolith/main_functions.go index 3b57f6c7..66fcdd84 100644 --- a/regolith/main_functions.go +++ b/regolith/main_functions.go @@ -39,7 +39,7 @@ var disallowedFiles = []string{ // // The "debug" parameter is a boolean that determines if the debug messages // should be printed. -func Install(filters []string, force, refreshResolvers, refreshFilters, add bool, profiles []string, debug bool) error { +func Install(filters []string, force, refreshResolvers, refreshFilters bool, profiles []string, debug bool) error { InitLogging(debug) Logger.Info("Installing filters...") if !hasGit() { @@ -50,17 +50,11 @@ func Install(filters []string, force, refreshResolvers, refreshFilters, add bool return burrito.WrapError(err, "Unable to load config file.") } // Check if selected profiles exist - if add { - if len(profiles) == 0 { - profiles = []string{"default"} - } - // Get the profile - for _, profile := range profiles { - _, err := FindByJSONPath[map[string]interface{}](config, "regolith/profiles/"+EscapePathPart(profile)) - if err != nil { - return burrito.WrapErrorf( - err, "Profile %s does not exist or is invalid.", profile) - } + for _, profile := range profiles { + _, err := FindByJSONPath[map[string]interface{}](config, "regolith/profiles/"+EscapePathPart(profile)) + if err != nil { + return burrito.WrapErrorf( + err, "Profile %s does not exist or is invalid.", profile) } } // Get parts of config file required for installation @@ -137,24 +131,22 @@ func Install(filters []string, force, refreshResolvers, refreshFilters, add bool for name, downloadedFilter := range filterInstallers { // Add the filter to config file filterDefinitions[name] = downloadedFilter - if add { - // Add the filter to the profile - for _, profile := range profiles { - profileMap, err := FindByJSONPath[map[string]interface{}](config, "regolith/profiles/"+EscapePathPart(profile)) - // This check here is not necessary, because we have identical one at the beginning, but better to be safe - if err != nil { - return burrito.WrapErrorf( - err, "Profile %s does not exist or is invalid.", profile) - } - if profileMap["filters"] == nil { - profileMap["filters"] = make([]interface{}, 0) - } - // Add the filter to the profile - profileMap["filters"] = append( - profileMap["filters"].([]interface{}), map[string]interface{}{ - "filter": name, - }) + // Add the filter to the profile + for _, profile := range profiles { + profileMap, err := FindByJSONPath[map[string]interface{}](config, "regolith/profiles/"+EscapePathPart(profile)) + // This check here is not necessary, because we have identical one at the beginning, but better to be safe + if err != nil { + return burrito.WrapErrorf( + err, "Profile %s does not exist or is invalid.", profile) + } + if profileMap["filters"] == nil { + profileMap["filters"] = make([]interface{}, 0) } + // Add the filter to the profile + profileMap["filters"] = append( + profileMap["filters"].([]interface{}), map[string]interface{}{ + "filter": name, + }) } } // Save the config file diff --git a/test/remote_filters_test.go b/test/remote_filters_test.go index ea677b8d..e49f364b 100644 --- a/test/remote_filters_test.go +++ b/test/remote_filters_test.go @@ -127,8 +127,7 @@ func TestInstall(t *testing.T) { true, // Force false, // Refresh resolvers false, // Refresh filters - false, // Add to config - []string{"default"}, // Profiles + []string{}, // Profiles that should have the filter added true, // Debug ) if err != nil { From fce1b91f7d45c0db07a7ac9d9782f37faa143bcb Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 5 May 2024 22:28:33 +0200 Subject: [PATCH 5/9] Refactoring code: Moved adding filters to config (and saving it) to a separate function. --- regolith/install_add.go | 47 ++++++++++++++++++++++++++++++++++++++ regolith/main_functions.go | 30 ++++-------------------- 2 files changed, 51 insertions(+), 26 deletions(-) diff --git a/regolith/install_add.go b/regolith/install_add.go index a3f5c6e4..43dcbbda 100644 --- a/regolith/install_add.go +++ b/regolith/install_add.go @@ -1,6 +1,7 @@ package regolith import ( + "encoding/json" "os" "os/exec" "path/filepath" @@ -70,6 +71,52 @@ func installFilters( return nil } +// addFiltersToConfig modifies the config by adding the specified filters +// to the list of the filters in the project. If the profiles list is not +// empty, it also adds the filters to the specified profiles. After modifying +// the config, it saves it to the standard config file location. +func addFiltersToConfig( + config map[string]interface{}, + filterInstallers map[string]FilterInstaller, + profiles []string, +) error { + filterDefinitions, err := filterDefinitionsFromConfigMap(config) + if err != nil { + return burrito.WrapError( + err, + "Failed to get the list of filter definitions from config file.") + } + // Add the filters to the config + for name, downloadedFilter := range filterInstallers { + // Add the filter to config file + filterDefinitions[name] = downloadedFilter + // Add the filter to the profile + for _, profile := range profiles { + profileMap, err := FindByJSONPath[map[string]interface{}](config, "regolith/profiles/"+EscapePathPart(profile)) + // This check here is not necessary, because we have identical one at the beginning, but better to be safe + if err != nil { + return burrito.WrapErrorf( + err, "Profile %s does not exist or is invalid.", profile) + } + if profileMap["filters"] == nil { + profileMap["filters"] = make([]interface{}, 0) + } + // Add the filter to the profile + profileMap["filters"] = append( + profileMap["filters"].([]interface{}), map[string]interface{}{ + "filter": name, + }) + } + } + // Save the config file + jsonBytes, _ := json.MarshalIndent(config, "", "\t") + err = os.WriteFile(ConfigFilePath, jsonBytes, 0644) + if err != nil { + return burrito.WrapErrorf(err, fileWriteError, ConfigFilePath) + } + return nil +} + // parseInstallFilterArgs parses a list of arguments of the // "regolith install" command and returns a list of download tasks. func parseInstallFilterArgs( diff --git a/regolith/main_functions.go b/regolith/main_functions.go index 66fcdd84..7004b418 100644 --- a/regolith/main_functions.go +++ b/regolith/main_functions.go @@ -127,39 +127,17 @@ func Install(filters []string, force, refreshResolvers, refreshFilters bool, pro if err != nil { return burrito.WrapError(err, "Failed to install filters.") } - // Add the filters to the config - for name, downloadedFilter := range filterInstallers { - // Add the filter to config file - filterDefinitions[name] = downloadedFilter - // Add the filter to the profile - for _, profile := range profiles { - profileMap, err := FindByJSONPath[map[string]interface{}](config, "regolith/profiles/"+EscapePathPart(profile)) - // This check here is not necessary, because we have identical one at the beginning, but better to be safe - if err != nil { - return burrito.WrapErrorf( - err, "Profile %s does not exist or is invalid.", profile) - } - if profileMap["filters"] == nil { - profileMap["filters"] = make([]interface{}, 0) - } - // Add the filter to the profile - profileMap["filters"] = append( - profileMap["filters"].([]interface{}), map[string]interface{}{ - "filter": name, - }) - } - } - // Save the config file - jsonBytes, _ := json.MarshalIndent(config, "", "\t") - err = os.WriteFile(ConfigFilePath, jsonBytes, 0644) + + err = addFiltersToConfig(config, filterInstallers, profiles) if err != nil { return burrito.WrapErrorf( err, "Successfully downloaded %v filters"+ "but failed to update the config file.\n"+ "Run \"regolith clean\" to fix invalid cache state.", - len(parsedArgs)) + len(filterInstallers)) } + Logger.Info("Successfully installed the filters.") return sessionLockErr // Return the error from the defer function } From 8149c6e4eba7033304e4b8c42943ba57adcf5f00 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 5 May 2024 23:26:04 +0200 Subject: [PATCH 6/9] Added the --update flag to the 'regolith install-all' command; removed some duplicated error messages. --- main.go | 4 +++- regolith/install_add.go | 5 ++--- regolith/main_functions.go | 41 +++++++++++++++++++++++++++++-------- test/local_filters_test.go | 2 +- test/remote_filters_test.go | 6 +++--- 5 files changed, 41 insertions(+), 17 deletions(-) diff --git a/main.go b/main.go index eb557454..17b2403b 100644 --- a/main.go +++ b/main.go @@ -257,11 +257,13 @@ func main() { Short: "Installs all nonexistent or outdated filters defined in filterDefinitions list", Long: regolithInstallAllDesc, Run: func(cmd *cobra.Command, _ []string) { - err = regolith.InstallAll(force, burrito.PrintStackTrace, filterRefresh) + err = regolith.InstallAll(force, update, burrito.PrintStackTrace, filterRefresh) }, } cmdInstallAll.Flags().BoolVarP( &force, "force", "f", false, "Force the operation, overriding potential safeguards.") + cmdInstallAll.Flags().BoolVarP( + &update, "update", "u", false, "Updates the remote filters to the latest stable version available.") cmdInstallAll.Flags().BoolVar( &filterRefresh, "force-filter-refresh", false, "Force filter cache refresh.") subcommands = append(subcommands, cmdInstallAll) diff --git a/regolith/install_add.go b/regolith/install_add.go index 43dcbbda..a0a62b71 100644 --- a/regolith/install_add.go +++ b/regolith/install_add.go @@ -29,7 +29,7 @@ type parsedInstallFilterArg struct { // and copies their data to the data path. If the filter is already installed, // it returns an error unless the force flag is set. func installFilters( - filterDefinitions map[string]FilterInstaller, force bool, + filtersToInstall map[string]FilterInstaller, force bool, dataPath, dotRegolithPath string, refreshFilters bool, ) error { joinedPath := filepath.Join(dotRegolithPath, "cache/filters") @@ -44,7 +44,7 @@ func installFilters( } // Download all the remote filters - for name, filterDefinition := range filterDefinitions { + for name, filterDefinition := range filtersToInstall { Logger.Infof("Downloading %q filter...", name) if remoteFilter, ok := filterDefinition.(*RemoteFilterDefinition); ok { // Download the remote filter, and its dependencies @@ -93,7 +93,6 @@ func addFiltersToConfig( // Add the filter to the profile for _, profile := range profiles { profileMap, err := FindByJSONPath[map[string]interface{}](config, "regolith/profiles/"+EscapePathPart(profile)) - // This check here is not necessary, because we have identical one at the beginning, but better to be safe if err != nil { return burrito.WrapErrorf( err, "Profile %s does not exist or is invalid.", profile) diff --git a/regolith/main_functions.go b/regolith/main_functions.go index 7004b418..0e43d9db 100644 --- a/regolith/main_functions.go +++ b/regolith/main_functions.go @@ -106,13 +106,7 @@ func Install(filters []string, force, refreshResolvers, refreshFilters bool, pro remoteFilterDefinition, err := FilterDefinitionFromTheInternet( parsedArg.url, parsedArg.name, parsedArg.version) if err != nil { - return burrito.WrapErrorf( - err, - "Unable to download the filter definition from the internet.\n"+ - "Filter repository Url: %s\n"+ - "Filter name: %s\n"+ - "Filter version: %s\n", - parsedArg.url, parsedArg.name, parsedArg.version) + return burrito.PassError(err) } if parsedArg.version == "HEAD" || parsedArg.version == "latest" { // The "HEAD" and "latest" keywords should be the same in the @@ -151,7 +145,7 @@ func Install(filters []string, force, refreshResolvers, refreshFilters bool, pro // // The "debug" parameter is a boolean that determines if the debug messages // should be printed. -func InstallAll(force, debug, refreshFilters bool) error { +func InstallAll(force, update, debug, refreshFilters bool) error { InitLogging(debug) Logger.Info("Installing filters...") if !hasGit() { @@ -174,12 +168,41 @@ func InstallAll(force, debug, refreshFilters bool) error { return burrito.WrapError(sessionLockErr, acquireSessionLockError) } defer func() { sessionLockErr = unlockSession() }() + + filtersToInstall := make(map[string]FilterInstaller, 0) + remoteFilters := make(map[string]FilterInstaller, 0) // Used for updating the config + if update { + for filterName, filterDefinition := range config.FilterDefinitions { + + switch fd := filterDefinition.(type) { + case *RemoteFilterDefinition: + filterInstaller, err := FilterDefinitionFromTheInternet( + fd.Url, fd.Id, "") + if err != nil { + return burrito.PassError(err) + } + filtersToInstall[filterName] = filterInstaller + remoteFilters[filterName] = filterInstaller + default: + filtersToInstall[filterName] = fd + } + } + } else { + filtersToInstall = config.FilterDefinitions + } // Install the filters err = installFilters( - config.FilterDefinitions, force, config.DataPath, dotRegolithPath, refreshFilters) + filtersToInstall, force, config.DataPath, dotRegolithPath, refreshFilters) if err != nil { return burrito.WrapError(err, "Could not install filters.") } + // Update the config + if update { + err = addFiltersToConfig(configMap, remoteFilters, nil) + if err != nil { + return burrito.WrapError(err, "Failed to update the config file.") + } + } Logger.Info("Successfully installed the filters.") return sessionLockErr // Return the error from the defer function } diff --git a/test/local_filters_test.go b/test/local_filters_test.go index 8be38f22..32bd268a 100644 --- a/test/local_filters_test.go +++ b/test/local_filters_test.go @@ -66,7 +66,7 @@ func TestLocalRequirementsInstallAndRun(t *testing.T) { // THE TEST t.Log("Testing the 'regolith install-all' command...") - err := regolith.InstallAll(false, true, false) + err := regolith.InstallAll(false, false, true, false) if err != nil { t.Fatal("'regolith install-all' failed", err.Error()) } diff --git a/test/remote_filters_test.go b/test/remote_filters_test.go index e49f364b..5acbf121 100644 --- a/test/remote_filters_test.go +++ b/test/remote_filters_test.go @@ -31,7 +31,7 @@ func TestInstallAllAndRun(t *testing.T) { // THE TEST t.Log("Testing the 'regolith install-all' command...") - err := regolith.InstallAll(false, true, false) + err := regolith.InstallAll(false, false, true, false) if err != nil { t.Fatal("'regolith install-all' failed:", err) } @@ -71,7 +71,7 @@ func TestDataModifyRemoteFilter(t *testing.T) { // THE TEST t.Log("Testing the 'regolith install-all' command...") - err := regolith.InstallAll(false, true, false) + err := regolith.InstallAll(false, false, true, false) if err != nil { t.Fatal("'regolith install-all' failed:", err) } @@ -186,7 +186,7 @@ func TestInstallAll(t *testing.T) { // Run 'regolith update' / 'regolith update-all' t.Log("Running 'regolith update'...") - err = regolith.InstallAll(false, true, false) + err = regolith.InstallAll(false, false, true, false) if err != nil { t.Fatal("'regolith update' failed:", err) } From 75a20a0a6157c1be1cff3da9fe2ac1fdb6e00212 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 8 Jun 2024 11:29:57 +0200 Subject: [PATCH 7/9] Fixed invalid 'warning' markdown tags in the documentation: Old: '{: .notice--warning}' New: ':::: warning' --- docs/docs/guide/getting-started.md | 6 ++++-- docs/docs/guide/installing-filters.md | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/docs/docs/guide/getting-started.md b/docs/docs/guide/getting-started.md index 89f9f4a8..32f99357 100644 --- a/docs/docs/guide/getting-started.md +++ b/docs/docs/guide/getting-started.md @@ -131,11 +131,13 @@ Now, you can re-run `regolith run`. Check `com.mojang`, and open the new `texture_list.json` file in `RP/textures/texture_list.json`. Every time you run regolith, this file will be re-created, based on your current textures. No need to manually edit it ever again! -{: .notice--warning} +:::: warning `Warning:` If your resource pack already contains `texture_list.json`, you should delete it. You don't need to manually worry about it anymore - Regolith will handle it! +:::: -{: .notice--warning} +:::: warning `Warning:` If your project doesn't have any textures, than `texture_list.json` will simply create a blank file `[]`. Consider adding some textures to see the filter at work! +:::: ## Whats Next diff --git a/docs/docs/guide/installing-filters.md b/docs/docs/guide/installing-filters.md index 2152d8af..b08a95db 100644 --- a/docs/docs/guide/installing-filters.md +++ b/docs/docs/guide/installing-filters.md @@ -65,15 +65,17 @@ Regolith is intended to be used with git version control, and by default the `.r You may use the command `regolith install-all`, which will check `config.json`, and install every filter in the `filterDefinitions`. -{: .notice--warning} +:::: warning This is only intended to be used with existing projects. To install new filters, use `regolith install`. +:::: ## Filter Versioning Filters in Regolith are optionally versioned with a [semantic version](https://semver.org/). As filters get updated, new versions will be released, and you can optionally update. -{: .notice--warning} +:::: warning If you don't specify a version, the `install` command will pick a sensible default. First, it will search for the latest release. If that doesn't exist (such as a filter that has no versions), it will select the latest commit in the repository. In both cases, the installed version will be `pinned`. +:::: ### Installing a Specific Version From 385830259cb5d83e7d8c24794866ddba621c9556 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 8 Jun 2024 11:49:58 +0200 Subject: [PATCH 8/9] The documentation mentiones the '--update' flag for 'regolith install-all' command. --- docs/docs/guide/installing-filters.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/docs/guide/installing-filters.md b/docs/docs/guide/installing-filters.md index b08a95db..4a6535c5 100644 --- a/docs/docs/guide/installing-filters.md +++ b/docs/docs/guide/installing-filters.md @@ -104,6 +104,12 @@ regolith install name_ninja --update Alternatively, you can modify the `version` field in `config.json` and run `regolith install-all`. Regolith install-all is useful for working in a team, when other team members may have to update or add filters to the project. +If you want to update all filters in your project, you can use the `--update` flag with the `install-all` command. + +``` +regolith install-all --update +``` + ### Updating resolvers When using short names for filters, Regolith uses a resolver file from a remote repository to determine the URL of the filter. From ca7138e587a3d8cd0989d829909788eb3ec2a688 Mon Sep 17 00:00:00 2001 From: stirante Date: Tue, 11 Jun 2024 17:03:29 +0200 Subject: [PATCH 9/9] Move copying data before installing dependencies --- regolith/filter_remote.go | 4 +++- regolith/install_add.go | 4 +--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/regolith/filter_remote.go b/regolith/filter_remote.go index fb1f8e15..66bfeb14 100644 --- a/regolith/filter_remote.go +++ b/regolith/filter_remote.go @@ -547,7 +547,7 @@ func (f *RemoteFilterDefinition) InstalledVersion(dotRegolithPath string) (strin return versionStr, nil } -func (f *RemoteFilterDefinition) Update(force bool, dotRegolithPath string, refreshFilters bool) error { +func (f *RemoteFilterDefinition) Update(force bool, dotRegolithPath, dataPath string, refreshFilters bool) error { installedVersion, err := f.InstalledVersion(dotRegolithPath) installedVersion = trimFilterPrefix(installedVersion, f.Id) if err != nil && force { @@ -569,6 +569,8 @@ func (f *RemoteFilterDefinition) Update(force bool, dotRegolithPath string, refr if err != nil { return burrito.PassError(err) } + // Copy the data of the remote filter to the data path + f.CopyFilterData(dataPath, dotRegolithPath) err = f.InstallDependencies(f, dotRegolithPath) if err != nil { return burrito.PassError(err) diff --git a/regolith/install_add.go b/regolith/install_add.go index a0a62b71..3127f690 100644 --- a/regolith/install_add.go +++ b/regolith/install_add.go @@ -48,12 +48,10 @@ func installFilters( Logger.Infof("Downloading %q filter...", name) if remoteFilter, ok := filterDefinition.(*RemoteFilterDefinition); ok { // Download the remote filter, and its dependencies - err := remoteFilter.Update(force, dotRegolithPath, refreshFilters) + err := remoteFilter.Update(force, dotRegolithPath, dataPath, refreshFilters) if err != nil { return burrito.WrapErrorf(err, remoteFilterDownloadError, name) } - // Copy the data of the remote filter to the data path - remoteFilter.CopyFilterData(dataPath, dotRegolithPath) } else { // Non-remote filters must always update their dependencies. // TODO - add option to track if the filter already installed