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

Add user configuration #225

Merged
merged 15 commits into from
Nov 7, 2022
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
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
6 changes: 4 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,18 @@ go 1.18
require (
github.com/fatih/color v1.13.0
github.com/google/go-github/v39 v39.2.0
github.com/hashicorp/go-getter v1.5.11
github.com/hashicorp/go-getter v1.6.2
github.com/nightlyone/lockfile v1.0.0
github.com/otiai10/copy v1.7.0
github.com/spf13/cobra v1.6.1
go.uber.org/zap v1.21.0
golang.org/x/mod v0.5.1
golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8
golang.org/x/sys v0.0.0-20220517195934-5e4e11fc645e
muzzammil.xyz/jsonc v1.0.0
)

replace github.com/hashicorp/go-getter => github.com/arikkfir/go-getter v1.6.3-0.20220803164326-281b7670b734
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're using the unofficial version of go-getter here. We have to wait until this PR will be merged:


require (
cloud.google.com/go v0.100.2 // indirect
cloud.google.com/go/compute v1.5.0 // indirect
Expand Down
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
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=
github.com/aws/aws-sdk-go v1.43.25 h1:PtdVewK7GZAGnu7JFdi4XFgH+j2AICXkHRjaAXow/4s=
github.com/aws/aws-sdk-go v1.43.25/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
Expand Down Expand Up @@ -189,8 +191,6 @@ github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/Oth
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
github.com/hashicorp/go-getter v1.5.11 h1:wioTuNmaBU3IE9vdFtFMcmZWj0QzLc6DYaP6sNe5onY=
github.com/hashicorp/go-getter v1.5.11/go.mod h1:9i48BP6wpWweI/0/+FBjqLrp9S8XtwUGjiu0QkWHEaY=
github.com/hashicorp/go-safetemp v1.0.0 h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhEyExpmo=
github.com/hashicorp/go-safetemp v1.0.0/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoDHxNAB65b+Rj1I=
github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
Expand Down Expand Up @@ -458,8 +458,8 @@ golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8 h1:OH54vjqzRWmbJ62fjuhxy7AxFFgoHN0/DPc/UrL8cAs=
golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220517195934-5e4e11fc645e h1:w36l2Uw3dRan1K3TyXriXvY+6T56GNmlKGcqiQUJDfM=
golang.org/x/sys v0.0.0-20220517195934-5e4e11fc645e/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
65 changes: 59 additions & 6 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,37 @@ the Regolith data folder to remove the cache files of the projects that you don'
You can clear caches of all projects stored in user data by using the "--user-cache" flag.
`

const regolithConfigDesc = `
The config command is used to manage the user configuration of Regolith. It can access and modify
global and project-specific configuration files. The global configuration file is stored in the
application data folder in the "user_config.json" file. The project-specific configuration file is
stored in the ".regolith/user_config.json". The project specific configuration file is used when
the local doesn't have specific properties defined. If the global configuration doesn't define them
either, the default values are used.

The behavior of the command changes based on the used flags and the number of provided arguments.
The cheetsheet below shows the possible combinations of flags and arguments and what they do:

Printing all properties: regolith config
Printing specified property: regolith config <key>
Setting property value: regolith config <key> <value>
Deleting a property: regolith config <key> --delete
Appending to a list proeprty: regolith config <key> <value> --append
Replacing item in a list property: regolith config <key> <value> --index <index>
Deleting item in a list property: regolith config <key> --index <index> --delete

You can use the "--global" or "--local" flags for all of the above combinations. To change whether
the command uses the global or local (project-specific) configuration file.

If you skip the "--global" or "--local" flag:
- The commands that edit the config file use the local config file by default.
- The commands that print the config file will print a combined view of the local and global
configuration. This view defines, what Regolith will actually use when running the project.

You can use "regolith config" command to see the full configuration to learn what properties are
available.
`

func main() {
// Schedule error handling
var err error
Expand Down Expand Up @@ -190,6 +221,10 @@ func main() {
Short: "Downloads and installs filters from the internet and adds them to the filterDefinitions list",
Long: regolithInitDesc,
Run: func(cmd *cobra.Command, filters []string) {
if len(filters) == 0 {
cmd.Help()
return
}
err = regolith.Install(filters, force, regolith.Debug)
},
}
Expand Down Expand Up @@ -243,10 +278,7 @@ func main() {
Long: regolithToolDesc,
Run: func(cmd *cobra.Command, args []string) {
if len(args) == 0 {
err = regolith.WrappedError(
"You must specify a filter name when running " +
"the \"regolith tool\" command.\n" +
"Use \"regolith help tool\" to learn more details.")
cmd.Help()
return
}
filter := args[0]
Expand All @@ -265,16 +297,37 @@ func main() {
err = regolith.Clean(regolith.Debug, userCache)
},
}
// regolith config
cmdConfig := &cobra.Command{
Use: "config [key] [value]",
Short: " Print or modify the user configuration.",
Long: regolithConfigDesc,
Run: func(cmd *cobra.Command, args []string) {
regolith.InitLogging(regolith.Debug)
global, _ := cmd.Flags().GetBool("global")
local, _ := cmd.Flags().GetBool("local")
delete, _ := cmd.Flags().GetBool("delete")
append, _ := cmd.Flags().GetBool("append")
index, _ := cmd.Flags().GetInt("index")
err = regolith.ManageConfig(regolith.Debug, global, local, delete, append, index, args)
},
}
cmdConfig.Flags().BoolP("global", "g", false, "Use global configuration file")
cmdConfig.Flags().BoolP("local", "l", false, "Use local (project) configuration file")
cmdConfig.Flags().BoolP("delete", "d", false, "Delete property")
cmdConfig.Flags().BoolP("append", "a", false, "Append value to array property")
cmdConfig.Flags().IntP("index", "i", -1, "The index of the array property on which to act")
subcomands = append(subcomands, cmdConfig)

cmdClean.Flags().BoolVarP(
&userCache, "user-cache", "u", false, "Clears all caches stored in user data, instead of the cache of "+
"the current project")
subcomands = append(subcomands, cmdClean)
// add --debug flag to every command
for _, cmd := range subcomands {
cmd.Flags().BoolVarP(&regolith.Debug, "debug", "d", false, "Enables debugging")
cmd.Flags().BoolVarP(&regolith.Debug, "debug", "", false, "Enables debugging")
}
// Build and run CLI
rootCmd.AddCommand(subcomands...)
rootCmd.Execute()

}
11 changes: 0 additions & 11 deletions regolith/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ type RegolithProject struct {
Profiles map[string]Profile `json:"profiles,omitempty"`
FilterDefinitions map[string]FilterInstaller `json:"filterDefinitions"`
DataPath string `json:"dataPath,omitempty"`
UseAppData bool `json:"useAppData,omitempty"`
}

// ConfigFromObject creates a "Config" object from map[string]interface{}
Expand Down Expand Up @@ -154,16 +153,6 @@ func RegolithProjectFromObject(
}
result.Profiles[profileName] = profileValue
}
// UseAppData (optional, false by default)
useAppData := false
if _, ok := obj["useAppData"]; ok {
useAppData, ok = obj["useAppData"].(bool)
if !ok {
return result, WrappedErrorf(
jsonPropertyTypeError, "useAppData", "boolean")
}
}
result.UseAppData = useAppData
return result, nil
}

Expand Down
19 changes: 0 additions & 19 deletions regolith/config_unparsed.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,22 +58,3 @@ func filterDefinitionsFromConfigMap(
}
return filterDefinitions, nil
}

// useAppDataFromConfigMap returns the useAppData value from the config file
// map, without parsing it to a Config object.
func useAppDataFromConfigMap(config map[string]interface{}) (bool, error) {
regolith, ok := config["regolith"].(map[string]interface{})
if !ok {
return false, WrappedErrorf(jsonPathMissingError, "regolith")
}
filterDefinitionsInterface, ok := regolith["useAppData"]
if !ok { // false by default
return false, nil
}
filterDefinitions, ok := filterDefinitionsInterface.(bool)
if !ok {
return false, WrappedErrorf(
jsonPathTypeError, "regolith->useAppData", "bool")
}
return filterDefinitions, nil
}
15 changes: 15 additions & 0 deletions regolith/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,9 @@ const (
// Error used when GetRegolithConfigPath fails
getRegolithConfigPathError = "Failed to get path to Regolith's app data folder."

// Error used when GetUserConfig function fails
getUserConfigError = "Failed to get user configuration."

// Error used whe Regolith fails to undo failed file system operation.
fsUndoError = "Filed to undo file system operation."

Expand All @@ -172,4 +175,16 @@ const (
"program (usually terminal).\n" +
"Please close your terminal and try again.\n" +
"Make sure that you open it directly inside the root of the Regolith project."

// Error used on attempt to access user config property that is not known
// to Regolith.
invalidUserConfigPropertyError = "Invalid user configuration property:\n" +
"Property name: %s\n"

// Error used when the getGlobalUserConfigPath function fails
getGlobalUserConfigPathError = "Failed to get global user_config.json path"

// Error used when the dump method of the UserConfig object failse
userConfigDumpError = "Failed to save the user configuration.\n" +
"Path: %s"
)
10 changes: 6 additions & 4 deletions regolith/install_add.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,12 +159,13 @@ func GetRemoteFilterDownloadRef(url, name, version string) (string, error) {
// changing the function signature. In order to pass it in the 'vg' list.
type vg []func(string, string) (string, error)
var versionGetters vg
getHeadSha := func(url, _ string) (string, error) { return GetHeadSha(url) }
if version == "" {
versionGetters = vg{GetLatestRemoteFilterTag, GetHeadSha}
versionGetters = vg{GetLatestRemoteFilterTag, getHeadSha}
} else if version == "latest" {
versionGetters = vg{GetLatestRemoteFilterTag}
} else if version == "HEAD" {
versionGetters = vg{GetHeadSha}
versionGetters = vg{getHeadSha}
} else {
if semver.IsValid("v" + version) {
version = name + "-" + version
Expand Down Expand Up @@ -228,12 +229,13 @@ func ListRemoteFilterTags(url, name string) ([]string, error) {
// GetHeadSha returns the SHA of the HEAD of the repository specified by the
// filter URL. This function does not check whether the filter actually exists
// in the repository.
func GetHeadSha(url, name string) (string, error) {
func GetHeadSha(url string) (string, error) {
commandArgs := []string{
"ls-remote", "--symref", "https://" + url, "HEAD"}
output, err := exec.Command("git", commandArgs...).Output()
if err != nil {
return "", WrapErrorf(err, execCommandError, name)
commandText := "git " + strings.Join(commandArgs, " ")
return "", WrapErrorf(err, execCommandError, commandText)
}
// The result is on the second line.
lines := strings.Split(string(output), "\n")
Expand Down
Loading