From 2e11fa57fadd067ae026a248e1d86b462c8d0d4c Mon Sep 17 00:00:00 2001 From: Ashok Siyani Date: Mon, 1 Jul 2024 14:00:58 +0100 Subject: [PATCH] split URL package for easy import --- pkg/{mirror => giturl}/git_url.go | 42 +++++++++---------- pkg/{mirror => giturl}/git_url_test.go | 30 ++++++------- .../git-mirror-e2e-1393286165/upstream1 | 1 - pkg/mirror/repo_pool.go | 6 ++- pkg/mirror/repository.go | 12 +++--- pkg/mirror/repository_test.go | 7 ++-- 6 files changed, 51 insertions(+), 47 deletions(-) rename pkg/{mirror => giturl}/git_url.go (83%) rename pkg/{mirror => giturl}/git_url_test.go (80%) delete mode 160000 pkg/mirror/git-mirror-e2e-1393286165/upstream1 diff --git a/pkg/mirror/git_url.go b/pkg/giturl/git_url.go similarity index 83% rename from pkg/mirror/git_url.go rename to pkg/giturl/git_url.go index 7f83a49..ddb328a 100644 --- a/pkg/mirror/git_url.go +++ b/pkg/giturl/git_url.go @@ -1,4 +1,4 @@ -package mirror +package giturl import ( "fmt" @@ -23,8 +23,8 @@ var ( localURLRgx = regexp.MustCompile(`^file:///(?P([\w\-\.]+\/)*)(?P[\w\-\.]+(\.git)?)$`) ) -// GitURL represents parsed git url -type GitURL struct { +// URL represents parsed git url +type URL struct { Scheme string // value will be either 'scp', 'ssh', 'https' or 'local' User string // might be empty for http and local urls Host string // host or host:port @@ -40,40 +40,40 @@ func NormaliseURL(rawURL string) string { return nURL } -// ParseGitURL parses a raw url into a GitURL structure. +// Parse parses a raw url into a GitURL structure. // valid git urls are... // - user@host.xz:path/to/repo.git // - ssh://user@host.xz[:port]/path/to/repo.git // - https://host.xz[:port]/path/to/repo.git -func ParseGitURL(rawURL string) (*GitURL, error) { - gURL := &GitURL{} +func Parse(rawURL string) (*URL, error) { + gURL := &URL{} rawURL = NormaliseURL(rawURL) var sections []string switch { - case isSCPURL(rawURL): + case IsSCPURL(rawURL): sections = scpURLRgx.FindStringSubmatch(rawURL) gURL.Scheme = "scp" gURL.User = sections[scpURLRgx.SubexpIndex("user")] gURL.Host = sections[scpURLRgx.SubexpIndex("host")] gURL.Path = sections[scpURLRgx.SubexpIndex("path")] gURL.Repo = sections[scpURLRgx.SubexpIndex("repo")] - case isSSHURL(rawURL): + case IsSSHURL(rawURL): sections = sshURLRgx.FindStringSubmatch(rawURL) gURL.Scheme = "ssh" gURL.User = sections[sshURLRgx.SubexpIndex("user")] gURL.Host = sections[sshURLRgx.SubexpIndex("host")] gURL.Path = sections[sshURLRgx.SubexpIndex("path")] gURL.Repo = sections[sshURLRgx.SubexpIndex("repo")] - case isHTTPSURL(rawURL): + case IsHTTPSURL(rawURL): sections = httpsURLRgx.FindStringSubmatch(rawURL) gURL.Scheme = "https" gURL.Host = sections[httpsURLRgx.SubexpIndex("host")] gURL.Path = sections[httpsURLRgx.SubexpIndex("path")] gURL.Repo = sections[httpsURLRgx.SubexpIndex("repo")] - case isLocalURL(rawURL): + case IsLocalURL(rawURL): sections = localURLRgx.FindStringSubmatch(rawURL) gURL.Scheme = "local" gURL.Path = sections[localURLRgx.SubexpIndex("path")] @@ -101,7 +101,7 @@ func ParseGitURL(rawURL string) (*GitURL, error) { // SameURL returns whether or not the two parsed git URLs are equivalent. // git URLs can be represented in multiple schemes so if host, path and repo name // of URLs are same then those URLs are for the same remote repository -func SameURL(lURL, rURL *GitURL) bool { +func SameURL(lURL, rURL *URL) bool { return lURL.Host == rURL.Host && lURL.Path == rURL.Path && lURL.Repo == rURL.Repo @@ -109,11 +109,11 @@ func SameURL(lURL, rURL *GitURL) bool { // SameRawURL returns whether or not the two remote URL strings are equivalent func SameRawURL(lRepo, rRepo string) (bool, error) { - lURL, err := ParseGitURL(lRepo) + lURL, err := Parse(lRepo) if err != nil { return false, err } - rURL, err := ParseGitURL(rRepo) + rURL, err := Parse(rRepo) if err != nil { return false, err } @@ -121,22 +121,22 @@ func SameRawURL(lRepo, rRepo string) (bool, error) { return SameURL(lURL, rURL), nil } -// isSCPURL returns true if supplied URL is scp-like syntax -func isSCPURL(rawURL string) bool { +// IsSCPURL returns true if supplied URL is scp-like syntax +func IsSCPURL(rawURL string) bool { return scpURLRgx.MatchString(rawURL) } -// isSSHURL returns true if supplied URL is SSH URL -func isSSHURL(rawURL string) bool { +// IsSSHURL returns true if supplied URL is SSH URL +func IsSSHURL(rawURL string) bool { return sshURLRgx.MatchString(rawURL) } -// isHTTPSURL returns true if supplied URL is HTTPS URL -func isHTTPSURL(rawURL string) bool { +// IsHTTPSURL returns true if supplied URL is HTTPS URL +func IsHTTPSURL(rawURL string) bool { return httpsURLRgx.MatchString(rawURL) } -// isLocalURL returns true if supplied URL is HTTPS URL -func isLocalURL(rawURL string) bool { +// IsLocalURL returns true if supplied URL is HTTPS URL +func IsLocalURL(rawURL string) bool { return localURLRgx.MatchString(rawURL) } diff --git a/pkg/mirror/git_url_test.go b/pkg/giturl/git_url_test.go similarity index 80% rename from pkg/mirror/git_url_test.go rename to pkg/giturl/git_url_test.go index 2a778f8..f34f3da 100644 --- a/pkg/mirror/git_url_test.go +++ b/pkg/giturl/git_url_test.go @@ -1,4 +1,4 @@ -package mirror +package giturl import ( "testing" @@ -11,60 +11,60 @@ func TestParseGitURL(t *testing.T) { tests := []struct { name string rawURL string - want *GitURL + want *URL wantErr bool }{ {"1", "user@host.xz:path/to/repo.git", - &GitURL{Scheme: "scp", User: "user", Host: "host.xz", Path: "path/to", Repo: "repo.git"}, + &URL{Scheme: "scp", User: "user", Host: "host.xz", Path: "path/to", Repo: "repo.git"}, false, }, {"2", "git@github.com:org/repo", - &GitURL{Scheme: "scp", User: "git", Host: "github.com", Path: "org", Repo: "repo"}, + &URL{Scheme: "scp", User: "git", Host: "github.com", Path: "org", Repo: "repo"}, false}, {"3", "ssh://user@host.xz:123/path/to/repo.git", - &GitURL{Scheme: "ssh", User: "user", Host: "host.xz:123", Path: "path/to", Repo: "repo.git"}, + &URL{Scheme: "ssh", User: "user", Host: "host.xz:123", Path: "path/to", Repo: "repo.git"}, false}, {"4", "ssh://git@github.com/org/repo", - &GitURL{Scheme: "ssh", User: "git", Host: "github.com", Path: "org", Repo: "repo"}, + &URL{Scheme: "ssh", User: "git", Host: "github.com", Path: "org", Repo: "repo"}, false}, {"5", "https://host.xz:345/path/to/repo.git", - &GitURL{Scheme: "https", Host: "host.xz:345", Path: "path/to", Repo: "repo.git"}, + &URL{Scheme: "https", Host: "host.xz:345", Path: "path/to", Repo: "repo.git"}, false}, {"6", "https://github.com/org/repo", - &GitURL{Scheme: "https", Host: "github.com", Path: "org", Repo: "repo"}, + &URL{Scheme: "https", Host: "github.com", Path: "org", Repo: "repo"}, false}, {"7", "https://host.xz:123/path/to/repo.git", - &GitURL{Scheme: "https", Host: "host.xz:123", Path: "path/to", Repo: "repo.git"}, + &URL{Scheme: "https", Host: "host.xz:123", Path: "path/to", Repo: "repo.git"}, false}, { "valid-special-char-scp", "user.name-with_@host-with_x.xz:123:path-with_.x/to/prr.test_test-repo0.git", - &GitURL{Scheme: "scp", User: "user.name-with_", Host: "host-with_x.xz:123", Path: "path-with_.x/to", Repo: "prr.test_test-repo0.git"}, + &URL{Scheme: "scp", User: "user.name-with_", Host: "host-with_x.xz:123", Path: "path-with_.x/to", Repo: "prr.test_test-repo0.git"}, false, }, { "valid-special-char-ssh", "ssh://user.name-with_@host-with_x.xz:123/path-with_.x/to/prr.test_test-repo1.git", - &GitURL{Scheme: "ssh", User: "user.name-with_", Host: "host-with_x.xz:123", Path: "path-with_.x/to", Repo: "prr.test_test-repo1.git"}, + &URL{Scheme: "ssh", User: "user.name-with_", Host: "host-with_x.xz:123", Path: "path-with_.x/to", Repo: "prr.test_test-repo1.git"}, false, }, { "valid-special-char-https", "https://host-with_x.xz:123/path-with_.x/to/prr.test_test-repo2.git", - &GitURL{Scheme: "https", Host: "host-with_x.xz:123", Path: "path-with_.x/to", Repo: "prr.test_test-repo2.git"}, + &URL{Scheme: "https", Host: "host-with_x.xz:123", Path: "path-with_.x/to", Repo: "prr.test_test-repo2.git"}, false, }, { "valid-special-char-local", "file:///path-with_.x/to/prr.test_test-repo3.git", - &GitURL{Scheme: "local", Path: "path-with_.x/to", Repo: "prr.test_test-repo3.git"}, + &URL{Scheme: "local", Path: "path-with_.x/to", Repo: "prr.test_test-repo3.git"}, false, }, @@ -97,12 +97,12 @@ func TestParseGitURL(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := ParseGitURL(tt.rawURL) + got, err := Parse(tt.rawURL) if (err != nil) != tt.wantErr { t.Errorf("ParseGitURL() error = %v, wantErr %v", err, tt.wantErr) return } - if diff := cmp.Diff(tt.want, got, cmpopts.EquateComparable(GitURL{})); diff != "" { + if diff := cmp.Diff(tt.want, got, cmpopts.EquateComparable(URL{})); diff != "" { t.Errorf("ParseGitURL() mismatch (-want +got):\n%s", diff) } }) diff --git a/pkg/mirror/git-mirror-e2e-1393286165/upstream1 b/pkg/mirror/git-mirror-e2e-1393286165/upstream1 deleted file mode 160000 index d489b70..0000000 --- a/pkg/mirror/git-mirror-e2e-1393286165/upstream1 +++ /dev/null @@ -1 +0,0 @@ -Subproject commit d489b70664219af620cc38783b02c9bc23a9c6c7 diff --git a/pkg/mirror/repo_pool.go b/pkg/mirror/repo_pool.go index 8863a67..6c60bc7 100644 --- a/pkg/mirror/repo_pool.go +++ b/pkg/mirror/repo_pool.go @@ -5,6 +5,8 @@ import ( "fmt" "log/slog" "time" + + "github.com/utilitywarehouse/git-mirror/pkg/giturl" ) var ( @@ -97,13 +99,13 @@ func (rp *RepoPool) StartLoop() { // Repository will return Repository object based on given remote URL func (rp *RepoPool) Repository(remote string) (*Repository, error) { - gitURL, err := ParseGitURL(remote) + gitURL, err := giturl.Parse(remote) if err != nil { return nil, err } for _, repo := range rp.repos { - if SameURL(repo.gitURL, gitURL) { + if giturl.SameURL(repo.gitURL, gitURL) { return repo, nil } } diff --git a/pkg/mirror/repository.go b/pkg/mirror/repository.go index 4a31605..143114e 100644 --- a/pkg/mirror/repository.go +++ b/pkg/mirror/repository.go @@ -13,6 +13,8 @@ import ( "strings" "sync" "time" + + "github.com/utilitywarehouse/git-mirror/pkg/giturl" ) const ( @@ -47,7 +49,7 @@ const ( // The implementation borrows heavily from https://github.com/kubernetes/git-sync. // A Repository is safe for concurrent use by multiple goroutines. type Repository struct { - gitURL *GitURL // parsed remote git URL + gitURL *giturl.URL // parsed remote git URL remote string // remote repo to mirror root string // absolute path to the root where repo directory createdabsolute path to the root where repo directory created dir string // absolute path to the repo directory @@ -66,9 +68,9 @@ type Repository struct { // NewRepository creates new repository from the given config. // Remote repo will not be mirrored until either Mirror() or StartLoop() is called. func NewRepository(repoConf RepositoryConfig, envs []string, log *slog.Logger) (*Repository, error) { - remoteURL := NormaliseURL(repoConf.Remote) + remoteURL := giturl.NormaliseURL(repoConf.Remote) - gURL, err := ParseGitURL(remoteURL) + gURL, err := giturl.Parse(remoteURL) if err != nil { return nil, err } @@ -506,7 +508,7 @@ func (r *Repository) init(ctx context.Context) error { // and parse output to get default branch name func (r *Repository) getRemoteDefaultBranch(ctx context.Context) (string, error) { envs := []string{} - if isSCPURL(r.remote) || isSSHURL(r.remote) { + if giturl.IsSCPURL(r.remote) || giturl.IsSSHURL(r.remote) { envs = append(envs, r.auth.gitSSHCommand()) } @@ -598,7 +600,7 @@ func (r *Repository) fetch(ctx context.Context) ([]string, error) { args := []string{"fetch", "origin", "--prune", "--no-progress", "--porcelain", "--no-auto-gc"} envs := []string{} - if isSCPURL(r.remote) || isSSHURL(r.remote) { + if giturl.IsSCPURL(r.remote) || giturl.IsSSHURL(r.remote) { envs = append(envs, r.auth.gitSSHCommand()) } diff --git a/pkg/mirror/repository_test.go b/pkg/mirror/repository_test.go index e1f307e..0399863 100644 --- a/pkg/mirror/repository_test.go +++ b/pkg/mirror/repository_test.go @@ -7,6 +7,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" + "github.com/utilitywarehouse/git-mirror/pkg/giturl" ) func TestNewRepo(t *testing.T) { @@ -33,7 +34,7 @@ func TestNewRepo(t *testing.T) { gc: "always", }, &Repository{ - gitURL: &GitURL{Scheme: "scp", User: "user", Host: "host.xz", Path: "path/to", Repo: "repo.git"}, + gitURL: &giturl.URL{Scheme: "scp", User: "user", Host: "host.xz", Path: "path/to", Repo: "repo.git"}, remote: "user@host.xz:path/to/repo.git", root: "/tmp", dir: "/tmp/repo.git", @@ -110,7 +111,7 @@ func TestNewRepo(t *testing.T) { t.Errorf("NewRepository() error = %v, wantErr %v", err, tt.wantErr) return } - if diff := cmp.Diff(tt.want, got, cmpopts.IgnoreFields(Repository{}, "log", "lock", "stop", "stopped"), cmp.AllowUnexported(Repository{}, GitURL{})); diff != "" { + if diff := cmp.Diff(tt.want, got, cmpopts.IgnoreFields(Repository{}, "log", "lock", "stop", "stopped"), cmp.AllowUnexported(Repository{}, giturl.URL{})); diff != "" { t.Errorf("NewRepository() mismatch (-want +got):\n%s", diff) } }) @@ -119,7 +120,7 @@ func TestNewRepo(t *testing.T) { func TestRepo_AddWorktreeLink(t *testing.T) { r := &Repository{ - gitURL: &GitURL{Scheme: "scp", User: "user", Host: "host.xz", Path: "path/to", Repo: "repo.git"}, + gitURL: &giturl.URL{Scheme: "scp", User: "user", Host: "host.xz", Path: "path/to", Repo: "repo.git"}, root: "/tmp/root", interval: 10 * time.Second, auth: nil,