Compare commits
20 commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 19591ad8e1 | |||
| 6323576826 | |||
| 8175f54ddd | |||
| b162228efd | |||
| d98e648dca | |||
| 959f92dea2 | |||
| 9515ec0e29 | |||
| 9ec56012c2 | |||
| 9755abdfd3 | |||
| cf3d8636e2 | |||
| 80ab07e86e | |||
| 739a3972eb | |||
| 31d313c6a9 | |||
| 74f2ebfa57 | |||
| 3a94768343 | |||
| 9f4ad8d959 | |||
| 3f84eaf185 | |||
| 0ee35feeb1 | |||
| f6983c78d0 | |||
| c3da4461fa |
16 changed files with 153 additions and 10 deletions
7
.forgejo/workflows/test.yml
Normal file
7
.forgejo/workflows/test.yml
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
on: push
|
||||||
|
jobs:
|
||||||
|
check:
|
||||||
|
runs-on: nixos
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- run: nix develop -c just test
|
||||||
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
/git-repo-updater
|
||||||
|
/result
|
||||||
20
CHANGELOG.md
20
CHANGELOG.md
|
|
@ -6,8 +6,26 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
||||||
|
|
||||||
## [Unreleased]
|
## [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
|
### Added
|
||||||
|
|
||||||
- Load a list of directories from a configuration file (`~/.config/git-repo-updater/config.yaml`).
|
- 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
|
||||||
|
|
|
||||||
23
README.md
Normal file
23
README.md
Normal file
|
|
@ -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
|
||||||
|
```
|
||||||
13
config.yaml.example
Normal file
13
config.yaml.example
Normal file
|
|
@ -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
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
packages = with pkgs; [
|
packages = with pkgs; [
|
||||||
go
|
go
|
||||||
gopls
|
gopls
|
||||||
|
just
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
11
flake-modules/packages.nix
Normal file
11
flake-modules/packages.nix
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
perSystem =
|
||||||
|
{ pkgs, ... }:
|
||||||
|
{
|
||||||
|
packages.default = pkgs.buildGoModule {
|
||||||
|
name = "git-repo-updater";
|
||||||
|
src = ../.;
|
||||||
|
vendorHash = "sha256-g+yaVIx4jxpAQ/+WrGKxhVeliYx7nLQe/zsGpxV4Fn4=";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
4
go.mod
4
go.mod
|
|
@ -1,5 +1,5 @@
|
||||||
module git-repo-updater
|
module code.oliverdavies.uk/opdavies/git-repo-updater
|
||||||
|
|
||||||
go 1.24.5
|
go 1.24.5
|
||||||
|
|
||||||
require gopkg.in/yaml.v3 v3.0.1 // indirect
|
require gopkg.in/yaml.v3 v3.0.1
|
||||||
|
|
|
||||||
1
go.sum
1
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/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 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,9 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
|
Depth string `yaml:"depth"`
|
||||||
Directories []string `yaml:"directories"`
|
Directories []string `yaml:"directories"`
|
||||||
|
IgnoredRepos []string `yaml:"ignored"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func getConfigPath() (string, error) {
|
func getConfigPath() (string, error) {
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,8 @@ import (
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"strings"
|
"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) {
|
func FindInDirectory(dir string) (string, error) {
|
||||||
|
|
@ -36,10 +37,16 @@ func FindInDirectory(dir string) (string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func splitPath(repoPath string) (string, string) {
|
func splitPath(repoPath string) (string, string) {
|
||||||
|
cfg, err := config.Load()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
parts := strings.SplitN(repoPath, ":", 2)
|
parts := strings.SplitN(repoPath, ":", 2)
|
||||||
|
|
||||||
repoPath = parts[0]
|
repoPath = parts[0]
|
||||||
depth := "2"
|
depth := cfg.Depth
|
||||||
|
|
||||||
if len(parts) == 2 {
|
if len(parts) == 2 {
|
||||||
return parts[0], parts[1]
|
return parts[0], parts[1]
|
||||||
|
|
|
||||||
|
|
@ -4,13 +4,36 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"code.oliverdavies.uk/opdavies/git-repo-updater/internal/config"
|
||||||
|
"code.oliverdavies.uk/opdavies/git-repo-updater/internal/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Update(repositoryPath string) error {
|
func Update(repositoryPath string) error {
|
||||||
|
cfg, err := config.Load()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
repositoryPath = strings.TrimSuffix(repositoryPath, "/.git")
|
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 {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to change directory to %s: %w", repositoryPath, err)
|
return fmt.Errorf("failed to change directory to %s: %w", repositoryPath, err)
|
||||||
|
|
|
||||||
26
internal/utils/path_test.go
Normal file
26
internal/utils/path_test.go
Normal file
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
5
justfile
Normal file
5
justfile
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
@default:
|
||||||
|
just --list
|
||||||
|
|
||||||
|
test:
|
||||||
|
go test ./... -v
|
||||||
4
main.go
4
main.go
|
|
@ -4,8 +4,8 @@ import (
|
||||||
"log"
|
"log"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"git-repo-updater/internal/config"
|
"code.oliverdavies.uk/opdavies/git-repo-updater/internal/config"
|
||||||
"git-repo-updater/internal/repositories"
|
"code.oliverdavies.uk/opdavies/git-repo-updater/internal/repositories"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
|
||||||
8
todo.txt
8
todo.txt
|
|
@ -1,9 +1,13 @@
|
||||||
* Load directories from a configuration file
|
* Load directories from a configuration file
|
||||||
* Update the repositories within each directory.
|
* Update the repositories within each directory.
|
||||||
* Make depth configurable per 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 unit tests.
|
||||||
Add a `--dry-run` option.
|
Add a `--dry-run` option.
|
||||||
Complete README.
|
Complete README.
|
||||||
Add Nix package.
|
Filtering repos by path at runtime?
|
||||||
|
|
||||||
|
grep -r --exclude-dir=.git TODO .
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue