This commit is contained in:
Jingwen Owen Ou 2013-07-01 11:04:35 -07:00
Родитель c60599b490 46cf7a2f21
Коммит c787d9b845
9 изменённых файлов: 222 добавлений и 33 удалений

Просмотреть файл

@ -54,6 +54,14 @@ func (a *Args) Remove(i int) string {
return item
}
func (a *Args) Replace(i int, item string) {
if i > a.Size()-1 {
panic(fmt.Sprintf("Index %d is out of bound", i))
}
a.args[i] = item
}
func (a *Args) IndexOf(arg string) int {
for i, aa := range a.args {
if aa == arg {

78
commands/clone.go Normal file
Просмотреть файл

@ -0,0 +1,78 @@
package commands
import (
"github.com/jingweno/gh/github"
"regexp"
"strings"
)
var cmdClone = &Command{
Run: clone,
GitExtension: true,
Usage: "clone [-p] OPTIONS [USER] REPOSITORY DIRECTORY",
Short: "clone a remote repository into a new directory",
}
/**
$ gh clone jingweno/gh
> git clone git://github.com/jingweno/gh
$ gh clone -p jingweno/gh
> git clone git@github.com:jingweno/gh.git
$ gh clone jekyll_and_hype
> git clone git://github.com/YOUR_LOGIN/jekyll_and_hype.
$ hub clone -p jekyll_and_hype
> git clone git@github.com:YOUR_LOGIN/jekyll_and_hype.git
*/
func clone(command *Command, args *Args) {
if !args.IsEmpty() {
transformCloneArgs(args)
}
}
func transformCloneArgs(args *Args) {
isSSH := parseClonePrivateFlag(args)
hasValueRegxp := regexp.MustCompile("^(--(upload-pack|template|depth|origin|branch|reference|name)|-[ubo])$")
nameWithOwnerRegexp := regexp.MustCompile(NameWithOwnerRe)
for i, a := range args.Array() {
if hasValueRegxp.MatchString(a) {
continue
}
if nameWithOwnerRegexp.MatchString(a) && !isDir(a) {
name, owner := parseCloneNameAndOwner(a)
project := github.Project{Name: name, Owner: owner}
url := project.GitURL(name, owner, isSSH)
args.Replace(i, url)
break
}
}
}
func parseClonePrivateFlag(args *Args) bool {
if i := args.IndexOf("-p"); i != -1 {
args.Remove(i)
return true
}
return false
}
func parseCloneNameAndOwner(arg string) (name, owner string) {
name, owner = arg, ""
if strings.Contains(arg, "/") {
split := strings.SplitN(arg, "/", 2)
name = split[1]
owner = split[0]
}
if owner == "" {
config := github.CurrentConfig()
owner = config.User
}
return
}

40
commands/clone_test.go Normal file
Просмотреть файл

@ -0,0 +1,40 @@
package commands
import (
"github.com/bmizerany/assert"
"github.com/jingweno/gh/github"
"os"
"path/filepath"
"testing"
)
func TestTransformCloneArgs(t *testing.T) {
args := NewArgs([]string{"jingweno/gh"})
transformCloneArgs(args)
assert.Equal(t, 1, args.Size())
assert.Equal(t, "git://github.com/jingweno/gh.git", args.First())
args = NewArgs([]string{"-p", "jingweno/gh"})
transformCloneArgs(args)
assert.Equal(t, 1, args.Size())
assert.Equal(t, "git@github.com:jingweno/gh.git", args.First())
args = NewArgs([]string{"-p", "acl-services/devise-acl"})
transformCloneArgs(args)
assert.Equal(t, 1, args.Size())
assert.Equal(t, "git@github.com:acl-services/devise-acl.git", args.First())
github.DefaultConfigFile = "./test_support/gh"
config := github.Config{User: "jingweno", Token: "123"}
github.SaveConfig(&config)
defer os.RemoveAll(filepath.Dir(github.DefaultConfigFile))
args = NewArgs([]string{"-p", "jekyll_and_hyde"})
transformCloneArgs(args)
assert.Equal(t, 1, args.Size())
assert.Equal(t, "git@github.com:jingweno/jekyll_and_hyde.git", args.First())
}

Просмотреть файл

@ -11,7 +11,7 @@ import (
var (
NameRe = "[\\w.][\\w.-]*"
OwnerRe = "[a-zA-Z0-9][a-zA-Z0-9-]*"
NameWithOwnerRe = fmt.Sprintf("/^(?:%s|%s\\/%s)$", NameRe, OwnerRe, NameRe)
NameWithOwnerRe = fmt.Sprintf("^(?:%s|%s\\/%s)$", NameRe, OwnerRe, NameRe)
)
type Command struct {
@ -59,6 +59,7 @@ var Branching = []*Command{
}
var Remote = []*Command{
cmdClone,
cmdRemote,
}

Просмотреть файл

@ -3,6 +3,9 @@ package commands
import (
"fmt"
"github.com/jingweno/gh/github"
"github.com/jingweno/gh/utils"
"os"
"path/filepath"
"regexp"
)
@ -31,15 +34,23 @@ func remote(command *Command, args *Args) {
func transformRemoteArgs(args *Args) {
ownerWithName := args.Last()
owner, repo, match := parseRepoNameOwner(ownerWithName)
owner, name, match := parseRepoNameOwner(ownerWithName)
if !match {
return
}
isPriavte := parseRemotePrivateFlag(args)
if name == "" {
dir, err := os.Getwd()
utils.Check(err)
name = filepath.Base(dir)
}
gh := github.New()
url := gh.ExpandRemoteUrl(owner, repo, isPriavte)
if owner == "origin" {
owner = github.CurrentConfig().FetchUser()
}
project := github.Project{Owner: owner, Name: name}
url := project.GitURL(name, owner, isPriavte)
args.Append(url)
}

Просмотреть файл

@ -2,6 +2,10 @@ package commands
import (
"github.com/bmizerany/assert"
"github.com/jingweno/gh/github"
"os"
"path/filepath"
"regexp"
"testing"
)
@ -16,7 +20,7 @@ func TestParseRepoNameOwner(t *testing.T) {
assert.T(t, match)
assert.Equal(t, "jingweno", owner)
assert.Equal(t, "gh", repo)
assert.Equal(t, "gh", repo)
}
func TestTransformRemoteArgs(t *testing.T) {
@ -26,7 +30,8 @@ func TestTransformRemoteArgs(t *testing.T) {
assert.Equal(t, 3, args.Size())
assert.Equal(t, "add", args.First())
assert.Equal(t, "jingweno", args.Get(1))
assert.Equal(t, "git://github.com/jingweno/gh.git", args.Get(2))
reg := regexp.MustCompile("^git://github.com/jingweno/.+\\.git$")
assert.T(t, reg.MatchString(args.Get(2)))
args = NewArgs([]string{"add", "-p", "jingweno"})
transformRemoteArgs(args)
@ -34,7 +39,22 @@ func TestTransformRemoteArgs(t *testing.T) {
assert.Equal(t, 3, args.Size())
assert.Equal(t, "add", args.First())
assert.Equal(t, "jingweno", args.Get(1))
assert.Equal(t, "git@github.com:jingweno/gh.git", args.Get(2))
reg = regexp.MustCompile("^git@github.com:jingweno/.+\\.git$")
assert.T(t, reg.MatchString(args.Get(2)))
github.DefaultConfigFile = "./test_support/gh"
config := github.Config{User: "jingweno", Token: "123"}
github.SaveConfig(&config)
defer os.RemoveAll(filepath.Dir(github.DefaultConfigFile))
args = NewArgs([]string{"add", "origin"})
transformRemoteArgs(args)
assert.Equal(t, 3, args.Size())
assert.Equal(t, "add", args.First())
assert.Equal(t, "origin", args.Get(1))
reg = regexp.MustCompile("^git://github.com/.+/.+\\.git$")
assert.T(t, reg.MatchString(args.Get(2)))
args = NewArgs([]string{"add", "jingweno", "git@github.com:jingweno/gh.git"})
transformRemoteArgs(args)

Просмотреть файл

@ -3,6 +3,7 @@ package commands
import (
"github.com/jingweno/gh/cmd"
"github.com/jingweno/gh/utils"
"os"
)
func browserCommand(url string) error {
@ -15,3 +16,18 @@ func browserCommand(url string) error {
c := cmd.NewWithArray(launcher)
return c.Exec()
}
func isDir(file string) bool {
f, err := os.Open(file)
if err != nil {
return false
}
defer f.Close()
fi, err := f.Stat()
if err != nil {
return false
}
return fi.IsDir()
}

Просмотреть файл

@ -40,14 +40,44 @@ func (c *Config) FetchPassword() string {
return string(pass)
}
var DefaultFile string
func (c *Config) FetchCredentials() {
var changed bool
if c.User == "" {
c.FetchUser()
changed = true
}
func init() {
DefaultFile = filepath.Join(os.Getenv("HOME"), ".config", "gh")
if c.Token == "" {
password := c.FetchPassword()
token, err := findOrCreateToken(c.User, password)
utils.Check(err)
c.Token = token
changed = true
}
if changed {
err := SaveConfig(c)
utils.Check(err)
}
}
var (
DefaultConfigFile = filepath.Join(os.Getenv("HOME"), ".config", "gh")
)
func CurrentConfig() *Config {
config, err := loadConfig()
if err != nil {
config = Config{}
}
config.FetchCredentials()
return &config
}
func loadConfig() (Config, error) {
return loadFrom(DefaultFile)
return loadFrom(DefaultConfigFile)
}
func loadFrom(filename string) (Config, error) {
@ -74,8 +104,8 @@ func doLoadFrom(f *os.File) (Config, error) {
return c, nil
}
func saveConfig(config *Config) error {
return saveTo(DefaultFile, config)
func SaveConfig(config *Config) error {
return saveTo(DefaultConfigFile, config)
}
func saveTo(filename string, config *Config) error {

Просмотреть файл

@ -4,7 +4,6 @@ import (
"errors"
"fmt"
"github.com/jingweno/gh/git"
"github.com/jingweno/gh/utils"
"github.com/jingweno/octokat"
)
@ -87,9 +86,7 @@ func (gh *GitHub) ExpandRemoteUrl(owner, name string, isSSH bool) (url string) {
project := gh.Project
if owner == "origin" {
config := gh.config
project.Owner = config.FetchUser()
} else {
project.Owner = owner
owner = config.FetchUser()
}
return project.GitURL(name, owner, isSSH)
@ -134,27 +131,15 @@ func findOrCreateToken(user, password string) (string, error) {
func (gh *GitHub) client() *octokat.Client {
config := gh.config
if config.User == "" {
config.FetchUser()
}
if config.Token == "" {
password := config.FetchPassword()
token, err := findOrCreateToken(config.User, password)
utils.Check(err)
config.Token = token
err = saveConfig(config)
utils.Check(err)
}
config.FetchCredentials()
return octokat.NewClient().WithToken(config.Token)
}
func New() *GitHub {
project := CurrentProject()
c, _ := loadConfig()
c := CurrentConfig()
c.FetchUser()
return &GitHub{project, &c}
return &GitHub{project, c}
}