From 5dcce02a3af17000e71521a0c0ca82456e6c47be Mon Sep 17 00:00:00 2001 From: Matt Clarkson Date: Mon, 8 Apr 2024 17:14:27 +0100 Subject: [PATCH] feat: implement `git config $NAME $VALUE` This is needed to set `core.compression` to `9` in `rules_git`. Nothing else is implemented other than setting repository local configurations. --- cmd/bazel-git/BUILD.bazel | 2 ++ cmd/bazel-git/cat-file.go | 1 + cmd/bazel-git/config.go | 43 +++++++++++++++++++++++++++++++ config/BUILD.bazel | 19 ++++++++++++++ config/set.go | 53 +++++++++++++++++++++++++++++++++++++++ config/set_test.go | 32 +++++++++++++++++++++++ 6 files changed, 150 insertions(+) create mode 100644 cmd/bazel-git/config.go create mode 100644 config/BUILD.bazel create mode 100644 config/set.go create mode 100644 config/set_test.go diff --git a/cmd/bazel-git/BUILD.bazel b/cmd/bazel-git/BUILD.bazel index 8997861..4b59524 100644 --- a/cmd/bazel-git/BUILD.bazel +++ b/cmd/bazel-git/BUILD.bazel @@ -6,6 +6,7 @@ go_library( srcs = [ "cat-file.go", "checkout.go", + "config.go", "error.go", "fetch.go", "init.go", @@ -16,6 +17,7 @@ go_library( visibility = ["//visibility:private"], deps = [ "//checkout", + "//config", "//fetch", "//object", "//reference", diff --git a/cmd/bazel-git/cat-file.go b/cmd/bazel-git/cat-file.go index 36fda48..b1e67cc 100644 --- a/cmd/bazel-git/cat-file.go +++ b/cmd/bazel-git/cat-file.go @@ -1,6 +1,7 @@ package main import ( + "errors" "log/slog" "github.com/jessevdk/go-flags" diff --git a/cmd/bazel-git/config.go b/cmd/bazel-git/config.go new file mode 100644 index 0000000..6680caa --- /dev/null +++ b/cmd/bazel-git/config.go @@ -0,0 +1,43 @@ +package main + +import ( + "log/slog" + + "github.com/jessevdk/go-flags" + "gitlab.arm.com/bazel/git/v1/config" +) + +type ConfigCommand struct { + Args struct { + Name string `positional-arg-name:"" description:"The configuration option name." required:"yes"` + Value string `positional-arg-name:"" description:"The configuration option value." required:"yes"` + } `positional-args:"yes"` +} + +var configCommand ConfigCommand + +func (x *ConfigCommand) Execute(rest []string) error { + if len(rest) != 0 { + return &flags.Error{flags.ErrDuplicatedFlag, "unsupported number of positional arguments"} + } + + log := slog.With("name", x.Args.Name, "value", x.Args.Value) + log.Debug("set") + err := config.Set(config.SetOptions{ + GitDir: options.Dir, + Name: x.Args.Name, + Value: x.Args.Value, + }) + if err != nil { + return err + } + + return nil +} + +func init() { + parser.AddCommand("config", + "Set repository options.", + `Sets repository options using a dot-separated key and value pair.`, + &configCommand) +} diff --git a/config/BUILD.bazel b/config/BUILD.bazel new file mode 100644 index 0000000..e20eea5 --- /dev/null +++ b/config/BUILD.bazel @@ -0,0 +1,19 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "config", + srcs = ["set.go"], + importpath = "gitlab.arm.com/bazel/git/v1/config", + visibility = ["//visibility:public"], + deps = ["@com_github_go_git_go_git_v5//:go_default_library"], +) + +go_test( + name = "config_test", + srcs = ["set_test.go"], + embed = [":config"], + deps = [ + "@com_github_go_git_go_git_v5//:go_default_library", + "@com_github_stretchr_testify//assert:go_default_library", + ], +) diff --git a/config/set.go b/config/set.go new file mode 100644 index 0000000..6e91532 --- /dev/null +++ b/config/set.go @@ -0,0 +1,53 @@ +package config + +import ( + "errors" + "fmt" + "log/slog" + "strings" + + "github.com/go-git/go-git/v5" +) + +type SetOptions struct { + GitDir string + Name string + Value string +} + +func Set(options SetOptions) (err error) { + log := slog.With("namespace", "config.Set", "name", options.Name, "value", options.Value) + + log.Debug("open", "git-dir", options.GitDir) + repo, err := git.PlainOpen(options.GitDir) + if err != nil { + log.Error("open", "err", err) + return err + } + config, err := repo.Config() + if err != nil { + log.Error("config", "err", err) + return err + } + + if config.Raw == nil { + return errors.New("Unexpected empty raw configuration value") + } + + parts := strings.Split(options.Name, ".") + log.Debug("split", "parts", parts) + if len(parts) != 2 { + return fmt.Errorf("Invalid configuration value name: %s", options.Name) + } + + section, name := parts[0], parts[1] + + if !config.Raw.HasSection(section) { + return fmt.Errorf("`%s` section not found: %s", options.Name, section) + } + s := config.Raw.Section(section) + + s.SetOption(name, options.Value) + + return repo.SetConfig(config) +} diff --git a/config/set_test.go b/config/set_test.go new file mode 100644 index 0000000..450e6ee --- /dev/null +++ b/config/set_test.go @@ -0,0 +1,32 @@ +package config + +import ( + "github.com/go-git/go-git/v5" + "github.com/stretchr/testify/assert" + "os" + "testing" +) + +func TestSet(t *testing.T) { + assert := assert.New(t) + + dir, err := os.MkdirTemp("", "bazel-git-config-set-dir-") + assert.Nil(err) + defer os.RemoveAll(dir) + + repo, err := git.PlainInitWithOptions(dir, &git.PlainInitOptions{ + Bare: true, + }) + assert.Nil(err) + + err = Set(SetOptions{ + GitDir: dir, + Name: "user.name", + Value: "Jango Fett", + }) + assert.Nil(err) + + config, err := repo.Config() + assert.Nil(err) + assert.Equal(config.User.Name, "Jango Fett") +} -- GitLab