From 7463d5f56f9d9184135509b34048715421183f94 Mon Sep 17 00:00:00 2001 From: Stefan Dillenburg Date: Thu, 8 Sep 2022 10:54:06 +0200 Subject: [PATCH] feat: search repos in a nested project structure --- README.md | 14 +++++++++---- infra/filesystem_repos.go | 41 +++++++++++++++++++++++++++++++++++---- 2 files changed, 47 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 15d6811..e94be9e 100644 --- a/README.md +++ b/README.md @@ -30,21 +30,27 @@ Download build binary from the [releases](https://github.com/suin/git-remind/rel ## Configuration -Add `remind.paths` to your `.gitconfig`, using your own absolute path to the repository directories. +Add `remind.paths` to your `.gitconfig`, using your own absolute path to the repository directories. ```text:.gitconfig [remind] paths = /Users/you/projects/foo,/Users/you/projects/bar ``` -If you have some git repositories (e.g. `~/projects/foo` and `~/projects/bar`) in the same directory (e.g. in `~/projects`) , you may specify the path using wildcard (e.g.`/Users/you/projects/*`): - +If you have some git repositories (e.g. `~/projects/foo` and `~/projects/bar`) in the same directory (e.g. in `~/projects`) , you may specify the path using wildcard (e.g. `/Users/you/projects/*`): ```text:.gitconfig [remind] paths = /Users/you/projects/* ``` +If you have a nested git repository structure (e.g. `~/projects/foobar/foo`, `~/projects/foobar/bar` and `~/projects/foo`), you may specify the path using a double asterisk (e.g. `/Users/you/projects/**`): + +```text:.gitconfig +[remind] + paths = /Users/you/projects/** +``` + You can also utilise the `git config` command to configure git-remind to avoid the manually editing of the `.gitconfig`. ```bash @@ -76,7 +82,7 @@ C /Users/suin/projects/myapp1 CP /Users/suin/projects/myapp2 ``` -#### Show all status including up-to-date repositories +#### Show all status including up-to-date repositories ``` $ git-remind status -a diff --git a/infra/filesystem_repos.go b/infra/filesystem_repos.go index e14915e..69a7031 100644 --- a/infra/filesystem_repos.go +++ b/infra/filesystem_repos.go @@ -1,9 +1,12 @@ package infra import ( - "github.com/suin/git-remind/domain" + "io/fs" "os" "path/filepath" + "strings" + + "github.com/suin/git-remind/domain" ) var FilesystemRepos domain.GetReposByPathPattern = func(patterns domain.GetPathPatterns) (repos []string, err error) { @@ -12,9 +15,17 @@ var FilesystemRepos domain.GetReposByPathPattern = func(patterns domain.GetPathP return } for _, pathPattern := range pathPatterns { - paths, err2 := filepath.Glob(string(pathPattern)) - if err2 != nil { - return repos, err2 + if strings.HasSuffix(string(pathPattern), "/**") { + path := strings.TrimSuffix(string(pathPattern), "/**") + dirs, err := searchForGitDirs(path) + if err != nil { + return repos, err + } + repos = append(repos, dirs...) + } + paths, err := filepath.Glob(string(pathPattern)) + if err != nil { + return repos, err } for _, path := range paths { isDir, _ := isDirectory(path + "/.git") @@ -33,3 +44,25 @@ func isDirectory(path string) (bool, error) { } return fileInfo.IsDir(), err } + +func searchForGitDirs(root string) ([]string, error) { + var skipPath string + var matchedPaths []string + err := filepath.WalkDir( + root, + func(path string, d fs.DirEntry, err error) error { + if err != nil { + return err + } + if d.IsDir() && d.Name() == ".git" && skipPath != path { + skipPath = path + matchedPaths = append(matchedPaths, strings.TrimSuffix(path, "/.git")) + } + return nil + }, + ) + if err != nil { + return nil, err + } + return matchedPaths, nil +}