Beispiel #1
0
func fetchCiStatus(p *github.Project, sha string) (state, targetURL string, exitCode int, err error) {
	gh := github.NewClient(p.Host)
	status, err := gh.CIStatus(p, sha)
	if err != nil {
		return
	}

	if status == nil {
		state = "no status"
	} else {
		state = status.State
		targetURL = status.TargetURL
	}

	switch state {
	case "success":
		exitCode = 0
	case "failure", "error":
		exitCode = 1
	case "pending":
		exitCode = 2
	default:
		exitCode = 3
	}

	return
}
Beispiel #2
0
func tranformFetchArgs(args *Args) error {
	names := parseRemoteNames(args)
	localRepo := github.LocalRepo()

	projects := make(map[*github.Project]bool)
	ownerRegexp := regexp.MustCompile(OwnerRe)
	for _, name := range names {
		if ownerRegexp.MatchString(name) {
			_, err := localRepo.RemoteByName(name)
			if err != nil {
				project := github.NewProject(name, "", "")
				gh := github.NewClient(project.Host)
				repo, err := gh.Repository(project)
				if err != nil {
					continue
				}

				projects[project] = repo.Private
			}
		}
	}

	for project, private := range projects {
		args.Before("git", "remote", "add", project.Owner, project.GitURL("", "", private))
	}

	return nil
}
Beispiel #3
0
func transformCheckoutArgs(args *Args) error {
	words := args.Words()
	if len(words) == 0 {
		return nil
	}

	checkoutURL := words[0]
	url, err := github.ParseURL(checkoutURL)
	if err != nil {
		return nil
	}
	var newBranchName string
	if len(words) > 1 {
		newBranchName = words[1]
	}

	pullURLRegex := regexp.MustCompile("^pull/(\\d+)")
	projectPath := url.ProjectPath()
	if !pullURLRegex.MatchString(projectPath) {
		return nil
	}

	id := pullURLRegex.FindStringSubmatch(projectPath)[1]
	gh := github.NewClient(url.Project.Host)
	pullRequest, err := gh.PullRequest(url.Project, id)
	if err != nil {
		return err
	}

	if idx := args.IndexOfParam(newBranchName); idx >= 0 {
		args.RemoveParam(idx)
	}

	user, branch := parseUserBranchFromPR(pullRequest)
	if pullRequest.Head.Repo.ID == 0 {
		return fmt.Errorf("Error: %s's fork is not available anymore", user)
	}

	if newBranchName == "" {
		newBranchName = fmt.Sprintf("%s-%s", user, branch)
	}

	repo := github.LocalRepo()
	_, err = repo.RemoteByName(user)
	if err == nil {
		args.Before("git", "remote", "set-branches", "--add", user, branch)
		remoteURL := fmt.Sprintf("+refs/heads/%s:refs/remotes/%s/%s", branch, user, branch)
		args.Before("git", "fetch", user, remoteURL)
	} else {
		u := url.Project.GitURL("", user, pullRequest.Head.Repo.Private)
		args.Before("git", "remote", "add", "-f", "-t", branch, user, u)
	}

	idx := args.IndexOfParam(checkoutURL)
	args.RemoveParam(idx)
	args.InsertParam(idx, "--track", "-B", newBranchName, fmt.Sprintf("%s/%s", user, branch))

	return nil
}
Beispiel #4
0
/*
  $ gh create
  ... create repo on github ...
  > git remote add -f origin [email protected]:YOUR_USER/CURRENT_REPO.git

  # with description:
  $ gh create -d 'It shall be mine, all mine!'

  $ gh create recipes
  [ repo created on GitHub ]
  > git remote add origin [email protected]:YOUR_USER/recipes.git

  $ gh create sinatra/recipes
  [ repo created in GitHub organization ]
  > git remote add origin [email protected]:sinatra/recipes.git
*/
func create(command *Command, args *Args) {
	_, err := git.Dir()
	if err != nil {
		err = fmt.Errorf("'create' must be run from inside a git repository")
		utils.Check(err)
	}

	var newRepoName string
	if args.IsParamsEmpty() {
		newRepoName, err = utils.DirName()
		utils.Check(err)
	} else {
		reg := regexp.MustCompile("^[^-]")
		if !reg.MatchString(args.FirstParam()) {
			err = fmt.Errorf("invalid argument: %s", args.FirstParam())
			utils.Check(err)
		}
		newRepoName = args.FirstParam()
	}

	configs := github.CurrentConfigs()
	credentials := configs.DefaultCredentials()

	owner := credentials.User
	if strings.Contains(newRepoName, "/") {
		split := strings.SplitN(newRepoName, "/", 2)
		owner = split[0]
		newRepoName = split[1]
	}

	project := github.NewProject(owner, newRepoName, credentials.Host)
	gh := github.NewClient(project.Host)

	var action string
	if gh.IsRepositoryExist(project) {
		fmt.Printf("%s already exists on %s\n", project, project.Host)
		action = "set remote origin"
	} else {
		action = "created repository"
		if !args.Noop {
			repo, err := gh.CreateRepository(project, flagCreateDescription, flagCreateHomepage, flagCreatePrivate)
			utils.Check(err)
			project = github.NewProject(repo.FullName, "", project.Host)
		}
	}

	remote, _ := github.OriginRemote()
	if remote == nil {
		url := project.GitURL("", "", true)
		args.Replace("git", "remote", "add", "-f", "origin", url)
	} else {
		args.Replace("git", "remote", "-v")
	}

	args.After("echo", fmt.Sprintf("%s:", action), project.String())
}
Beispiel #5
0
func runInLocalRepo(fn func(localRepo *github.GitHubRepo, project *github.Project, client *github.Client)) {
	localRepo := github.LocalRepo()
	project, err := localRepo.CurrentProject()
	utils.Check(err)

	client := github.NewClient(project.Host)
	fn(localRepo, project, client)

	os.Exit(0)
}
Beispiel #6
0
func transformMergeArgs(args *Args) error {
	words := args.Words()
	if len(words) == 0 {
		return nil
	}

	mergeURL := words[0]
	url, err := github.ParseURL(mergeURL)
	if err != nil {
		return nil
	}

	pullURLRegex := regexp.MustCompile("^pull/(\\d+)")
	projectPath := url.ProjectPath()
	if !pullURLRegex.MatchString(projectPath) {
		return nil
	}

	id := pullURLRegex.FindStringSubmatch(projectPath)[1]
	gh := github.NewClient(url.Project.Host)
	pullRequest, err := gh.PullRequest(url.Project, id)
	if err != nil {
		return err
	}

	user, branch := parseUserBranchFromPR(pullRequest)
	if pullRequest.Head.Repo.ID == 0 {
		return fmt.Errorf("Error: %s's fork is not available anymore", user)
	}

	u := url.GitURL("", user, pullRequest.Head.Repo.Private)
	mergeHead := fmt.Sprintf("%s/%s", user, branch)
	ref := fmt.Sprintf("+refs/heads/%s:refs/remotes/%s", branch, mergeHead)
	args.Before("git", "fetch", u, ref)

	// Remove pull request URL
	idx := args.IndexOfParam(mergeURL)
	args.RemoveParam(idx)

	mergeMsg := fmt.Sprintf(`"Merge pull request #%v from %s\n\n%s"`, id, mergeHead, pullRequest.Title)
	args.AppendParams(mergeHead, "-m", mergeMsg)

	if args.IndexOfParam("--ff-only") == -1 {
		i := args.IndexOfParam("-m")
		args.InsertParam(i, "--no-ff")
	}

	return nil
}
Beispiel #7
0
/*
  $ gh fork
  [ repo forked on GitHub ]
  > git remote add -f YOUR_USER [email protected]:YOUR_USER/CURRENT_REPO.git

  $ gh fork --no-remote
  [ repo forked on GitHub ]
*/
func fork(cmd *Command, args *Args) {
	localRepo := github.LocalRepo()

	project, err := localRepo.MainProject()
	utils.Check(err)

	configs := github.CurrentConfigs()
	credentials := configs.PromptFor(project.Host)
	forkProject := github.NewProject(credentials.User, project.Name, project.Host)

	client := github.NewClient(project.Host)
	existingRepo, err := client.Repository(forkProject)
	if err == nil {
		var parentURL *github.URL
		if parent := existingRepo.Parent; parent != nil {
			parentURL, _ = github.ParseURL(parent.HTMLURL)
		}
		if parentURL == nil || !reflect.DeepEqual(parentURL.Project, project) {
			err = fmt.Errorf("Error creating fork: %s already exists on %s",
				forkProject, forkProject.Host)
			utils.Check(err)
		}
	} else {
		if !args.Noop {
			_, err := client.ForkRepository(project)
			utils.Check(err)
		}
	}

	if flagForkNoRemote {
		os.Exit(0)
	} else {
		u := forkProject.GitURL("", "", true)
		args.Replace("git", "remote", "add", "-f", forkProject.Owner, u)
		args.After("echo", fmt.Sprintf("new remote: %s", forkProject.Owner))
	}
}
Beispiel #8
0
/*
  # while on a topic branch called "feature":
  $ gh pull-request
  [ opens text editor to edit title & body for the request ]
  [ opened pull request on GitHub for "YOUR_USER:feature" ]

  # explicit pull base & head:
  $ gh pull-request -b jingweno:master -h jingweno:feature

  $ gh pull-request -m "title\n\nbody"
  [ create pull request with title & body  ]

  $ gh pull-request -i 123
  [ attached pull request to issue #123 ]

  $ gh pull-request https://github.com/jingweno/gh/pull/123
  [ attached pull request to issue #123 ]

  $ gh pull-request -F FILE
  [ create pull request with title & body from FILE ]
*/
func pullRequest(cmd *Command, args *Args) {
	localRepo := github.LocalRepo()

	currentBranch, err := localRepo.CurrentBranch()
	utils.Check(err)

	baseProject, err := localRepo.MainProject()
	utils.Check(err)

	client := github.NewClient(baseProject.Host)

	trackedBranch, headProject, err := localRepo.RemoteBranchAndProject(client.Credentials.User)
	utils.Check(err)

	var (
		base, head string
		force      bool
	)

	force = flagPullRequestForce

	if flagPullRequestBase != "" {
		baseProject, base = parsePullRequestProject(baseProject, flagPullRequestBase)
	}

	if flagPullRequestHead != "" {
		headProject, head = parsePullRequestProject(headProject, flagPullRequestHead)
	}

	if args.ParamsSize() == 1 {
		arg := args.RemoveParam(0)
		flagPullRequestIssue = parsePullRequestIssueNumber(arg)
	}

	if base == "" {
		masterBranch := localRepo.MasterBranch()
		base = masterBranch.ShortName()
	}

	if head == "" {
		if !trackedBranch.IsRemote() {
			// the current branch tracking another branch
			// pretend there's no upstream at all
			trackedBranch = nil
		} else {
			if reflect.DeepEqual(baseProject, headProject) && base == trackedBranch.ShortName() {
				e := fmt.Errorf(`Aborted: head branch is the same as base ("%s")`, base)
				e = fmt.Errorf("%s\n(use `-h <branch>` to specify an explicit pull request head)", e)
				utils.Check(e)
			}
		}

		if trackedBranch == nil {
			head = currentBranch.ShortName()
		} else {
			head = trackedBranch.ShortName()
		}
	}

	title, body, err := getTitleAndBodyFromFlags(flagPullRequestMessage, flagPullRequestFile)
	utils.Check(err)

	fullBase := fmt.Sprintf("%s:%s", baseProject.Owner, base)
	fullHead := fmt.Sprintf("%s:%s", headProject.Owner, head)

	if !force && trackedBranch != nil {
		remoteCommits, _ := git.RefList(trackedBranch.LongName(), "")
		if len(remoteCommits) > 0 {
			err = fmt.Errorf("Aborted: %d commits are not yet pushed to %s", len(remoteCommits), trackedBranch.LongName())
			err = fmt.Errorf("%s\n(use `-f` to force submit a pull request anyway)", err)
			utils.Check(err)
		}
	}

	if title == "" && flagPullRequestIssue == "" {
		commits, _ := git.RefList(base, head)
		title, body, err = writePullRequestTitleAndBody(base, head, fullBase, fullHead, commits)
		utils.Check(err)
	}

	if title == "" && flagPullRequestIssue == "" {
		utils.Check(fmt.Errorf("Aborting due to empty pull request title"))
	}

	var pullRequestURL string
	if args.Noop {
		args.Before(fmt.Sprintf("Would request a pull request to %s from %s", fullBase, fullHead), "")
		pullRequestURL = "PULL_REQUEST_URL"
	} else {
		if title != "" {
			pr, err := client.CreatePullRequest(baseProject, base, fullHead, title, body)
			utils.Check(err)
			pullRequestURL = pr.HTMLURL
		}

		if flagPullRequestIssue != "" {
			pr, err := client.CreatePullRequestForIssue(baseProject, base, fullHead, flagPullRequestIssue)
			utils.Check(err)
			pullRequestURL = pr.HTMLURL
		}
	}

	args.Replace("echo", "", pullRequestURL)
	if flagPullRequestIssue != "" {
		args.After("echo", "Warning: Issue to pull request conversion is deprecated and might not work in the future.")
	}
}