1package commands 2 3import ( 4 "fmt" 5 "regexp" 6 "strings" 7 8 "github.com/github/hub/git" 9 "github.com/github/hub/github" 10 "github.com/github/hub/utils" 11) 12 13var cmdRemote = &Command{ 14 Run: remote, 15 GitExtension: true, 16 Usage: ` 17remote add [-p] [<OPTIONS>] <USER>[/<REPOSITORY>] 18remote set-url [-p] [<OPTIONS>] <NAME> <USER>[/<REPOSITORY>] 19`, 20 Long: `Add a git remote for a GitHub repository. 21 22## Options: 23 -p 24 (Deprecated) Use the ''ssh:'' protocol instead of ''git:'' for the remote URL. 25 The writeable ''ssh:'' protocol is automatically used for own repos, GitHub 26 Enterprise remotes, and private or pushable repositories. 27 28 <USER>[/<REPOSITORY>] 29 If <USER> is "origin", that value will be substituted for your GitHub 30 username. <REPOSITORY> defaults to the name of the current working directory. 31 32## Examples: 33 $ hub remote add jingweno 34 > git remote add jingweno git://github.com/jingweno/REPO.git 35 36 $ hub remote add origin 37 > git remote add origin git@github.com:USER/REPO.git 38 39## See also: 40 41hub-fork(1), hub(1), git-remote(1) 42`, 43} 44 45func init() { 46 CmdRunner.Use(cmdRemote) 47} 48 49/* 50 */ 51func remote(command *Command, args *Args) { 52 if !args.IsParamsEmpty() && (args.FirstParam() == "add" || args.FirstParam() == "set-url") { 53 transformRemoteArgs(args) 54 } 55} 56 57func transformRemoteArgs(args *Args) { 58 ownerWithName := args.LastParam() 59 60 re := regexp.MustCompile(fmt.Sprintf(`^%s(/%s)?$`, OwnerRe, NameRe)) 61 if !re.MatchString(ownerWithName) { 62 return 63 } 64 owner := ownerWithName 65 name := "" 66 if strings.Contains(ownerWithName, "/") { 67 parts := strings.SplitN(ownerWithName, "/", 2) 68 owner, name = parts[0], parts[1] 69 } 70 71 localRepo, err := github.LocalRepo() 72 utils.Check(err) 73 74 var host string 75 mainProject, err := localRepo.MainProject() 76 if err == nil { 77 host = mainProject.Host 78 } 79 80 if name == "" { 81 if mainProject != nil { 82 name = mainProject.Name 83 } else { 84 dirName, err := git.WorkdirName() 85 utils.Check(err) 86 name = github.SanitizeProjectName(dirName) 87 } 88 } 89 90 var hostConfig *github.Host 91 if host == "" { 92 hostConfig, err = github.CurrentConfig().DefaultHost() 93 } else { 94 hostConfig, err = github.CurrentConfig().PromptForHost(host) 95 } 96 if err != nil { 97 utils.Check(github.FormatError("adding remote", err)) 98 } 99 host = hostConfig.Host 100 101 p := utils.NewArgsParser() 102 p.RegisterValue("-t") 103 p.RegisterValue("-m") 104 params, _ := p.Parse(args.Params) 105 if len(params) > 3 { 106 return 107 } 108 109 for i, pi := range p.PositionalIndices { 110 if i == 1 && strings.Contains(params[i], "/") { 111 args.ReplaceParam(pi, owner) 112 } else if i == 2 { 113 args.RemoveParam(pi) 114 } 115 } 116 if len(params) == 2 && owner == "origin" { 117 owner = hostConfig.User 118 } 119 120 if strings.EqualFold(owner, hostConfig.User) { 121 owner = hostConfig.User 122 } 123 124 project := github.NewProject(owner, name, host) 125 126 isPrivate := parseRemotePrivateFlag(args) || owner == hostConfig.User || project.Host != github.GitHubHost 127 if !isPrivate { 128 gh := github.NewClient(project.Host) 129 repo, err := gh.Repository(project) 130 if err != nil { 131 if strings.Contains(err.Error(), "HTTP 404") { 132 err = fmt.Errorf("Error: repository %s/%s doesn't exist", project.Owner, project.Name) 133 } 134 utils.Check(err) 135 } 136 isPrivate = repo.Private || repo.Permissions.Push 137 } 138 139 url := project.GitURL("", "", isPrivate) 140 args.AppendParams(url) 141} 142 143func parseRemotePrivateFlag(args *Args) bool { 144 if i := args.IndexOfParam("-p"); i != -1 { 145 args.RemoveParam(i) 146 return true 147 } 148 149 return false 150} 151