From 74b98617063269b2e131f19d49b200f621251011 Mon Sep 17 00:00:00 2001 From: jtagcat Date: Sun, 23 Jan 2022 19:58:22 +0200 Subject: [PATCH 01/10] repo: add RemotesList() also added utils: stdoutToStringSlice() --- repo_remote.go | 28 ++++++++++++++++++++++++++++ repo_remote_test.go | 33 +++++++++++++++++++++++++++++++++ utils.go | 10 ++++++++++ 3 files changed, 71 insertions(+) diff --git a/repo_remote.go b/repo_remote.go index 06e8f51de..829c8b4d4 100644 --- a/repo_remote.go +++ b/repo_remote.go @@ -146,3 +146,31 @@ func RepoRemoveRemote(repoPath, name string, opts ...RemoveRemoteOptions) error func (r *Repository) RemoveRemote(name string, opts ...RemoveRemoteOptions) error { return RepoRemoveRemote(r.path, name, opts...) } + +// RemotesListOptions contains arguments for listing remotes of the repository. +// Docs: https://git-scm.com/docs/git-remote#_commands +type RemotesListOptions struct { + // The timeout duration before giving up for each shell command execution. + // The default timeout duration will be used when not supplied. + Timeout time.Duration +} + +// RepoRemotesList lists remotes of the repository in given path. +func RepoRemotesList(repoPath string, opts ...RemotesListOptions) ([]string, error) { + var opt RemotesListOptions + if len(opts) > 0 { + opt = opts[0] + } + + stdout, err := NewCommand("remote").RunInDirWithTimeout(opt.Timeout, repoPath) + if err != nil { + return nil, err + } + + return stdoutToStringSlice(stdout), nil +} + +// RemotesList lists remotes of the repository. +func (r *Repository) RemotesList(opts ...RemotesListOptions) ([]string, error) { + return RepoRemotesList(r.path, opts...) +} diff --git a/repo_remote_test.go b/repo_remote_test.go index 1cea3300d..a01123c2d 100644 --- a/repo_remote_test.go +++ b/repo_remote_test.go @@ -131,3 +131,36 @@ func TestRepository_RemoveRemote(t *testing.T) { err = r.RemoveRemote("origin", RemoveRemoteOptions{}) assert.Equal(t, ErrRemoteNotExist, err) } + +func TestRepository_RemotesList(t *testing.T) { + r, cleanup, err := setupTempRepo() + if err != nil { + t.Fatal(err) + } + defer cleanup() + + // 1 remote + remotes, err := r.RemotesList() + assert.Nil(t, err) + assert.Equal(t, []string{"origin"}, remotes) + + // 2 remotes + err = r.AddRemote("t", "t") + assert.Nil(t, err) + + remotes, err = r.RemotesList() + assert.Nil(t, err) + assert.Equal(t, []string{"origin", "t"}, remotes) + assert.Len(t, remotes, 2) + + // 0 remotes + err = r.RemoveRemote("t") + assert.Nil(t, err) + err = r.RemoveRemote("origin") + assert.Nil(t, err) + + remotes, err = r.RemotesList() + assert.Nil(t, err) + assert.Equal(t, []string{}, remotes) + assert.Len(t, remotes, 0) +} diff --git a/utils.go b/utils.go index 1327b05ba..551f200f3 100644 --- a/utils.go +++ b/utils.go @@ -7,6 +7,7 @@ package git import ( "fmt" "os" + "strings" "sync" ) @@ -71,3 +72,12 @@ func concatenateError(err error, stderr string) error { } return fmt.Errorf("%v - %s", err, stderr) } + +// turns "a\n\list\n" to []string{"a", "list"} +func stdoutToStringSlice(stdout []byte) []string { + o := strings.TrimRight(string(stdout), "\n") + if o == "" { // empty (not {""}, len=1) + return []string{} + } + return strings.Split(o, "\n") +} From 23cd988cdc1708b75cf6997a07da12e2caf1788d Mon Sep 17 00:00:00 2001 From: jtagcat Date: Sun, 23 Jan 2022 20:44:25 +0200 Subject: [PATCH 02/10] repo: implement remote get-url and set-url family --- error.go | 2 + repo_remote.go | 150 ++++++++++++++++++++++++++++++++++++++++++++ repo_remote_test.go | 42 +++++++++++++ 3 files changed, 194 insertions(+) diff --git a/error.go b/error.go index 6961231a7..9900ff989 100644 --- a/error.go +++ b/error.go @@ -13,7 +13,9 @@ var ( ErrSubmoduleNotExist = errors.New("submodule does not exist") ErrRevisionNotExist = errors.New("revision does not exist") ErrRemoteNotExist = errors.New("remote does not exist") + ErrURLNotExist = errors.New("URL does not exist") ErrExecTimeout = errors.New("execution was timed out") ErrNoMergeBase = errors.New("no merge based was found") ErrNotBlob = errors.New("the entry is not a blob") + ErrDelAllNonPushURL = errors.New("will not delete all non-push URLs") ) diff --git a/repo_remote.go b/repo_remote.go index 829c8b4d4..d7c6ff519 100644 --- a/repo_remote.go +++ b/repo_remote.go @@ -174,3 +174,153 @@ func RepoRemotesList(repoPath string, opts ...RemotesListOptions) ([]string, err func (r *Repository) RemotesList(opts ...RemotesListOptions) ([]string, error) { return RepoRemotesList(r.path, opts...) } + +// RemoteURLGetOptions contains arguments for retrieving URL(s) of a remote of the repository. +// Docs: https://git-scm.com/docs/git-remote#Documentation/git-remote.txt-emget-urlem +type RemoteURLGetOptions struct { + // False: get fetch URLs + // True: get push URLs + Push bool + // True: get all URLs (lists also non-main URLs; not related with Push) + All bool + // The timeout duration before giving up for each shell command execution. + // The default timeout duration will be used when not supplied. + Timeout time.Duration +} + +// RepoRemoteURLGet retrieves URL(s) of a remote of the repository in given path. +func RepoRemoteURLGet(repoPath, name string, opts ...RemoteURLGetOptions) ([]string, error) { + var opt RemoteURLGetOptions + if len(opts) > 0 { + opt = opts[0] + } + + cmd := NewCommand("remote", "get-url") + if opt.Push { + cmd.AddArgs("--push") + } + if opt.All { + cmd.AddArgs("--all") + } + + stdout, err := cmd.AddArgs(name).RunInDirWithTimeout(opt.Timeout, repoPath) + if err != nil { + return nil, err + } + return stdoutToStringSlice(stdout), nil +} + +// RemoteURLGet retrieves URL(s) of a remote of the repository in given path. +func (r *Repository) RemoteURLGet(name string, opts ...RemoteURLGetOptions) ([]string, error) { + return RepoRemoteURLGet(r.path, name, opts...) +} + +// RemoteURLSetOptions contains arguments for setting an URL of a remote of the repository. +// Docs: https://git-scm.com/docs/git-remote#Documentation/git-remote.txt-emget-urlem +type RemoteURLSetOptions struct { + // False: set fetch URLs + // True: set push URLs + Push bool + // The timeout duration before giving up for each shell command execution. + // The default timeout duration will be used when not supplied. + Timeout time.Duration +} + +// RepoRemoteURLSetFirst sets first URL of the remote with given name of the repository in given path. +func RepoRemoteURLSetFirst(repoPath, name, newurl string, opts ...RemoteURLSetOptions) error { + var opt RemoteURLSetOptions + if len(opts) > 0 { + opt = opts[0] + } + + cmd := NewCommand("remote", "set-url") + if opt.Push { + cmd.AddArgs("--push") + } + + _, err := cmd.AddArgs(name, newurl).RunInDirWithTimeout(opt.Timeout, repoPath) + if err != nil && strings.Contains(err.Error(), "No such remote") { + return ErrRemoteNotExist + } + return err +} + +// RemoteURLSetFirst sets the first URL of the remote with given name of the repository. +func (r *Repository) RemoteURLSetFirst(name, newurl string, opts ...RemoteURLSetOptions) error { + return RepoRemoteURLSetFirst(r.path, name, newurl, opts...) +} + +// RepoRemoteURLSetRegex sets the first URL of the remote with given name and URL regex match of the repository in given path. +func RepoRemoteURLSetRegex(repoPath, name, urlregex string, newurl string, opts ...RemoteURLSetOptions) error { + var opt RemoteURLSetOptions + if len(opts) > 0 { + opt = opts[0] + } + + cmd := NewCommand("remote", "set-url") + if opt.Push { + cmd.AddArgs("--push") + } + + _, err := cmd.AddArgs(name, newurl, urlregex).RunInDirWithTimeout(opt.Timeout, repoPath) + if err != nil { + if strings.Contains(err.Error(), "No such URL found") { + return ErrURLNotExist + } + if strings.Contains(err.Error(), "No such remote") { + return ErrRemoteNotExist + } + return err + } + return nil +} + +// RemoteURLSetRegex sets the first URL of the remote with given name and URL regex match of the repository. +func (r *Repository) RemoteURLSetRegex(name, urlregex, newurl string, opts ...RemoteURLSetOptions) error { + return RepoRemoteURLSetRegex(r.path, name, urlregex, newurl, opts...) +} + +// RepoRemoteURLAdd adds an URL to the remote with given name of the repository in given path. +func RepoRemoteURLAdd(repoPath, name, newurl string, opts ...RemoteURLSetOptions) error { + var opt RemoteURLSetOptions + if len(opts) > 0 { + opt = opts[0] + } + + cmd := NewCommand("remote", "set-url", "--add") + if opt.Push { + cmd.AddArgs("--push") + } + + _, err := cmd.AddArgs(name, newurl).RunInDirWithTimeout(opt.Timeout, repoPath) + return err +} + +// RemoteURLAdd adds an URL to the remote with given name of the repository. +func (r *Repository) RemoteURLAdd(name, newvalue string, opts ...RemoteURLSetOptions) error { + return RepoRemoteURLAdd(r.path, name, newvalue, opts...) +} + +// RepoRemoteURLDelRegex Deletes all URLs matchin regex of the remote with given name of the repository in given path. +func RepoRemoteURLDelRegex(repoPath, name, urlregex string, opts ...RemoteURLSetOptions) error { + var opt RemoteURLSetOptions + if len(opts) > 0 { + opt = opts[0] + } + + cmd := NewCommand("remote", "set-url", "--delete") + if opt.Push { + cmd.AddArgs("--push") + } + + _, err := cmd.AddArgs(name, urlregex).RunInDirWithTimeout(opt.Timeout, repoPath) + if err != nil && strings.Contains(err.Error(), "Will not delete all non-push URLs") { + return ErrDelAllNonPushURL + } + return err +} + +// RemoteURLDelRegex // RepoRemoteURLDelRegex Deletes all URLs matchin regex of the remote with given name of the repository. +func (r *Repository) RemoteURLDelRegex(name, urlregex string, opts ...RemoteURLSetOptions) error { + return RepoRemoteURLDelRegex(r.path, name, urlregex, opts...) +} diff --git a/repo_remote_test.go b/repo_remote_test.go index a01123c2d..d3bd29414 100644 --- a/repo_remote_test.go +++ b/repo_remote_test.go @@ -164,3 +164,45 @@ func TestRepository_RemotesList(t *testing.T) { assert.Equal(t, []string{}, remotes) assert.Len(t, remotes, 0) } + +func TestRepository_RemoteURLFamily(t *testing.T) { + r, cleanup, err := setupTempRepo() + if err != nil { + t.Fatal(err) + } + defer cleanup() + + err = r.RemoteURLDelRegex("origin", ".*") + assert.Equal(t, ErrDelAllNonPushURL, err) + + err = r.RemoteURLSetFirst("notexist", "t") + assert.Equal(t, ErrRemoteNotExist, err) + + err = r.RemoteURLSetRegex("notexist", "t", "t") + assert.Equal(t, ErrRemoteNotExist, err) + + // default origin URL is not easily testable + err = r.RemoteURLSetFirst("origin", "t") + assert.Nil(t, err) + URLs, err := r.RemoteURLGet("origin") + assert.Nil(t, err) + assert.Equal(t, []string{"t"}, URLs) + + err = r.RemoteURLAdd("origin", "e") + assert.Nil(t, err) + URLs, err = r.RemoteURLGet("origin", RemoteURLGetOptions{All: true}) + assert.Nil(t, err) + assert.Equal(t, []string{"t", "e"}, URLs) + + err = r.RemoteURLSetRegex("origin", "e", "s") + assert.Nil(t, err) + URLs, err = r.RemoteURLGet("origin", RemoteURLGetOptions{All: true}) + assert.Nil(t, err) + assert.Equal(t, []string{"t", "s"}, URLs) + + err = r.RemoteURLDelRegex("origin", "t") + assert.Nil(t, err) + URLs, err = r.RemoteURLGet("origin", RemoteURLGetOptions{All: true}) + assert.Nil(t, err) + assert.Equal(t, []string{"s"}, URLs) +} From 2765e5ad82a6f23f3decd8cc03687fcf798f845c Mon Sep 17 00:00:00 2001 From: jtagcat Date: Fri, 11 Feb 2022 18:16:05 +0200 Subject: [PATCH 03/10] suggestions --- repo_remote.go | 21 ++++++++++----------- repo_remote_test.go | 6 +++--- utils.go | 11 ++++++----- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/repo_remote.go b/repo_remote.go index d7c6ff519..c3e75a2c2 100644 --- a/repo_remote.go +++ b/repo_remote.go @@ -155,8 +155,8 @@ type RemotesListOptions struct { Timeout time.Duration } -// RepoRemotesList lists remotes of the repository in given path. -func RepoRemotesList(repoPath string, opts ...RemotesListOptions) ([]string, error) { +// RepoRemotes lists remotes of the repository in given path. +func RepoRemotes(repoPath string, opts ...RemotesListOptions) ([]string, error) { var opt RemotesListOptions if len(opts) > 0 { opt = opts[0] @@ -167,19 +167,18 @@ func RepoRemotesList(repoPath string, opts ...RemotesListOptions) ([]string, err return nil, err } - return stdoutToStringSlice(stdout), nil + return bytesToStrings(stdout), nil } -// RemotesList lists remotes of the repository. -func (r *Repository) RemotesList(opts ...RemotesListOptions) ([]string, error) { - return RepoRemotesList(r.path, opts...) +// Remotes lists remotes of the repository. +func (r *Repository) Remotes(opts ...RemotesListOptions) ([]string, error) { + return RepoRemotes(r.path, opts...) } // RemoteURLGetOptions contains arguments for retrieving URL(s) of a remote of the repository. // Docs: https://git-scm.com/docs/git-remote#Documentation/git-remote.txt-emget-urlem type RemoteURLGetOptions struct { - // False: get fetch URLs - // True: get push URLs + // Indicates whether to get push URLs instead of fetch URLs. Push bool // True: get all URLs (lists also non-main URLs; not related with Push) All bool @@ -207,7 +206,7 @@ func RepoRemoteURLGet(repoPath, name string, opts ...RemoteURLGetOptions) ([]str if err != nil { return nil, err } - return stdoutToStringSlice(stdout), nil + return bytesToStrings(stdout), nil } // RemoteURLGet retrieves URL(s) of a remote of the repository in given path. @@ -301,7 +300,7 @@ func (r *Repository) RemoteURLAdd(name, newvalue string, opts ...RemoteURLSetOpt return RepoRemoteURLAdd(r.path, name, newvalue, opts...) } -// RepoRemoteURLDelRegex Deletes all URLs matchin regex of the remote with given name of the repository in given path. +// RepoRemoteURLDelRegex deletes all URLs matching regex of the remote with given name of the repository in given path. func RepoRemoteURLDelRegex(repoPath, name, urlregex string, opts ...RemoteURLSetOptions) error { var opt RemoteURLSetOptions if len(opts) > 0 { @@ -320,7 +319,7 @@ func RepoRemoteURLDelRegex(repoPath, name, urlregex string, opts ...RemoteURLSet return err } -// RemoteURLDelRegex // RepoRemoteURLDelRegex Deletes all URLs matchin regex of the remote with given name of the repository. +// RemoteURLDelRegex deletes all URLs matching regex of the remote with given name of the repository. func (r *Repository) RemoteURLDelRegex(name, urlregex string, opts ...RemoteURLSetOptions) error { return RepoRemoteURLDelRegex(r.path, name, urlregex, opts...) } diff --git a/repo_remote_test.go b/repo_remote_test.go index d3bd29414..ecc5e01cb 100644 --- a/repo_remote_test.go +++ b/repo_remote_test.go @@ -140,7 +140,7 @@ func TestRepository_RemotesList(t *testing.T) { defer cleanup() // 1 remote - remotes, err := r.RemotesList() + remotes, err := r.Remotes() assert.Nil(t, err) assert.Equal(t, []string{"origin"}, remotes) @@ -148,7 +148,7 @@ func TestRepository_RemotesList(t *testing.T) { err = r.AddRemote("t", "t") assert.Nil(t, err) - remotes, err = r.RemotesList() + remotes, err = r.Remotes() assert.Nil(t, err) assert.Equal(t, []string{"origin", "t"}, remotes) assert.Len(t, remotes, 2) @@ -159,7 +159,7 @@ func TestRepository_RemotesList(t *testing.T) { err = r.RemoveRemote("origin") assert.Nil(t, err) - remotes, err = r.RemotesList() + remotes, err = r.Remotes() assert.Nil(t, err) assert.Equal(t, []string{}, remotes) assert.Len(t, remotes, 0) diff --git a/utils.go b/utils.go index 551f200f3..22b7a06c7 100644 --- a/utils.go +++ b/utils.go @@ -73,11 +73,12 @@ func concatenateError(err error, stderr string) error { return fmt.Errorf("%v - %s", err, stderr) } -// turns "a\n\list\n" to []string{"a", "list"} -func stdoutToStringSlice(stdout []byte) []string { - o := strings.TrimRight(string(stdout), "\n") - if o == "" { // empty (not {""}, len=1) +// bytesToStrings splits given bytes into strings by line separator ("\n"). +// It returns empty slice if the given bytes only contains line separators. +func bytesToStrings(in []byte) []string { + s := strings.TrimRight(string(in), "\n") + if s == "" { // empty (not {""}, len=1) return []string{} } - return strings.Split(o, "\n") + return strings.Split(s, "\n") } From 9a7ef77fedf2fb4cde21d70666e9b58ed42e793e Mon Sep 17 00:00:00 2001 From: jtagcat Date: Thu, 24 Feb 2022 22:18:56 +0200 Subject: [PATCH 04/10] suggs 2 --- repo_remote.go | 61 ++++++++++++++++++++++----------------------- repo_remote_test.go | 16 ++++++------ 2 files changed, 38 insertions(+), 39 deletions(-) diff --git a/repo_remote.go b/repo_remote.go index c3e75a2c2..0511b0987 100644 --- a/repo_remote.go +++ b/repo_remote.go @@ -175,21 +175,21 @@ func (r *Repository) Remotes(opts ...RemotesListOptions) ([]string, error) { return RepoRemotes(r.path, opts...) } -// RemoteURLGetOptions contains arguments for retrieving URL(s) of a remote of the repository. +// RemoteGetURLOptions contains arguments for retrieving URL(s) of a remote of the repository. // Docs: https://git-scm.com/docs/git-remote#Documentation/git-remote.txt-emget-urlem -type RemoteURLGetOptions struct { +type RemoteGetURLOptions struct { // Indicates whether to get push URLs instead of fetch URLs. Push bool - // True: get all URLs (lists also non-main URLs; not related with Push) + // get all URLs: also lists non-main/default URLs for fetch OR push (not related with Push) All bool // The timeout duration before giving up for each shell command execution. // The default timeout duration will be used when not supplied. Timeout time.Duration } -// RepoRemoteURLGet retrieves URL(s) of a remote of the repository in given path. -func RepoRemoteURLGet(repoPath, name string, opts ...RemoteURLGetOptions) ([]string, error) { - var opt RemoteURLGetOptions +// RepoRemoteGetURL retrieves URL(s) of a remote of the repository in given path. +func RepoRemoteGetURL(repoPath, name string, opts ...RemoteGetURLOptions) ([]string, error) { + var opt RemoteGetURLOptions if len(opts) > 0 { opt = opts[0] } @@ -209,25 +209,24 @@ func RepoRemoteURLGet(repoPath, name string, opts ...RemoteURLGetOptions) ([]str return bytesToStrings(stdout), nil } -// RemoteURLGet retrieves URL(s) of a remote of the repository in given path. -func (r *Repository) RemoteURLGet(name string, opts ...RemoteURLGetOptions) ([]string, error) { - return RepoRemoteURLGet(r.path, name, opts...) +// RemoteGetURL retrieves URL(s) of a remote of the repository in given path. +func (r *Repository) RemoteGetURL(name string, opts ...RemoteGetURLOptions) ([]string, error) { + return RepoRemoteGetURL(r.path, name, opts...) } -// RemoteURLSetOptions contains arguments for setting an URL of a remote of the repository. +// RemoteSetURLOptions contains arguments for setting an URL of a remote of the repository. // Docs: https://git-scm.com/docs/git-remote#Documentation/git-remote.txt-emget-urlem -type RemoteURLSetOptions struct { - // False: set fetch URLs - // True: set push URLs +type RemoteSetURLOptions struct { + // Indicates whether to get push URLs instead of fetch URLs. Push bool // The timeout duration before giving up for each shell command execution. // The default timeout duration will be used when not supplied. Timeout time.Duration } -// RepoRemoteURLSetFirst sets first URL of the remote with given name of the repository in given path. -func RepoRemoteURLSetFirst(repoPath, name, newurl string, opts ...RemoteURLSetOptions) error { - var opt RemoteURLSetOptions +// RepoRemoteSetURL sets first URL of the remote with given name of the repository in given path. +func RepoRemoteSetURL(repoPath, name, newurl string, opts ...RemoteSetURLOptions) error { + var opt RemoteSetURLOptions if len(opts) > 0 { opt = opts[0] } @@ -244,14 +243,14 @@ func RepoRemoteURLSetFirst(repoPath, name, newurl string, opts ...RemoteURLSetOp return err } -// RemoteURLSetFirst sets the first URL of the remote with given name of the repository. -func (r *Repository) RemoteURLSetFirst(name, newurl string, opts ...RemoteURLSetOptions) error { - return RepoRemoteURLSetFirst(r.path, name, newurl, opts...) +// RemoteSetURL sets the first URL of the remote with given name of the repository. +func (r *Repository) RemoteSetURL(name, newurl string, opts ...RemoteSetURLOptions) error { + return RepoRemoteSetURL(r.path, name, newurl, opts...) } -// RepoRemoteURLSetRegex sets the first URL of the remote with given name and URL regex match of the repository in given path. -func RepoRemoteURLSetRegex(repoPath, name, urlregex string, newurl string, opts ...RemoteURLSetOptions) error { - var opt RemoteURLSetOptions +// RepoRemoteSetURLRegex sets the first URL of the remote with given name and URL regex match of the repository in given path. +func RepoRemoteSetURLRegex(repoPath, name, urlregex string, newurl string, opts ...RemoteSetURLOptions) error { + var opt RemoteSetURLOptions if len(opts) > 0 { opt = opts[0] } @@ -274,14 +273,14 @@ func RepoRemoteURLSetRegex(repoPath, name, urlregex string, newurl string, opts return nil } -// RemoteURLSetRegex sets the first URL of the remote with given name and URL regex match of the repository. -func (r *Repository) RemoteURLSetRegex(name, urlregex, newurl string, opts ...RemoteURLSetOptions) error { - return RepoRemoteURLSetRegex(r.path, name, urlregex, newurl, opts...) +// RemoteSetURLRegex sets the first URL of the remote with given name and URL regex match of the repository. +func (r *Repository) RemoteSetURLRegex(name, urlregex, newurl string, opts ...RemoteSetURLOptions) error { + return RepoRemoteSetURLRegex(r.path, name, urlregex, newurl, opts...) } // RepoRemoteURLAdd adds an URL to the remote with given name of the repository in given path. -func RepoRemoteURLAdd(repoPath, name, newurl string, opts ...RemoteURLSetOptions) error { - var opt RemoteURLSetOptions +func RepoRemoteURLAdd(repoPath, name, newurl string, opts ...RemoteSetURLOptions) error { + var opt RemoteSetURLOptions if len(opts) > 0 { opt = opts[0] } @@ -296,13 +295,13 @@ func RepoRemoteURLAdd(repoPath, name, newurl string, opts ...RemoteURLSetOptions } // RemoteURLAdd adds an URL to the remote with given name of the repository. -func (r *Repository) RemoteURLAdd(name, newvalue string, opts ...RemoteURLSetOptions) error { +func (r *Repository) RemoteURLAdd(name, newvalue string, opts ...RemoteSetURLOptions) error { return RepoRemoteURLAdd(r.path, name, newvalue, opts...) } // RepoRemoteURLDelRegex deletes all URLs matching regex of the remote with given name of the repository in given path. -func RepoRemoteURLDelRegex(repoPath, name, urlregex string, opts ...RemoteURLSetOptions) error { - var opt RemoteURLSetOptions +func RepoRemoteURLDelRegex(repoPath, name, urlregex string, opts ...RemoteSetURLOptions) error { + var opt RemoteSetURLOptions if len(opts) > 0 { opt = opts[0] } @@ -320,6 +319,6 @@ func RepoRemoteURLDelRegex(repoPath, name, urlregex string, opts ...RemoteURLSet } // RemoteURLDelRegex deletes all URLs matching regex of the remote with given name of the repository. -func (r *Repository) RemoteURLDelRegex(name, urlregex string, opts ...RemoteURLSetOptions) error { +func (r *Repository) RemoteURLDelRegex(name, urlregex string, opts ...RemoteSetURLOptions) error { return RepoRemoteURLDelRegex(r.path, name, urlregex, opts...) } diff --git a/repo_remote_test.go b/repo_remote_test.go index ecc5e01cb..5c722a6eb 100644 --- a/repo_remote_test.go +++ b/repo_remote_test.go @@ -175,34 +175,34 @@ func TestRepository_RemoteURLFamily(t *testing.T) { err = r.RemoteURLDelRegex("origin", ".*") assert.Equal(t, ErrDelAllNonPushURL, err) - err = r.RemoteURLSetFirst("notexist", "t") + err = r.RemoteSetURL("notexist", "t") assert.Equal(t, ErrRemoteNotExist, err) - err = r.RemoteURLSetRegex("notexist", "t", "t") + err = r.RemoteSetURLRegex("notexist", "t", "t") assert.Equal(t, ErrRemoteNotExist, err) // default origin URL is not easily testable - err = r.RemoteURLSetFirst("origin", "t") + err = r.RemoteSetURL("origin", "t") assert.Nil(t, err) - URLs, err := r.RemoteURLGet("origin") + URLs, err := r.RemoteGetURL("origin") assert.Nil(t, err) assert.Equal(t, []string{"t"}, URLs) err = r.RemoteURLAdd("origin", "e") assert.Nil(t, err) - URLs, err = r.RemoteURLGet("origin", RemoteURLGetOptions{All: true}) + URLs, err = r.RemoteGetURL("origin", RemoteGetURLOptions{All: true}) assert.Nil(t, err) assert.Equal(t, []string{"t", "e"}, URLs) - err = r.RemoteURLSetRegex("origin", "e", "s") + err = r.RemoteSetURLRegex("origin", "e", "s") assert.Nil(t, err) - URLs, err = r.RemoteURLGet("origin", RemoteURLGetOptions{All: true}) + URLs, err = r.RemoteGetURL("origin", RemoteGetURLOptions{All: true}) assert.Nil(t, err) assert.Equal(t, []string{"t", "s"}, URLs) err = r.RemoteURLDelRegex("origin", "t") assert.Nil(t, err) - URLs, err = r.RemoteURLGet("origin", RemoteURLGetOptions{All: true}) + URLs, err = r.RemoteGetURL("origin", RemoteGetURLOptions{All: true}) assert.Nil(t, err) assert.Equal(t, []string{"s"}, URLs) } From a0a5863330d6b639eb5dcc7db9f72eb208722b2a Mon Sep 17 00:00:00 2001 From: Joe Chen Date: Fri, 25 Feb 2022 10:58:23 +0800 Subject: [PATCH 05/10] Update repo_remote.go --- repo_remote.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/repo_remote.go b/repo_remote.go index 0511b0987..92aad3b30 100644 --- a/repo_remote.go +++ b/repo_remote.go @@ -180,7 +180,7 @@ func (r *Repository) Remotes(opts ...RemotesListOptions) ([]string, error) { type RemoteGetURLOptions struct { // Indicates whether to get push URLs instead of fetch URLs. Push bool - // get all URLs: also lists non-main/default URLs for fetch OR push (not related with Push) + // Indicates whether to get all URLs, including lists that are not part of main URLs. This option is independent of the Push option. All bool // The timeout duration before giving up for each shell command execution. // The default timeout duration will be used when not supplied. From 1e5f3c2bcf7372b64c99e62a974e909a9d73cbe2 Mon Sep 17 00:00:00 2001 From: Joe Chen Date: Fri, 25 Feb 2022 11:37:31 +0800 Subject: [PATCH 06/10] Tidy up code --- error.go | 18 +++--- repo_remote.go | 134 +++++++++++++++++++++----------------------- repo_remote_test.go | 30 +++++----- 3 files changed, 88 insertions(+), 94 deletions(-) diff --git a/error.go b/error.go index 9900ff989..dbbf7769b 100644 --- a/error.go +++ b/error.go @@ -9,13 +9,13 @@ import ( ) var ( - ErrParentNotExist = errors.New("parent does not exist") - ErrSubmoduleNotExist = errors.New("submodule does not exist") - ErrRevisionNotExist = errors.New("revision does not exist") - ErrRemoteNotExist = errors.New("remote does not exist") - ErrURLNotExist = errors.New("URL does not exist") - ErrExecTimeout = errors.New("execution was timed out") - ErrNoMergeBase = errors.New("no merge based was found") - ErrNotBlob = errors.New("the entry is not a blob") - ErrDelAllNonPushURL = errors.New("will not delete all non-push URLs") + ErrParentNotExist = errors.New("parent does not exist") + ErrSubmoduleNotExist = errors.New("submodule does not exist") + ErrRevisionNotExist = errors.New("revision does not exist") + ErrRemoteNotExist = errors.New("remote does not exist") + ErrURLNotExist = errors.New("URL does not exist") + ErrExecTimeout = errors.New("execution was timed out") + ErrNoMergeBase = errors.New("no merge based was found") + ErrNotBlob = errors.New("the entry is not a blob") + ErrNotDeleteNonPushURLs = errors.New("will not delete all non-push URLs") ) diff --git a/repo_remote.go b/repo_remote.go index 92aad3b30..85016cfef 100644 --- a/repo_remote.go +++ b/repo_remote.go @@ -147,17 +147,17 @@ func (r *Repository) RemoveRemote(name string, opts ...RemoveRemoteOptions) erro return RepoRemoveRemote(r.path, name, opts...) } -// RemotesListOptions contains arguments for listing remotes of the repository. +// RemotesOptions contains arguments for listing remotes of the repository. // Docs: https://git-scm.com/docs/git-remote#_commands -type RemotesListOptions struct { +type RemotesOptions struct { // The timeout duration before giving up for each shell command execution. // The default timeout duration will be used when not supplied. Timeout time.Duration } -// RepoRemotes lists remotes of the repository in given path. -func RepoRemotes(repoPath string, opts ...RemotesListOptions) ([]string, error) { - var opt RemotesListOptions +// Remotes lists remotes of the repository in given path. +func Remotes(repoPath string, opts ...RemotesOptions) ([]string, error) { + var opt RemotesOptions if len(opts) > 0 { opt = opts[0] } @@ -171,24 +171,27 @@ func RepoRemotes(repoPath string, opts ...RemotesListOptions) ([]string, error) } // Remotes lists remotes of the repository. -func (r *Repository) Remotes(opts ...RemotesListOptions) ([]string, error) { - return RepoRemotes(r.path, opts...) +func (r *Repository) Remotes(opts ...RemotesOptions) ([]string, error) { + return Remotes(r.path, opts...) } -// RemoteGetURLOptions contains arguments for retrieving URL(s) of a remote of the repository. +// RemoteGetURLOptions contains arguments for retrieving URL(s) of a remote of +// the repository. +// // Docs: https://git-scm.com/docs/git-remote#Documentation/git-remote.txt-emget-urlem type RemoteGetURLOptions struct { // Indicates whether to get push URLs instead of fetch URLs. Push bool - // Indicates whether to get all URLs, including lists that are not part of main URLs. This option is independent of the Push option. + // Indicates whether to get all URLs, including lists that are not part of main + // URLs. This option is independent of the Push option. All bool // The timeout duration before giving up for each shell command execution. // The default timeout duration will be used when not supplied. Timeout time.Duration } -// RepoRemoteGetURL retrieves URL(s) of a remote of the repository in given path. -func RepoRemoteGetURL(repoPath, name string, opts ...RemoteGetURLOptions) ([]string, error) { +// RemoteGetURL retrieves URL(s) of a remote of the repository in given path. +func RemoteGetURL(repoPath, name string, opts ...RemoteGetURLOptions) ([]string, error) { var opt RemoteGetURLOptions if len(opts) > 0 { opt = opts[0] @@ -211,61 +214,51 @@ func RepoRemoteGetURL(repoPath, name string, opts ...RemoteGetURLOptions) ([]str // RemoteGetURL retrieves URL(s) of a remote of the repository in given path. func (r *Repository) RemoteGetURL(name string, opts ...RemoteGetURLOptions) ([]string, error) { - return RepoRemoteGetURL(r.path, name, opts...) + return RemoteGetURL(r.path, name, opts...) } -// RemoteSetURLOptions contains arguments for setting an URL of a remote of the repository. -// Docs: https://git-scm.com/docs/git-remote#Documentation/git-remote.txt-emget-urlem +// RemoteSetURLOptions contains arguments for setting an URL of a remote of the +// repository. +// +// Docs: https://git-scm.com/docs/git-remote#Documentation/git-remote.txt-emset-urlem type RemoteSetURLOptions struct { + // Indicates whether to add a new URL. + Add bool // Indicates whether to get push URLs instead of fetch URLs. Push bool + // The regex to match existing URLs. + Regex string // The timeout duration before giving up for each shell command execution. // The default timeout duration will be used when not supplied. Timeout time.Duration } -// RepoRemoteSetURL sets first URL of the remote with given name of the repository in given path. -func RepoRemoteSetURL(repoPath, name, newurl string, opts ...RemoteSetURLOptions) error { +// RemoteSetURL sets first URL of the remote with given name of the repository in given path. +func RemoteSetURL(repoPath, name, newurl string, opts ...RemoteSetURLOptions) error { var opt RemoteSetURLOptions if len(opts) > 0 { opt = opts[0] } cmd := NewCommand("remote", "set-url") + if opt.Add { + cmd.AddArgs("--add") + } if opt.Push { cmd.AddArgs("--push") } - _, err := cmd.AddArgs(name, newurl).RunInDirWithTimeout(opt.Timeout, repoPath) - if err != nil && strings.Contains(err.Error(), "No such remote") { - return ErrRemoteNotExist - } - return err -} + cmd.AddArgs(name, newurl) -// RemoteSetURL sets the first URL of the remote with given name of the repository. -func (r *Repository) RemoteSetURL(name, newurl string, opts ...RemoteSetURLOptions) error { - return RepoRemoteSetURL(r.path, name, newurl, opts...) -} - -// RepoRemoteSetURLRegex sets the first URL of the remote with given name and URL regex match of the repository in given path. -func RepoRemoteSetURLRegex(repoPath, name, urlregex string, newurl string, opts ...RemoteSetURLOptions) error { - var opt RemoteSetURLOptions - if len(opts) > 0 { - opt = opts[0] - } - - cmd := NewCommand("remote", "set-url") - if opt.Push { - cmd.AddArgs("--push") + if opt.Regex != "" { + cmd.AddArgs(opt.Regex) } - _, err := cmd.AddArgs(name, newurl, urlregex).RunInDirWithTimeout(opt.Timeout, repoPath) + _, err := cmd.RunInDirWithTimeout(opt.Timeout, repoPath) if err != nil { if strings.Contains(err.Error(), "No such URL found") { return ErrURLNotExist - } - if strings.Contains(err.Error(), "No such remote") { + } else if strings.Contains(err.Error(), "No such remote") { return ErrRemoteNotExist } return err @@ -273,35 +266,29 @@ func RepoRemoteSetURLRegex(repoPath, name, urlregex string, newurl string, opts return nil } -// RemoteSetURLRegex sets the first URL of the remote with given name and URL regex match of the repository. -func (r *Repository) RemoteSetURLRegex(name, urlregex, newurl string, opts ...RemoteSetURLOptions) error { - return RepoRemoteSetURLRegex(r.path, name, urlregex, newurl, opts...) -} - -// RepoRemoteURLAdd adds an URL to the remote with given name of the repository in given path. -func RepoRemoteURLAdd(repoPath, name, newurl string, opts ...RemoteSetURLOptions) error { - var opt RemoteSetURLOptions - if len(opts) > 0 { - opt = opts[0] - } - - cmd := NewCommand("remote", "set-url", "--add") - if opt.Push { - cmd.AddArgs("--push") - } - - _, err := cmd.AddArgs(name, newurl).RunInDirWithTimeout(opt.Timeout, repoPath) - return err +// RemoteSetURL sets the first URL of the remote with given name of the repository. +func (r *Repository) RemoteSetURL(name, newurl string, opts ...RemoteSetURLOptions) error { + return RemoteSetURL(r.path, name, newurl, opts...) } -// RemoteURLAdd adds an URL to the remote with given name of the repository. -func (r *Repository) RemoteURLAdd(name, newvalue string, opts ...RemoteSetURLOptions) error { - return RepoRemoteURLAdd(r.path, name, newvalue, opts...) +// RemoteSetURLDeleteOptions contains arguments for deleting an URL of a remote +// of the repository. +// +// Docs: https://git-scm.com/docs/git-remote#Documentation/git-remote.txt-emset-urlem +type RemoteSetURLDeleteOptions struct { + // Indicates whether to get push URLs instead of fetch URLs. + Push bool + // The regex to match existing URLs. + Regex string + // The timeout duration before giving up for each shell command execution. + // The default timeout duration will be used when not supplied. + Timeout time.Duration } -// RepoRemoteURLDelRegex deletes all URLs matching regex of the remote with given name of the repository in given path. -func RepoRemoteURLDelRegex(repoPath, name, urlregex string, opts ...RemoteSetURLOptions) error { - var opt RemoteSetURLOptions +// RemoteSetURLDelete deletes the remote with given name of the repository in +// given path. +func RemoteSetURLDelete(repoPath, name string, opts ...RemoteSetURLDeleteOptions) error { + var opt RemoteSetURLDeleteOptions if len(opts) > 0 { opt = opts[0] } @@ -311,14 +298,21 @@ func RepoRemoteURLDelRegex(repoPath, name, urlregex string, opts ...RemoteSetURL cmd.AddArgs("--push") } - _, err := cmd.AddArgs(name, urlregex).RunInDirWithTimeout(opt.Timeout, repoPath) + cmd.AddArgs(name) + + if opt.Regex != "" { + cmd.AddArgs(opt.Regex) + } + + _, err := cmd.RunInDirWithTimeout(opt.Timeout, repoPath) if err != nil && strings.Contains(err.Error(), "Will not delete all non-push URLs") { - return ErrDelAllNonPushURL + return ErrNotDeleteNonPushURLs } return err } -// RemoteURLDelRegex deletes all URLs matching regex of the remote with given name of the repository. -func (r *Repository) RemoteURLDelRegex(name, urlregex string, opts ...RemoteSetURLOptions) error { - return RepoRemoteURLDelRegex(r.path, name, urlregex, opts...) +// RemoteSetURLDelete deletes all URLs matching regex of the remote with given +// name of the repository. +func (r *Repository) RemoteSetURLDelete(name string, opts ...RemoteSetURLDeleteOptions) error { + return RemoteSetURLDelete(r.path, name, opts...) } diff --git a/repo_remote_test.go b/repo_remote_test.go index 5c722a6eb..4fa482d8c 100644 --- a/repo_remote_test.go +++ b/repo_remote_test.go @@ -172,37 +172,37 @@ func TestRepository_RemoteURLFamily(t *testing.T) { } defer cleanup() - err = r.RemoteURLDelRegex("origin", ".*") - assert.Equal(t, ErrDelAllNonPushURL, err) + err = r.RemoteSetURLDelete("origin", RemoteSetURLDeleteOptions{Regex: ".*"}) + assert.Equal(t, ErrNotDeleteNonPushURLs, err) err = r.RemoteSetURL("notexist", "t") assert.Equal(t, ErrRemoteNotExist, err) - err = r.RemoteSetURLRegex("notexist", "t", "t") + err = r.RemoteSetURL("notexist", "t", RemoteSetURLOptions{Regex: "t"}) assert.Equal(t, ErrRemoteNotExist, err) - // default origin URL is not easily testable + // Default origin URL is not easily testable err = r.RemoteSetURL("origin", "t") assert.Nil(t, err) - URLs, err := r.RemoteGetURL("origin") + urls, err := r.RemoteGetURL("origin") assert.Nil(t, err) - assert.Equal(t, []string{"t"}, URLs) + assert.Equal(t, []string{"t"}, urls) - err = r.RemoteURLAdd("origin", "e") + err = r.RemoteSetURL("origin", "e", RemoteSetURLOptions{Add: true}) assert.Nil(t, err) - URLs, err = r.RemoteGetURL("origin", RemoteGetURLOptions{All: true}) + urls, err = r.RemoteGetURL("origin", RemoteGetURLOptions{All: true}) assert.Nil(t, err) - assert.Equal(t, []string{"t", "e"}, URLs) + assert.Equal(t, []string{"t", "e"}, urls) - err = r.RemoteSetURLRegex("origin", "e", "s") + err = r.RemoteSetURL("origin", "s", RemoteSetURLOptions{Regex: "e"}) assert.Nil(t, err) - URLs, err = r.RemoteGetURL("origin", RemoteGetURLOptions{All: true}) + urls, err = r.RemoteGetURL("origin", RemoteGetURLOptions{All: true}) assert.Nil(t, err) - assert.Equal(t, []string{"t", "s"}, URLs) + assert.Equal(t, []string{"t", "s"}, urls) - err = r.RemoteURLDelRegex("origin", "t") + err = r.RemoteSetURLDelete("origin", RemoteSetURLDeleteOptions{Regex: "t"}) assert.Nil(t, err) - URLs, err = r.RemoteGetURL("origin", RemoteGetURLOptions{All: true}) + urls, err = r.RemoteGetURL("origin", RemoteGetURLOptions{All: true}) assert.Nil(t, err) - assert.Equal(t, []string{"s"}, URLs) + assert.Equal(t, []string{"s"}, urls) } From 5863f89a6ba9827709ca8d41908b06c63281689d Mon Sep 17 00:00:00 2001 From: jtagcat Date: Fri, 25 Feb 2022 11:28:56 +0200 Subject: [PATCH 07/10] fixup: RemoteSetURLOptions Add description --- repo_remote.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/repo_remote.go b/repo_remote.go index 85016cfef..41af0aed6 100644 --- a/repo_remote.go +++ b/repo_remote.go @@ -222,7 +222,7 @@ func (r *Repository) RemoteGetURL(name string, opts ...RemoteGetURLOptions) ([]s // // Docs: https://git-scm.com/docs/git-remote#Documentation/git-remote.txt-emset-urlem type RemoteSetURLOptions struct { - // Indicates whether to add a new URL. + // Indicates whether to append, instead of overwriting (the first) URL. Add bool // Indicates whether to get push URLs instead of fetch URLs. Push bool From 465b1ac255624076f9fe18fae4041386269ecea5 Mon Sep 17 00:00:00 2001 From: jtagcat Date: Fri, 25 Feb 2022 11:37:26 +0200 Subject: [PATCH 08/10] DeleteURL: regex is mandatory --- repo_remote.go | 13 ++++--------- repo_remote_test.go | 4 ++-- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/repo_remote.go b/repo_remote.go index 41af0aed6..df4be553a 100644 --- a/repo_remote.go +++ b/repo_remote.go @@ -278,8 +278,6 @@ func (r *Repository) RemoteSetURL(name, newurl string, opts ...RemoteSetURLOptio type RemoteSetURLDeleteOptions struct { // Indicates whether to get push URLs instead of fetch URLs. Push bool - // The regex to match existing URLs. - Regex string // The timeout duration before giving up for each shell command execution. // The default timeout duration will be used when not supplied. Timeout time.Duration @@ -287,7 +285,7 @@ type RemoteSetURLDeleteOptions struct { // RemoteSetURLDelete deletes the remote with given name of the repository in // given path. -func RemoteSetURLDelete(repoPath, name string, opts ...RemoteSetURLDeleteOptions) error { +func RemoteSetURLDelete(repoPath, name, regex string, opts ...RemoteSetURLDeleteOptions) error { var opt RemoteSetURLDeleteOptions if len(opts) > 0 { opt = opts[0] @@ -299,10 +297,7 @@ func RemoteSetURLDelete(repoPath, name string, opts ...RemoteSetURLDeleteOptions } cmd.AddArgs(name) - - if opt.Regex != "" { - cmd.AddArgs(opt.Regex) - } + cmd.AddArgs(regex) _, err := cmd.RunInDirWithTimeout(opt.Timeout, repoPath) if err != nil && strings.Contains(err.Error(), "Will not delete all non-push URLs") { @@ -313,6 +308,6 @@ func RemoteSetURLDelete(repoPath, name string, opts ...RemoteSetURLDeleteOptions // RemoteSetURLDelete deletes all URLs matching regex of the remote with given // name of the repository. -func (r *Repository) RemoteSetURLDelete(name string, opts ...RemoteSetURLDeleteOptions) error { - return RemoteSetURLDelete(r.path, name, opts...) +func (r *Repository) RemoteSetURLDelete(name, regex string, opts ...RemoteSetURLDeleteOptions) error { + return RemoteSetURLDelete(r.path, name, regex, opts...) } diff --git a/repo_remote_test.go b/repo_remote_test.go index 4fa482d8c..ed0cb4cce 100644 --- a/repo_remote_test.go +++ b/repo_remote_test.go @@ -172,7 +172,7 @@ func TestRepository_RemoteURLFamily(t *testing.T) { } defer cleanup() - err = r.RemoteSetURLDelete("origin", RemoteSetURLDeleteOptions{Regex: ".*"}) + err = r.RemoteSetURLDelete("origin", ".*") assert.Equal(t, ErrNotDeleteNonPushURLs, err) err = r.RemoteSetURL("notexist", "t") @@ -200,7 +200,7 @@ func TestRepository_RemoteURLFamily(t *testing.T) { assert.Nil(t, err) assert.Equal(t, []string{"t", "s"}, urls) - err = r.RemoteSetURLDelete("origin", RemoteSetURLDeleteOptions{Regex: "t"}) + err = r.RemoteSetURLDelete("origin", "t") assert.Nil(t, err) urls, err = r.RemoteGetURL("origin", RemoteGetURLOptions{All: true}) assert.Nil(t, err) From d24c817da4e49acf15f78fcf305bf362ae7dc3d6 Mon Sep 17 00:00:00 2001 From: jtagcat Date: Fri, 25 Feb 2022 12:05:50 +0200 Subject: [PATCH 09/10] improve comment for SetURL, readd URLAdd --- repo_remote.go | 50 +++++++++++++++++++++++++++++++++++++-------- repo_remote_test.go | 2 +- 2 files changed, 43 insertions(+), 9 deletions(-) diff --git a/repo_remote.go b/repo_remote.go index df4be553a..ffe05bf90 100644 --- a/repo_remote.go +++ b/repo_remote.go @@ -222,11 +222,9 @@ func (r *Repository) RemoteGetURL(name string, opts ...RemoteGetURLOptions) ([]s // // Docs: https://git-scm.com/docs/git-remote#Documentation/git-remote.txt-emset-urlem type RemoteSetURLOptions struct { - // Indicates whether to append, instead of overwriting (the first) URL. - Add bool // Indicates whether to get push URLs instead of fetch URLs. Push bool - // The regex to match existing URLs. + // The regex to match existing URLs to replace (instead of first). Regex string // The timeout duration before giving up for each shell command execution. // The default timeout duration will be used when not supplied. @@ -241,9 +239,6 @@ func RemoteSetURL(repoPath, name, newurl string, opts ...RemoteSetURLOptions) er } cmd := NewCommand("remote", "set-url") - if opt.Add { - cmd.AddArgs("--add") - } if opt.Push { cmd.AddArgs("--push") } @@ -271,6 +266,46 @@ func (r *Repository) RemoteSetURL(name, newurl string, opts ...RemoteSetURLOptio return RemoteSetURL(r.path, name, newurl, opts...) } +// RemoteSetURLAddOptions contains arguments for appending an URL to a remote +// of the repository. +// +// Docs: https://git-scm.com/docs/git-remote#Documentation/git-remote.txt-emset-urlem +type RemoteSetURLAddOptions struct { + // Indicates whether to get push URLs instead of fetch URLs. + Push bool + // The timeout duration before giving up for each shell command execution. + // The default timeout duration will be used when not supplied. + Timeout time.Duration +} + +// RemoteSetURLAdd appends an URL to the remote with given name of the repository in +// given path. (RemoteSetURL overwrites the URL(s) instead) +func RemoteSetURLAdd(repoPath, name, newurl string, opts ...RemoteSetURLAddOptions) error { + var opt RemoteSetURLAddOptions + if len(opts) > 0 { + opt = opts[0] + } + + cmd := NewCommand("remote", "set-url", "--add") + if opt.Push { + cmd.AddArgs("--push") + } + + cmd.AddArgs(name, newurl) + + _, err := cmd.RunInDirWithTimeout(opt.Timeout, repoPath) + if err != nil && strings.Contains(err.Error(), "Will not delete all non-push URLs") { + return ErrNotDeleteNonPushURLs + } + return err +} + +// RemoteSetURLAdd appends an URL to the remote with given name of the repository. +// (RemoteSetURL overwrites the URL(s) instead) +func (r *Repository) RemoteSetURLAdd(name, newurl string, opts ...RemoteSetURLAddOptions) error { + return RemoteSetURLAdd(r.path, name, newurl, opts...) +} + // RemoteSetURLDeleteOptions contains arguments for deleting an URL of a remote // of the repository. // @@ -296,8 +331,7 @@ func RemoteSetURLDelete(repoPath, name, regex string, opts ...RemoteSetURLDelete cmd.AddArgs("--push") } - cmd.AddArgs(name) - cmd.AddArgs(regex) + cmd.AddArgs(name, regex) _, err := cmd.RunInDirWithTimeout(opt.Timeout, repoPath) if err != nil && strings.Contains(err.Error(), "Will not delete all non-push URLs") { diff --git a/repo_remote_test.go b/repo_remote_test.go index ed0cb4cce..130fcaab7 100644 --- a/repo_remote_test.go +++ b/repo_remote_test.go @@ -188,7 +188,7 @@ func TestRepository_RemoteURLFamily(t *testing.T) { assert.Nil(t, err) assert.Equal(t, []string{"t"}, urls) - err = r.RemoteSetURL("origin", "e", RemoteSetURLOptions{Add: true}) + err = r.RemoteSetURLAdd("origin", "e") assert.Nil(t, err) urls, err = r.RemoteGetURL("origin", RemoteGetURLOptions{All: true}) assert.Nil(t, err) From f7d5d5a17bc94f52c0372152004adab6b47972d2 Mon Sep 17 00:00:00 2001 From: Joe Chen Date: Fri, 25 Feb 2022 18:43:04 +0800 Subject: [PATCH 10/10] Apply suggestions from code review --- repo_remote.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/repo_remote.go b/repo_remote.go index ffe05bf90..9dd59efb1 100644 --- a/repo_remote.go +++ b/repo_remote.go @@ -279,7 +279,7 @@ type RemoteSetURLAddOptions struct { } // RemoteSetURLAdd appends an URL to the remote with given name of the repository in -// given path. (RemoteSetURL overwrites the URL(s) instead) +// given path. Use RemoteSetURL to overwrite the URL(s) instead. func RemoteSetURLAdd(repoPath, name, newurl string, opts ...RemoteSetURLAddOptions) error { var opt RemoteSetURLAddOptions if len(opts) > 0 { @@ -301,7 +301,7 @@ func RemoteSetURLAdd(repoPath, name, newurl string, opts ...RemoteSetURLAddOptio } // RemoteSetURLAdd appends an URL to the remote with given name of the repository. -// (RemoteSetURL overwrites the URL(s) instead) +// Use RemoteSetURL to overwrite the URL(s) instead. func (r *Repository) RemoteSetURLAdd(name, newurl string, opts ...RemoteSetURLAddOptions) error { return RemoteSetURLAdd(r.path, name, newurl, opts...) }