Skip to content

Commit

Permalink
Accept remote urls#182870068 (#109)
Browse files Browse the repository at this point in the history
* table test for all RepoPieces results

* use both regex and uri parse for remotes

* bump version to 0.10.7
  • Loading branch information
pgrunde authored Sep 14, 2022
1 parent de31ea3 commit 26368df
Show file tree
Hide file tree
Showing 3 changed files with 156 additions and 83 deletions.
57 changes: 47 additions & 10 deletions app/cmd/publish.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,16 +203,52 @@ func currentBranch() (string, error) {

var hostedGitRe = regexp.MustCompile(`^(:?(\w+):\/\/\/?)?(?:(~?\w+)@)?([\w\d\.\-_]+)(:?:([\d]+))?(?::)?\/*(.*)\/([\w\d\.\-_]+)(?:\.git)\/?$`)

func parseHostedGitRegex(originUrl string) (repoParts learn.RepoPieces, err error) {
var repoPieces learn.RepoPieces
if m := hostedGitRe.FindStringSubmatch(originUrl); m != nil {
repoPieces, err = learn.RepoPieces{
Origin: m[4],
Org: m[7],
RepoName: m[8],
}, nil
func parseHostedGit(remoteUrl string) (learn.RepoPieces, error) {
var origin, org, repoName string
if strings.HasPrefix(remoteUrl, "https") {
// assume acceptable url to parse when remote matches https protocol
parsed, err := url.Parse(remoteUrl)
if err != nil {
return learn.RepoPieces{}, err
}

org, repoName = orgAndRepoFromPath(parsed.Path)
origin = parsed.Host
} else if m := hostedGitRe.FindStringSubmatch(remoteUrl); m != nil {
// use regexp for URL matching in non-https contexts like ssh, git, etc
org, repoName = orgAndRepoFromRegex(m[7], m[8])
origin = m[4]
}
return repoPieces, err

return learn.RepoPieces{
Origin: origin,
Org: org,
RepoName: repoName,
}, nil
}

// orgAndRepoFromPath plucks the first portion of the path for the org, while
// cleaning the remaining portion of the path of .git extensions for the repo name
func orgAndRepoFromPath(path string) (string, string) {
path = strings.TrimPrefix(path, "/")
parts := strings.Split(path, "/")
repoParts := strings.Join(parts[1:len(parts)], "/")

gitTrimmed := strings.TrimSuffix(repoParts, ".git") // path can contain either .git or .git/
return parts[0], strings.TrimSuffix(gitTrimmed, ".git/")
}

// orgAndRepoFromRegex corrects the expected format for org and repoName from the hosted git regex matcher
// org is the top level group for the remote, while the repoName is the rest of the path with namespace.
// e.g. a path for a git host /org/repo/name is received as 'org/repo' for the long beginning and 'name' for the short end.
// The block api expects the opposite, and needs 'org' for the org and 'repo/name' for the repo name.
func orgAndRepoFromRegex(long, shortEnd string) (string, string) {
if !strings.Contains(long, "/") {
return long, shortEnd
}

repoParts := append(strings.Split(long, "/"), shortEnd)
return repoParts[0], strings.Join(repoParts[1:len(repoParts)], "/")
}

func remotePieces() (learn.RepoPieces, error) {
Expand All @@ -221,7 +257,8 @@ func remotePieces() (learn.RepoPieces, error) {
if err != nil {
return repoPieces, err
}
return parseHostedGitRegex(s)

return parseHostedGit(s)
}

func pushToRemote(branch string) error {
Expand Down
180 changes: 108 additions & 72 deletions app/cmd/publish_test.go
Original file line number Diff line number Diff line change
@@ -1,83 +1,119 @@
package cmd

import (
"github.com/gSchool/glearn-cli/api/learn"
"testing"
)

func Test_parseHostedGitRegex_many(t *testing.T) {
var origins = []string{
"[email protected]:gsei19/nineteen-week/week-02-full-stack-by-feature.git",
"https://gitlab.com/gsei19/week-05.git",
"[email protected]:golang/from/go.git",
"ssh://[email protected]/path/to/repo.git/",
"ssh://[email protected]:1234/path-path/to-to/repo-repo.git/",
"ssh://host.xz:7634/path/to/repo-name-nam.git/",
"ssh://host.xz/path/to/repo-name.git/",
"ssh://[email protected]/path/to/repo-name.git/",
"ssh://host.xz/path/to/repo-name.git/",
"[email protected]:/path/to/repo.git/",
"host.xz:/path/to/repo-name.git/",
"[email protected]:path/to/repo.git",
"host.xz:path/to/repo.git",
"rsync://host.xz/path/to/repo.git/",
"git://host.xz/path/to/repo.git/",
"http://host.xz/path/to/repo.git/",
"https://host.xz/path/to/repo.git/",
func Test_parseHostedGit_many(t *testing.T) {
type urlToRepo struct {
url string
result learn.RepoPieces
}
for _, origin := range origins {
var repoPieces, _ = parseHostedGitRegex(origin)
if repoPieces.Org == "" {
t.Errorf("Org parse failed")
}
}
}

func Test_parseRepoPieces_TopLevelOrg(t *testing.T) {
repoPieces, err := parseHostedGitRegex("https://gitlab.com/gsei19/week-05.git")

if err != nil {
t.Errorf("Threw an error")
}

// https://gitlab.com/gsei19/nineteen-week/week-05.git

if repoPieces.Org != "gsei19" {
t.Errorf("Incorrect org parse")
}
}

func Test_parseRepoPieces_TopLevelOrg_Ssh(t *testing.T) {
repoPieces, err := parseHostedGitRegex("[email protected]:golang/go.git")

if err != nil {
t.Errorf("Threw an error")
}

// https://gitlab.com/gsei19/nineteen-week/week-05.git

if repoPieces.Origin != "github.com" {
t.Errorf("Incorrect Origin parse")
}

if repoPieces.RepoName != "go" {
t.Errorf("Incorrect RepoName parse")
}

if repoPieces.Org != "golang" {
t.Errorf("Incorrect org parse")
}
}

func Test_parseRepoPieces_NestedOrg(t *testing.T) {
repoPieces, err := parseHostedGitRegex("https://gitlab.com/gsei19/nineteen-week/week-05.git")

if err != nil {
t.Errorf("Threw an error")
var origins = []urlToRepo{
{
url: "[email protected]:gsei19/nineteen-week/week-02-full-stack-by-feature.git",
result: learn.RepoPieces{Origin: "gitlab.com", Org: "gsei19", RepoName: "nineteen-week/week-02-full-stack-by-feature"},
},
{
url: "https://gitlab.com/gsei19/week-05.git",
result: learn.RepoPieces{Origin: "gitlab.com", Org: "gsei19", RepoName: "week-05"},
},
{
url: "https://gitlab.com/gsei19/week-05.git",
result: learn.RepoPieces{Origin: "gitlab.com", Org: "gsei19", RepoName: "week-05"},
},
{
url: "[email protected]:golang/from/go.git",
result: learn.RepoPieces{Origin: "github.com", Org: "golang", RepoName: "from/go"},
},
{
url: "ssh://[email protected]/path/to/repo.git/",
result: learn.RepoPieces{Origin: "host.xz", Org: "path", RepoName: "to/repo"},
},
{
url: "ssh://[email protected]:1234/path-path/to-to/repo-repo.git/",
result: learn.RepoPieces{Origin: "host-website.xz", Org: "path-path", RepoName: "to-to/repo-repo"},
},
{
url: "ssh://host.xz:7634/path/to/repo-name-nam.git/",
result: learn.RepoPieces{Origin: "host.xz", Org: "path", RepoName: "to/repo-name-nam"},
},
{
url: "ssh://host.xz/path/to/repo-name.git/",
result: learn.RepoPieces{Origin: "host.xz", Org: "path", RepoName: "to/repo-name"},
},
{
url: "ssh://[email protected]/path/to/repo-name.git/",
result: learn.RepoPieces{Origin: "host.xz", Org: "path", RepoName: "to/repo-name"},
},
{
url: "ssh://host.xz/path/to/repo-name.git/",
result: learn.RepoPieces{Origin: "host.xz", Org: "path", RepoName: "to/repo-name"},
},
{
url: "[email protected]:/path/to/repo.git/",
result: learn.RepoPieces{Origin: "host.xz", Org: "path", RepoName: "to/repo"},
},
{
url: "host.xz:/path/to/repo-name.git/",
result: learn.RepoPieces{Origin: "host.xz", Org: "path", RepoName: "to/repo-name"},
},
{
url: "[email protected]:path/to/repo.git",
result: learn.RepoPieces{Origin: "host.xz", Org: "path", RepoName: "to/repo"},
},
{
url: "host.xz:path/to/repo.git",
result: learn.RepoPieces{Origin: "host.xz", Org: "path", RepoName: "to/repo"},
},
{
url: "rsync://host.xz/path/to/repo.git/",
result: learn.RepoPieces{Origin: "host.xz", Org: "path", RepoName: "to/repo"},
},
{
url: "git://host.xz/path/to/repo.git/",
result: learn.RepoPieces{Origin: "host.xz", Org: "path", RepoName: "to/repo"},
},
{
url: "http://host.xz/path/to/repo.git/",
result: learn.RepoPieces{Origin: "host.xz", Org: "path", RepoName: "to/repo"},
},
{
url: "https://host.xz/path/to/repo.git/",
result: learn.RepoPieces{Origin: "host.xz", Org: "path", RepoName: "to/repo"},
},
{
url: "https://oauth2:[email protected]/galvanize-labs/curriculum-development/agile.git",
result: learn.RepoPieces{Origin: "gitlab.com", Org: "galvanize-labs", RepoName: "curriculum-development/agile"},
},
{
url: "https://[email protected]/galvanize-labs/curriculum-development/spring/spring-web.git",
result: learn.RepoPieces{Origin: "gitlab.com", Org: "galvanize-labs", RepoName: "curriculum-development/spring/spring-web"},
},
{
url: "ssh://[email protected]/galvanize-labs/curriculum-development/application-architectures/12-factor-app/00-introduction.git",
result: learn.RepoPieces{Origin: "gitlab.com", Org: "galvanize-labs", RepoName: "curriculum-development/application-architectures/12-factor-app/00-introduction"},
},
}

// https://gitlab.com/gsei19/nineteen-week/week-05.git

if repoPieces.Org != "gsei19/nineteen-week" {
t.Errorf("Incorrect org parse")
for _, expected := range origins {
var test, err = parseHostedGit(expected.url)
if err != nil {
t.Errorf("given %s returned error: %s\n", expected.url, err)
return
}
if test.Org != expected.result.Org {
t.Errorf("Org parse failed!\ngiven: %s\n expect: %s\n result: %s\n", expected.url, expected.result.Org, test.Org)
return
}
if test.Origin != expected.result.Origin {
t.Errorf("Origin parse failed!\n given: %s\n expect: %s\n result: %s\n", expected.url, expected.result.Origin, test.Origin)
return
}
if test.RepoName != expected.result.RepoName {
t.Errorf("RepoName parse failed!\n given: %s\n expect: %s\n result: %s\n", expected.url, expected.result.RepoName, test.RepoName)
return
}
}
}
2 changes: 1 addition & 1 deletion app/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ You can get your api token at https://learn-2.galvanize.com/api_token
`

// currentReleaseVersion is used to print the version the user currently has downloaded
const currentReleaseVersion = "v0.10.6"
const currentReleaseVersion = "v0.10.7"

// rootCmd is the base for all our commands. It currently just checks for all the
// necessary credentials and prompts the user to set them if they are not there.
Expand Down

0 comments on commit 26368df

Please sign in to comment.