2013-07-01 21:11:02 +04:00
|
|
|
package commands
|
|
|
|
|
|
|
|
import (
|
|
|
|
"regexp"
|
|
|
|
"strings"
|
2014-03-10 01:33:54 +04:00
|
|
|
|
|
|
|
"github.com/github/hub/github"
|
2014-03-28 03:42:14 +04:00
|
|
|
"github.com/github/hub/utils"
|
2013-07-01 21:11:02 +04:00
|
|
|
)
|
|
|
|
|
|
|
|
var cmdClone = &Command{
|
|
|
|
Run: clone,
|
|
|
|
GitExtension: true,
|
2013-07-04 09:07:23 +04:00
|
|
|
Usage: "clone [-p] OPTIONS [USER/]REPOSITORY DIRECTORY",
|
2013-07-01 22:54:01 +04:00
|
|
|
Short: "Clone a remote repository into a new directory",
|
2013-07-01 22:12:46 +04:00
|
|
|
Long: `Clone repository "git://github.com/USER/REPOSITORY.git" into
|
|
|
|
DIRECTORY as with git-clone(1). When USER/ is omitted, assumes
|
|
|
|
your GitHub login. With -p, clone private repositories over SSH.
|
|
|
|
For repositories under your GitHub login, -p is implicit.
|
|
|
|
`,
|
2013-07-01 21:11:02 +04:00
|
|
|
}
|
|
|
|
|
2013-12-30 02:18:14 +04:00
|
|
|
func init() {
|
|
|
|
CmdRunner.Use(cmdClone)
|
|
|
|
}
|
|
|
|
|
2013-07-01 21:11:02 +04:00
|
|
|
/**
|
|
|
|
$ gh clone jingweno/gh
|
2013-07-05 22:10:24 +04:00
|
|
|
> git clone git://github.com/jingweno/gh.git
|
2013-07-01 21:11:02 +04:00
|
|
|
|
|
|
|
$ gh clone -p jingweno/gh
|
|
|
|
> git clone git@github.com:jingweno/gh.git
|
|
|
|
|
2013-07-05 22:10:24 +04:00
|
|
|
$ gh clone jekyll_and_hyde
|
|
|
|
> git clone git://github.com/YOUR_LOGIN/jekyll_and_hyde.git
|
2013-07-01 21:11:02 +04:00
|
|
|
|
2013-07-01 22:35:15 +04:00
|
|
|
$ gh clone -p jekyll_and_hyde
|
|
|
|
> git clone git@github.com:YOUR_LOGIN/jekyll_and_hyde.git
|
2013-07-01 21:11:02 +04:00
|
|
|
*/
|
|
|
|
func clone(command *Command, args *Args) {
|
2013-07-02 22:56:45 +04:00
|
|
|
if !args.IsParamsEmpty() {
|
2013-07-01 21:11:02 +04:00
|
|
|
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)
|
2013-12-11 12:04:30 +04:00
|
|
|
for i := 0; i < args.ParamsSize(); i++ {
|
|
|
|
a := args.Params[i]
|
2013-07-20 18:31:12 +04:00
|
|
|
|
|
|
|
if strings.HasPrefix(a, "-") {
|
|
|
|
if hasValueRegxp.MatchString(a) {
|
2013-12-11 12:04:30 +04:00
|
|
|
i++
|
2013-07-20 18:31:12 +04:00
|
|
|
}
|
2013-12-11 12:04:30 +04:00
|
|
|
} else {
|
|
|
|
if nameWithOwnerRegexp.MatchString(a) && !isDir(a) {
|
|
|
|
name, owner := parseCloneNameAndOwner(a)
|
2014-03-26 04:01:00 +04:00
|
|
|
var host *github.Host
|
2013-12-11 12:04:30 +04:00
|
|
|
if owner == "" {
|
|
|
|
configs := github.CurrentConfigs()
|
2014-03-28 03:42:14 +04:00
|
|
|
h, err := configs.DefaultHost()
|
|
|
|
if err != nil {
|
|
|
|
utils.Check(github.FormatError("cloning repository", err))
|
|
|
|
}
|
|
|
|
|
|
|
|
host = h
|
2014-03-26 04:01:00 +04:00
|
|
|
owner = host.User
|
2013-12-11 12:04:30 +04:00
|
|
|
}
|
|
|
|
|
2014-03-26 04:01:00 +04:00
|
|
|
var hostStr string
|
|
|
|
if host != nil {
|
|
|
|
hostStr = host.Host
|
2013-12-11 12:04:30 +04:00
|
|
|
}
|
|
|
|
|
2014-03-26 04:01:00 +04:00
|
|
|
project := github.NewProject(owner, name, hostStr)
|
2014-04-08 08:44:08 +04:00
|
|
|
if !isSSH &&
|
2013-12-11 12:04:30 +04:00
|
|
|
args.Command != "submodule" &&
|
2014-04-08 08:44:08 +04:00
|
|
|
!github.IsHttpsProtocol() {
|
|
|
|
client := github.NewClient(project.Host)
|
|
|
|
repo, err := client.Repository(project)
|
|
|
|
isSSH = (err == nil) && (repo.Private || repo.Permissions.Push)
|
|
|
|
}
|
2013-12-11 12:04:30 +04:00
|
|
|
|
|
|
|
url := project.GitURL(name, owner, isSSH)
|
|
|
|
args.ReplaceParam(i, url)
|
2013-07-01 22:19:40 +04:00
|
|
|
}
|
|
|
|
|
2013-07-01 21:11:02 +04:00
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func parseClonePrivateFlag(args *Args) bool {
|
2013-07-02 22:56:45 +04:00
|
|
|
if i := args.IndexOfParam("-p"); i != -1 {
|
|
|
|
args.RemoveParam(i)
|
2013-07-01 21:11:02 +04:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
return false
|
|
|
|
}
|
2013-07-01 21:37:40 +04:00
|
|
|
|
|
|
|
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]
|
|
|
|
}
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|