1package commands
2
3import (
4	"fmt"
5	"strings"
6
7	"github.com/github/hub/git"
8	"github.com/github/hub/github"
9	"github.com/github/hub/ui"
10	"github.com/github/hub/utils"
11)
12
13var cmdCreate = &Command{
14	Run:   create,
15	Usage: "create [-poc] [-d <DESCRIPTION>] [-h <HOMEPAGE>] [[<ORGANIZATION>/]<NAME>]",
16	Long: `Create a new repository on GitHub and add a git remote for it.
17
18## Options:
19	-p, --private
20		Create a private repository.
21
22	-d, --description <DESCRIPTION>
23		A short description of the GitHub repository.
24
25	-h, --homepage <HOMEPAGE>
26		A URL with more information about the repository. Use this, for example, if
27		your project has an external website.
28
29	--remote-name <REMOTE>
30		Set the name for the new git remote (default: "origin").
31
32	-o, --browse
33		Open the new repository in a web browser.
34
35	-c, --copy
36		Put the URL of the new repository to clipboard instead of printing it.
37
38	[<ORGANIZATION>/]<NAME>
39		The name for the repository on GitHub (default: name of the current working
40		directory).
41
42		Optionally, create the repository within <ORGANIZATION>.
43
44## Examples:
45		$ hub create
46		[ repo created on GitHub ]
47		> git remote add -f origin git@github.com:USER/REPO.git
48
49		$ hub create sinatra/recipes
50		[ repo created in GitHub organization ]
51		> git remote add -f origin git@github.com:sinatra/recipes.git
52
53## See also:
54
55hub-init(1), hub(1)
56`,
57}
58
59func init() {
60	CmdRunner.Use(cmdCreate)
61}
62
63func create(command *Command, args *Args) {
64	_, err := git.Dir()
65	if err != nil {
66		err = fmt.Errorf("'create' must be run from inside a git repository")
67		utils.Check(err)
68	}
69
70	var newRepoName string
71	if args.IsParamsEmpty() {
72		dirName, err := git.WorkdirName()
73		utils.Check(err)
74		newRepoName = github.SanitizeProjectName(dirName)
75	} else {
76		newRepoName = args.FirstParam()
77		if newRepoName == "" {
78			utils.Check(command.UsageError(""))
79		}
80	}
81
82	config := github.CurrentConfig()
83	host, err := config.DefaultHost()
84	if err != nil {
85		utils.Check(github.FormatError("creating repository", err))
86	}
87
88	owner := host.User
89	if strings.Contains(newRepoName, "/") {
90		split := strings.SplitN(newRepoName, "/", 2)
91		owner = split[0]
92		newRepoName = split[1]
93	}
94
95	project := github.NewProject(owner, newRepoName, host.Host)
96	gh := github.NewClient(project.Host)
97
98	flagCreatePrivate := args.Flag.Bool("--private")
99
100	repo, err := gh.Repository(project)
101	if err == nil {
102		foundProject := github.NewProject(repo.FullName, "", project.Host)
103		if foundProject.SameAs(project) {
104			if !repo.Private && flagCreatePrivate {
105				err = fmt.Errorf("Repository '%s' already exists and is public", repo.FullName)
106				utils.Check(err)
107			} else {
108				ui.Errorln("Existing repository detected")
109				project = foundProject
110			}
111		} else {
112			repo = nil
113		}
114	} else {
115		repo = nil
116	}
117
118	if repo == nil {
119		if !args.Noop {
120			flagCreateDescription := args.Flag.Value("--description")
121			flagCreateHomepage := args.Flag.Value("--homepage")
122			repo, err := gh.CreateRepository(project, flagCreateDescription, flagCreateHomepage, flagCreatePrivate)
123			utils.Check(err)
124			project = github.NewProject(repo.FullName, "", project.Host)
125		}
126	}
127
128	localRepo, err := github.LocalRepo()
129	utils.Check(err)
130
131	originName := args.Flag.Value("--remote-name")
132	if originName == "" {
133		originName = "origin"
134	}
135
136	if originRemote, err := localRepo.RemoteByName(originName); err == nil {
137		originProject, err := originRemote.Project()
138		if err != nil || !originProject.SameAs(project) {
139			ui.Errorf("A git remote named '%s' already exists and is set to push to '%s'.\n", originRemote.Name, originRemote.PushURL)
140		}
141	} else {
142		url := project.GitURL("", "", true)
143		args.Before("git", "remote", "add", "-f", originName, url)
144	}
145
146	webUrl := project.WebURL("", "", "")
147	args.NoForward()
148	flagCreateBrowse := args.Flag.Bool("--browse")
149	flagCreateCopy := args.Flag.Bool("--copy")
150	printBrowseOrCopy(args, webUrl, flagCreateBrowse, flagCreateCopy)
151}
152