Skip to content

Commit

Permalink
Check owner and project name
Browse files Browse the repository at this point in the history
  • Loading branch information
kyoh86 committed Mar 17, 2019
1 parent d29be42 commit a994e89
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 13 deletions.
14 changes: 10 additions & 4 deletions gogh/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ type Context interface {

// CurrentContext get current context from OS envars and Git configurations
func CurrentContext(ctx context.Context) (Context, error) {
userName := getUserName()
userName, err := getUserName()
if err != nil {
return nil, err
}
gitHubToken := getGitHubToken()
gitHubHost := getGitHubHost()
logLevel := getLogLevel()
Expand Down Expand Up @@ -114,13 +117,16 @@ func getGitHubHost() string {
return getConf(envGoghGitHubHost, envGitHubHost)
}

func getUserName() string {
func getUserName() (string, error) {
name := getConf(envGoghGitHubUser, envGitHubUser, envUserName)
if name == "" {
// Make the error if it does not match any pattern
panic(fmt.Errorf("set %s to your environment variable", envGoghGitHubUser))
return name, fmt.Errorf("failed to find user name. set %s in environment variable", envGoghGitHubUser)
}
if err := ValidateOwner(name); err != nil {
return name, err
}
return name
return name, nil
}

func getLogLevel() string {
Expand Down
18 changes: 15 additions & 3 deletions gogh/context_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,18 +51,30 @@ func TestContext(t *testing.T) {
t.Run("get GitHub user name", func(t *testing.T) {
resetEnv(t)
require.NoError(t, os.Setenv(envGitHubUser, "kyoh87"))
assert.Equal(t, "kyoh87", getUserName())
name, err := getUserName()
require.NoError(t, err)
assert.Equal(t, "kyoh87", name)
})

t.Run("get OS user name", func(t *testing.T) {
resetEnv(t)
require.NoError(t, os.Setenv(envUserName, "kyoh88"))
assert.Equal(t, "kyoh88", getUserName())
name, err := getUserName()
require.NoError(t, err)
assert.Equal(t, "kyoh88", name)
})

t.Run("expect to fail to get user name from anywhere", func(t *testing.T) {
resetEnv(t)
assert.Panics(t, func() { getUserName() })
_, err := getUserName()
require.EqualError(t, err, "failed to find user name. set GOGH_GITHUB_USER in environment variable")
})

t.Run("expect to get invalid user name", func(t *testing.T) {
resetEnv(t)
require.NoError(t, os.Setenv(envUserName, "-kyoh88"))
_, err := getUserName()
require.NotNil(t, err)
})

t.Run("expect to fail to get log level from anywhere", func(t *testing.T) {
Expand Down
41 changes: 36 additions & 5 deletions gogh/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,29 @@ func CheckRepoHost(ctx Context, repo *Repo) error {
var hasSchemePattern = regexp.MustCompile("^[^:]+://")
var scpLikeURLPattern = regexp.MustCompile("^([^@]+@)?([^:]+):/?(.+)$")

//TODO: var validName = regexp.MustCompile(`^([a-zA-Z0-9](?:(?:-[a-zA-Z0-9]+)*[a-zA-Z0-9]+)?)/([\w-]+)$`)
//TODO: var capital = regexp.MustCompile(`[A-Z]`) // UNDONE: warn if name contains capital cases
var invalidNameRegexp = regexp.MustCompile(`[^\w\-\.]`)

func ValidateName(name string) error {
if name == "." || name == ".." {
return errors.New("'.' or '..' is reserved name")
}
if name == "" {
return errors.New("empty project name")
}
if invalidNameRegexp.MatchString(name) {
return errors.New("project name may only contain alphanumeric characters, dots or hyphens")
}
return nil
}

var validOwnerRegexp = regexp.MustCompile(`^[a-zA-Z0-9]+(?:-[a-zA-Z0-9]+)*$`)

func ValidateOwner(owner string) error {
if !validOwnerRegexp.MatchString(owner) {
return errors.New("owner name may only contain alphanumeric characters or single hyphens, and cannot begin or end with a hyphen")
}
return nil
}

// Set text as Repo
func (r *Repo) Set(rawRepo string) error {
Expand All @@ -75,29 +96,39 @@ func (r *Repo) Set(rawRepo string) error {
return err
}

var path string
if url.IsAbs() {
r.scheme = url.Scheme
r.host = url.Host
r.user = url.User
path = strings.Trim(url.Path, "/")
} else {
r.scheme = "https"
r.host = DefaultHost
r.user = nil
path = url.Path
}
r.forceQuery = url.ForceQuery
r.rawQuery = url.RawQuery
r.fragment = url.Fragment

pp := strings.Split(strings.Trim(url.Path, "/"), "/")
pp := strings.Split(path, "/")
switch len(pp) {
case 0:
return errors.New("repository remote has no local name")
case 1:
r.owner = "" // To use context.UserName() instead.
r.name = strings.TrimSuffix(pp[0], ".git")
if err := ValidateName(r.name); err != nil {
return err
}
case 2:
r.owner = pp[0]
if err := ValidateOwner(r.owner); err != nil {
return err
}
r.name = strings.TrimSuffix(pp[1], ".git")
if err := ValidateName(r.name); err != nil {
return err
}
default:
return errors.New("repository remote has too many slashes")
}
Expand Down
64 changes: 63 additions & 1 deletion gogh/repo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,71 @@ func TestRepo(t *testing.T) {
})

t.Run("fail when invalid url given", func(t *testing.T) {
_, err := ParseRepo("://////")
r, err := ParseRepo("://////")
assert.NotNil(t, err)
assert.Nil(t, r)
})

t.Run("fail when empty owner is given", func(t *testing.T) {
r, err := ParseRepo("/test")
assert.NotNil(t, err)
assert.Nil(t, r)
})

t.Run("fail when empty name is given", func(t *testing.T) {
r, err := ParseRepo("test/")
assert.NotNil(t, err)
assert.Nil(t, r)
})

t.Run("fail when owner name contains invalid charactor", func(t *testing.T) {
r, err := ParseRepo("kyoh_86/test")
assert.NotNil(t, err)
assert.Nil(t, r)
})

t.Run("fail when owner name starts with hyphen", func(t *testing.T) {
r, err := ParseRepo("-kyoh86/test")
assert.NotNil(t, err)
assert.Nil(t, r)
})

t.Run("fail when owner name ends with hyphen", func(t *testing.T) {
r, err := ParseRepo("kyoh86-/test")
assert.NotNil(t, err)
assert.Nil(t, r)
})

t.Run("fail when project name contains invalid charactor", func(t *testing.T) {
r, err := ParseRepo("kyoh86/foo,bar")
assert.NotNil(t, err)
assert.Nil(t, r)
})

t.Run("fail when owner name contains double hyphen", func(t *testing.T) {
r, err := ParseRepo("kyoh--86/test")
assert.NotNil(t, err)
assert.Nil(t, r)
})

t.Run("fail when url has no path", func(t *testing.T) {
r, err := ParseRepo("https://github.com/")
assert.EqualError(t, err, "empty project name")
assert.Nil(t, r)
})

t.Run("fail when url has subfolder", func(t *testing.T) {
r, err := ParseRepo("https://github.com/kyoh86/gogh/blob/master/gogh/repo.go")
assert.NotNil(t, err)
assert.Nil(t, r)
})

t.Run("fail to parse `dot`", func(t *testing.T) {
r, err := ParseRepo(".")
assert.NotNil(t, err)
assert.Nil(t, r)
})

}

func TestRepos(t *testing.T) {
Expand Down

0 comments on commit a994e89

Please sign in to comment.