Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 39 additions & 13 deletions internal/git/remote.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,42 @@ func (rs RemoteSet) FilterByHosts(hosts []string) RemoteSet {
return filtered
}

// Translate rewrites the URLs of every remote and re-derives each remote's
// repository identity from the result.
func (rs RemoteSet) Translate(translate func(*url.URL) *url.URL) {
for _, r := range rs {
r.Translate(translate)
}
}

// Translate rewrites the remote's URLs and re-derives its repository identity
// from the result.
func (r *Remote) Translate(translate func(*url.URL) *url.URL) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved translation here rather than keeping it in Current because the pattern exhibited a bit of https://refactoring.guru/smells/feature-envy

if r.FetchURL != nil {
r.FetchURL = translate(r.FetchURL)
}
if r.PushURL != nil {
r.PushURL = translate(r.PushURL)
}
r.resolveIdentity()
}

// resolveIdentity sets the remote's repository from its fetch URL, falling back
// to its push URL. Like gh, a remote whose URLs don't name a repository has no
// identity.
func (r *Remote) resolveIdentity() {
r.Host, r.Owner, r.Repo = "", "", ""
for _, u := range []*url.URL{r.FetchURL, r.PushURL} {
if u == nil {
continue
}
if host, owner, repo, err := RepoInfoFromURL(u); err == nil {
r.Host, r.Owner, r.Repo = host, owner, repo
return
}
}
}
Comment on lines +91 to +102

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: I know this is meant to simplify the old switch-statement on URL type, but I'm just a bit wondering about any potential edge cases, because it's not a 100% refactor in terms of behaviour (looking at the early return in the loop).

In this old switch-statement, any of Host, Owner, or Repo values that were not already populated from the fetch URL, would have a chance to be assigned from the push URL. So, a configuration like this (which is not actually correct, but technically possible):

fetchurl=https:///owner/repo
pushurl=https://some.host/owner/repo

would result in a different state with this PR's changes: some.host is not picked up as opposed to the current implementation.

I know it's super unlikely for a user to have such a weird config, so I think we're fine shipping the changes. Just wanted to call out in case you think otherwise.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think your specific example is right because https:///owner/repo will return an error from RepoInfoFromURL since there is no hostname.

https://a.host/owner/.git would probably be an issue. However, I think this is so weird, and would also diverge from gh that I'm not worried about.

Thanks for your diligence!


func listRemotes() ([]string, error) {
stdOut, _, err := Exec("remote", "-v")
if err != nil {
Expand All @@ -88,7 +124,6 @@ func parseRemotes(gitRemotes []string) RemoteSet {
if err != nil {
continue
}
host, owner, repo, _ := RepoInfoFromURL(url)

var rem *Remote
if len(remotes) > 0 {
Expand All @@ -105,22 +140,13 @@ func parseRemotes(gitRemotes []string) RemoteSet {
switch urlType {
case "fetch":
rem.FetchURL = url
rem.Host = host
rem.Owner = owner
rem.Repo = repo
case "push":
rem.PushURL = url
if rem.Host == "" {
rem.Host = host
}
if rem.Owner == "" {
rem.Owner = owner
}
if rem.Repo == "" {
rem.Repo = repo
}
}
}
for _, rem := range remotes {
rem.resolveIdentity()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just a cleanup that allows the Remotes/parseRemotes and the Translate to share the same

}
return remotes
}

Expand Down
10 changes: 1 addition & 9 deletions pkg/repository/repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,15 +132,7 @@ func Current() (Repository, error) {
return r, errors.New("unable to determine current repository, no git remotes configured for this repository")
}

translator := ssh.NewTranslator()
for _, r := range remotes {
if r.FetchURL != nil {
r.FetchURL = translator.Translate(r.FetchURL)
}
if r.PushURL != nil {
r.PushURL = translator.Translate(r.PushURL)
}
}
remotes.Translate(ssh.NewTranslator().Translate)

hosts := auth.KnownHosts()

Expand Down
Loading
Loading