diff --git a/.forgejo/workflows/test.yml b/.forgejo/workflows/test.yml new file mode 100644 index 0000000..74f9980 --- /dev/null +++ b/.forgejo/workflows/test.yml @@ -0,0 +1,7 @@ +on: push +jobs: + check: + runs-on: nixos + steps: + - uses: actions/checkout@v4 + - run: nix develop -c just test diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c858907 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/git-repo-updater +/result diff --git a/CHANGELOG.md b/CHANGELOG.md index 9d6ecad..18fec4d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,8 +6,26 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), ## [Unreleased] +Nothing yet. + +## [0.2.0] (2025-08-05) + +### Added + +- Set a default `depth` in config.yaml and remove the hard-coded value. +- Ignore repository paths using `ignores` in config.yaml. + +## Changed + +- Update module paths to my Forgejo instance (`code.oliverdavies.uk`). + +## [0.1.0] (2025-07-31) + ### Added - Load a list of directories from a configuration file (`~/.config/git-repo-updater/config.yaml`). +- Configure the depth to search in each directory by appending it to the path - e.g. (`~/Code:3`). -[unreleased]: https://code.oliverdavies.uk/opdavies/git-repo-updater/commits/branch/main +[unreleased]: https://code.oliverdavies.uk/opdavies/git-repo-updater/compare/0.2.0...main +[0.2.0]: https://code.oliverdavies.uk/opdavies/git-repo-updater/compare/0.1.0...0.2.0 +[0.1.0]: https://code.oliverdavies.uk/opdavies/git-repo-updater/releases/tag/0.1.0 diff --git a/README.md b/README.md new file mode 100644 index 0000000..6d10c35 --- /dev/null +++ b/README.md @@ -0,0 +1,23 @@ +# git-repo-updater + +`git-repo-updater` is an CLI program that finds and updates Git repositories in specified directories. + +## Configuration + +`git-repo-updater` is configurable using a configuration file at `~/.config/git-repo-updater/config.yaml`. + +For example: + +```yaml +# The number of levels to search. +depth: 3 + +# A list of directories to search in. +directories: + - ~/Code/code.oliverdavies.uk + - ~/Code/github.com + +# A list of repositories to ignore and not update. +ignored: + - ~/Code/github.com/nixos/nixpkgs +``` diff --git a/config.yaml.example b/config.yaml.example new file mode 100644 index 0000000..0ba49e3 --- /dev/null +++ b/config.yaml.example @@ -0,0 +1,13 @@ +# The default depth in each directory to search for Git repositories. +depth: 2 + +# A list of directories to search in. +directories: + - ~/Code/forgejo:3 + - ~/Code/github:3 + +# A list of repository paths to ignore (not update). +ignored: + - ~/Code/github/nixos/nixpkgs + +# vim: ft=yaml diff --git a/flake-modules/dev-shell.nix b/flake-modules/dev-shell.nix index fb61d3d..462173b 100644 --- a/flake-modules/dev-shell.nix +++ b/flake-modules/dev-shell.nix @@ -12,6 +12,7 @@ packages = with pkgs; [ go gopls + just ]; }; }; diff --git a/flake-modules/packages.nix b/flake-modules/packages.nix new file mode 100644 index 0000000..6a2cb36 --- /dev/null +++ b/flake-modules/packages.nix @@ -0,0 +1,11 @@ +{ + perSystem = + { pkgs, ... }: + { + packages.default = pkgs.buildGoModule { + name = "git-repo-updater"; + src = ../.; + vendorHash = "sha256-g+yaVIx4jxpAQ/+WrGKxhVeliYx7nLQe/zsGpxV4Fn4="; + }; + }; +} diff --git a/go.mod b/go.mod index 180b96e..06ed5e6 100644 --- a/go.mod +++ b/go.mod @@ -1,5 +1,5 @@ -module git-repo-updater +module code.oliverdavies.uk/opdavies/git-repo-updater go 1.24.5 -require gopkg.in/yaml.v3 v3.0.1 // indirect +require gopkg.in/yaml.v3 v3.0.1 diff --git a/go.sum b/go.sum index 4bc0337..a62c313 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,4 @@ +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/internal/config/config.go b/internal/config/config.go index e29a8d8..a583e90 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -9,7 +9,9 @@ import ( ) type Config struct { + Depth string `yaml:"depth"` Directories []string `yaml:"directories"` + IgnoredRepos []string `yaml:"ignored"` } func getConfigPath() (string, error) { diff --git a/internal/repositories/find.go b/internal/repositories/find.go index 73bd3dd..3db6c18 100644 --- a/internal/repositories/find.go +++ b/internal/repositories/find.go @@ -6,7 +6,8 @@ import ( "os/exec" "strings" - "git-repo-updater/internal/utils" + "code.oliverdavies.uk/opdavies/git-repo-updater/internal/config" + "code.oliverdavies.uk/opdavies/git-repo-updater/internal/utils" ) func FindInDirectory(dir string) (string, error) { @@ -36,10 +37,16 @@ func FindInDirectory(dir string) (string, error) { } func splitPath(repoPath string) (string, string) { + cfg, err := config.Load() + + if err != nil { + // TODO + } + parts := strings.SplitN(repoPath, ":", 2) repoPath = parts[0] - depth := "2" + depth := cfg.Depth if len(parts) == 2 { return parts[0], parts[1] diff --git a/internal/repositories/update.go b/internal/repositories/update.go index 920a54d..829b617 100644 --- a/internal/repositories/update.go +++ b/internal/repositories/update.go @@ -4,13 +4,36 @@ import ( "fmt" "os" "os/exec" + "slices" "strings" + + "code.oliverdavies.uk/opdavies/git-repo-updater/internal/config" + "code.oliverdavies.uk/opdavies/git-repo-updater/internal/utils" ) func Update(repositoryPath string) error { + cfg, err := config.Load() + + if err != nil { + // TODO + } + repositoryPath = strings.TrimSuffix(repositoryPath, "/.git") - err := os.Chdir(repositoryPath) + expandedIgnored := make([]string, 0, len(cfg.IgnoredRepos)) + for _, ignored := range cfg.IgnoredRepos { + if expanded, err := utils.ExpandPath(ignored); err == nil { + expandedIgnored = append(expandedIgnored, expanded) + } + } + + if slices.Contains(expandedIgnored, repositoryPath) { + fmt.Printf("Skipping %s as it's ignored\n", repositoryPath) + + return nil + } + + err = os.Chdir(repositoryPath) if err != nil { return fmt.Errorf("failed to change directory to %s: %w", repositoryPath, err) diff --git a/internal/utils/path_test.go b/internal/utils/path_test.go new file mode 100644 index 0000000..5263ec8 --- /dev/null +++ b/internal/utils/path_test.go @@ -0,0 +1,26 @@ +package utils_test + +import ( + "os" + "path/filepath" + "testing" + + "code.oliverdavies.uk/opdavies/git-repo-updater/internal/utils" +) + +func TestExpandPath(t *testing.T) { + home, _ := os.UserHomeDir() + + input := "~/Code/my-repo" + expected := filepath.Join(home, "Code/my-repo") + + result, err := utils.ExpandPath(input) + + if err != nil { + t.Errorf("ExpandPath(%q) returned error: %v", input, err) + } + + if result != expected { + t.Errorf("ExpandPath(%q) = %q; want %q", input, result, expected) + } +} diff --git a/justfile b/justfile new file mode 100644 index 0000000..6938f3b --- /dev/null +++ b/justfile @@ -0,0 +1,5 @@ +@default: + just --list + +test: + go test ./... -v diff --git a/main.go b/main.go index 0d9ebc4..b170387 100644 --- a/main.go +++ b/main.go @@ -4,8 +4,8 @@ import ( "log" "strings" - "git-repo-updater/internal/config" - "git-repo-updater/internal/repositories" + "code.oliverdavies.uk/opdavies/git-repo-updater/internal/config" + "code.oliverdavies.uk/opdavies/git-repo-updater/internal/repositories" ) func main() { diff --git a/todo.txt b/todo.txt index a085f11..7d63598 100644 --- a/todo.txt +++ b/todo.txt @@ -1,9 +1,13 @@ * Load directories from a configuration file * Update the repositories within each directory. * Make depth configurable per directory. +* Set a default depth in config.yaml. +* Add excluding/ignoring a repository. +* Add Nix package. -Set a default depth in config.yaml. Add unit tests. Add a `--dry-run` option. Complete README. -Add Nix package. +Filtering repos by path at runtime? + +grep -r --exclude-dir=.git TODO .