From 85a75fe07746eae0168546924c4f3861c3e7de5e Mon Sep 17 00:00:00 2001 From: Richard Macklin Date: Sun, 3 Mar 2024 21:18:34 -0800 Subject: [PATCH] Support `:owner/:repo` template in `repoPaths` configuration Previously, we supported a "wildcard" mapping like ``` user1/*: /path/to/user1_repos/* ``` to map any repository owned by `user1` to the directory of the same name within `/path/to/user1_repos`. But for folks who store all GitHub repositories under a path that includes the owner's name and the repo's name, this would still require them to enter a wildcard entry for every owner. To avoid that, we're introducing support for an `:owner/:repo` template in the `repoPaths` configuration. Now we can specify a `repoPaths` entry like: ``` :owner/:repo: /path/to/github.com/:owner/:repo ``` which will cover everything. It can still be overridden with individual entries that specify either an exact repository or a specific owner wildcard. In case the configured path includes the :`owner` or `:`repo substitution multiple times, we will replace all occurrences. --- README.md | 2 ++ ui/common/repopath.go | 4 ++++ ui/common/repopath_test.go | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+) diff --git a/README.md b/README.md index e9558338..1bfa92ce 100644 --- a/README.md +++ b/README.md @@ -138,6 +138,7 @@ defaults: refetchIntervalMinutes: 30 # will refetch all sections every 30 minutes repoPaths: # configure where to locate repos when checking out PRs default_path: ~/code/repos # fallback value if none of the other paths match + :owner/:repo: ~/src/github.com/:owner/:repo # template if you always clone github repos in a consistent location dlvhdr/*: ~/code/repos/dlvhdr/* # will match dlvhdr/repo-name to ~/code/repos/dlvhdr/repo-name dlvhdr/gh-dash: ~/code/gh-dash # will not match wildcard and map to specified path keybindings: # optional, define custom keybindings - see more info below @@ -216,6 +217,7 @@ An exact match for the full repo name to a full path takes priority over a match ```yaml repoPaths: default_path: ~/code/repos # fallback value if none of the other paths match + :owner/:repo: ~/src/github.com/:owner/:repo # template if you always clone github repos in a consistent location dlvhdr/*: ~/code/repos/dlvhdr/* # will match dlvhdr/repo-name to ~/code/repos/dlvhdr/repo-name dlvhdr/gh-dash: ~/code/gh-dash # will not match wildcard and map to specified path ``` diff --git a/ui/common/repopath.go b/ui/common/repopath.go index 4fee0dfc..e7aa4659 100644 --- a/ui/common/repopath.go +++ b/ui/common/repopath.go @@ -48,6 +48,10 @@ func GetRepoLocalPath(repoName string, cfgPaths map[string]string) (string, bool return fmt.Sprintf("%s/%s", strings.TrimSuffix(wildcardPath, "/*"), repo), true } + if template, ok := cfgPaths[":owner/:repo"]; ok { + return strings.ReplaceAll(strings.ReplaceAll(template, ":owner", owner), ":repo", repo), true + } + if defaultPath, found := cfgPaths["default_path"]; found { p := strings.TrimSuffix(defaultPath, "/*") return filepath.Join(p, repo), true diff --git a/ui/common/repopath_test.go b/ui/common/repopath_test.go index b6af8e68..eca0139c 100644 --- a/ui/common/repopath_test.go +++ b/ui/common/repopath_test.go @@ -19,6 +19,12 @@ var configPathsWithDefaultPath = map[string]string{ "default_path": "/path/to/user/dev", } +var configPathsWithOwnerRepoTemplate = map[string]string{ + "user/repo": "/path/to/the_repo", + "org/*": "/path/to/the_org/*", + ":owner/:repo": "/path/to/github.com/:owner/:repo", +} + func TestGetRepoLocalPath(t *testing.T) { testCases := map[string]struct { repo string @@ -56,6 +62,36 @@ func TestGetRepoLocalPath(t *testing.T) { found: true, configPaths: configPathsWithDefaultPath, }, + "with :owner/:repo template: exact match": { + repo: "user/repo", + want: "/path/to/the_repo", + found: true, + configPaths: configPathsWithOwnerRepoTemplate, + }, + "with :owner/:repo template: no match for this sibling repo": { + repo: "user/another_repo", + want: "/path/to/github.com/user/another_repo", + found: true, + configPaths: configPathsWithOwnerRepoTemplate, + }, + "with :owner/:repo template: wildcard repo match": { + repo: "org/some_repo", + want: "/path/to/the_org/some_repo", + found: true, + configPaths: configPathsWithOwnerRepoTemplate, + }, + "with :owner/:repo template: general fallback": { + repo: "any-owner/any-repo", + want: "/path/to/github.com/any-owner/any-repo", + found: true, + configPaths: configPathsWithOwnerRepoTemplate, + }, + "with :owner/:repo template: repeated :repo substitution": { + repo: "any-owner/any-repo", + want: "src/github.com/any-owner/any-repo/any-repo", + found: true, + configPaths: map[string]string{":owner/:repo": "src/github.com/:owner/:repo/:repo"}, + }, } for name, tc := range testCases {