Skip to content

Commit 9abab2c

Browse files
authored
Merge pull request #793 from bmeneg/fix-remote_url
remote: support remotes referred by URL only
2 parents 25678df + bbd51a7 commit 9abab2c

File tree

8 files changed

+56
-32
lines changed

8 files changed

+56
-32
lines changed

cmd/ci_run.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,10 @@ func getCIRunOptions(cmd *cobra.Command, args []string) (string, string, error)
100100

101101
var pid string
102102

103-
remote := determineSourceRemote(branch)
103+
remote, err := determineSourceRemote(branch)
104+
if err != nil {
105+
return "", "", err
106+
}
104107
rn, err := git.PathWithNamespace(remote)
105108
if err != nil {
106109
return "", "", err

cmd/mr_create.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,11 @@ func runMRCreate(cmd *cobra.Command, args []string) {
139139
log.Fatal(err)
140140
}
141141

142-
sourceRemote := determineSourceRemote(localBranch)
142+
sourceRemote, err := determineSourceRemote(localBranch)
143+
if err != nil {
144+
log.Fatal(err)
145+
}
146+
143147
// Get the pushed branch name
144148
sourceBranch, _ := git.UpstreamBranch(localBranch)
145149
if sourceBranch == "" {

cmd/util.go

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
flag "github.com/spf13/pflag"
1515
"github.com/spf13/viper"
1616
gitconfig "github.com/tcnksm/go-gitconfig"
17+
giturls "github.com/whilp/git-urls"
1718
gitlab "github.com/xanzy/go-gitlab"
1819
"github.com/zaquestion/lab/internal/config"
1920
"github.com/zaquestion/lab/internal/git"
@@ -187,7 +188,10 @@ func parseArgsRemoteAndBranch(args []string) (string, string, error) {
187188
}
188189

189190
if remote == "" {
190-
remote = determineSourceRemote(branch)
191+
remote, err = determineSourceRemote(branch)
192+
if err != nil {
193+
return "", "", err
194+
}
191195
}
192196
remote, err = getRemoteName(remote)
193197
if err != nil {
@@ -474,24 +478,29 @@ func labURLToRepo(project *gitlab.Project) string {
474478
return urlToRepo
475479
}
476480

477-
func determineSourceRemote(branch string) string {
481+
func determineSourceRemote(branch string) (string, error) {
478482
// There is a precendence of options that should be considered here:
479483
// branch.<name>.pushRemote > remote.pushDefault > branch.<name>.remote
480484
// This rule is placed in git-config(1) manpage
481485
r, err := gitconfig.Local("branch." + branch + ".pushRemote")
482-
if err == nil {
483-
return r
484-
}
485-
r, err = gitconfig.Local("remote.pushDefault")
486-
if err == nil {
487-
return r
486+
if err != nil {
487+
r, err = gitconfig.Local("remote.pushDefault")
488+
if err != nil {
489+
r, err = gitconfig.Local("branch." + branch + ".remote")
490+
if err != nil {
491+
return forkRemote, nil
492+
}
493+
}
488494
}
489-
r, err = gitconfig.Local("branch." + branch + ".remote")
490-
if err == nil {
491-
return r
495+
496+
// Parse the remote name for possible URL.
497+
u, err := giturls.Parse(r)
498+
if err != nil {
499+
return "", err
492500
}
493501

494-
return forkRemote
502+
path := strings.TrimPrefix(u.Path, "/")
503+
return path, nil
495504
}
496505

497506
// Check of a case-insensitive prefix in a string

cmd/util_test.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,10 @@ func Test_determineSourceRemote(t *testing.T) {
345345
}
346346

347347
t.Run(test.desc, func(t *testing.T) {
348-
sourceRemote := determineSourceRemote(test.branch)
348+
sourceRemote, err := determineSourceRemote(test.branch)
349+
if err != nil {
350+
t.Fatal(err)
351+
}
349352
assert.Equal(t, test.expected, sourceRemote)
350353
})
351354
}

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ require (
7373
github.com/spf13/jwalterweatherman v1.1.0 // indirect
7474
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect
7575
github.com/subosito/gotenv v1.2.0 // indirect
76+
github.com/whilp/git-urls v1.0.0
7677
github.com/xanzy/ssh-agent v0.3.1 // indirect
7778
github.com/yuin/goldmark v1.4.1 // indirect
7879
github.com/yuin/goldmark-emoji v1.0.1 // indirect

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,8 @@ github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s
436436
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
437437
github.com/tcnksm/go-gitconfig v0.1.2 h1:iiDhRitByXAEyjgBqsKi9QU4o2TNtv9kPP3RgPgXBPw=
438438
github.com/tcnksm/go-gitconfig v0.1.2/go.mod h1:/8EhP4H7oJZdIPyT+/UIsG87kTzrzM4UsLGSItWYCpE=
439+
github.com/whilp/git-urls v1.0.0 h1:95f6UMWN5FKW71ECsXRUd3FVYiXdrE7aX4NZKcPmIjU=
440+
github.com/whilp/git-urls v1.0.0/go.mod h1:J16SAmobsqc3Qcy98brfl5f5+e0clUvg1krgwk/qCfE=
439441
github.com/xanzy/go-gitlab v0.51.0 h1:qCVJM9ijpY/ZG703p6DIK7RCUwZ4iQlBAig0TGJ/mRc=
440442
github.com/xanzy/go-gitlab v0.51.0/go.mod h1:Q+hQhV508bDPoBijv7YjK/Lvlb4PhVhJdKqXVQrUoAE=
441443
github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0=

internal/git/git.go

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
retry "github.com/avast/retry-go"
1414
"github.com/pkg/errors"
1515
gitconfig "github.com/tcnksm/go-gitconfig"
16+
giturls "github.com/whilp/git-urls"
1617
"github.com/zaquestion/lab/internal/logger"
1718
)
1819

@@ -181,26 +182,27 @@ func PathWithNamespace(remote string) (string, error) {
181182
if err != nil {
182183
return "", err
183184
}
185+
if remoteURL == "" {
186+
// Branches can track remote based on ther URL, thus we don't
187+
// really have a remote entity in the git config, but only the
188+
// URL of the remote.
189+
// https://git-scm.com/docs/git-push#Documentation/git-push.txt-ltrepositorygt
190+
remoteURL = remote
191+
}
184192
}
185193

186-
parts := strings.Split(remoteURL, "//")
187-
188-
if len(parts) == 1 {
189-
// scp-like short syntax (e.g. [email protected]...)
190-
part := parts[0]
191-
parts = strings.Split(part, ":")
192-
} else if len(parts) == 2 {
193-
// every other protocol syntax (e.g. ssh://, http://, git://)
194-
part := parts[1]
195-
parts = strings.SplitN(part, "/", 2)
196-
} else {
197-
return "", errors.Errorf("cannot parse remote: %s url: %s", remote, remoteURL)
194+
u, err := giturls.Parse(remoteURL)
195+
if err != nil {
196+
return "", err
198197
}
199198

200-
if len(parts) != 2 {
201-
return "", errors.Errorf("cannot parse remote: %s url: %s", remote, remoteURL)
199+
// remote URLs can't refer to other files or local paths, ie., other remote
200+
// names.
201+
if u.Scheme == "file" {
202+
return "", errors.Errorf("invalid remote URL format for %s", remote)
202203
}
203-
path := parts[1]
204+
205+
path := strings.TrimPrefix(u.Path, "/")
204206
path = strings.TrimSuffix(path, ".git")
205207
return path, nil
206208
}

internal/git/git_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -187,10 +187,10 @@ func TestPathWithNamespace(t *testing.T) {
187187
expectedErr: "the key `remote.phoney.url` is not found",
188188
},
189189
{
190-
desc: "remote doesn't exist",
190+
desc: "invalid remote URL",
191191
remote: "garbage",
192192
expected: "",
193-
expectedErr: "cannot parse remote: garbage url: garbageurl",
193+
expectedErr: "invalid remote URL format for garbage",
194194
},
195195
}
196196

0 commit comments

Comments
 (0)