Exemple #1
0
func ciStatus(cmd *Command, args *Args) {
	ref := "HEAD"
	if !args.IsParamsEmpty() {
		ref = args.RemoveParam(0)
	}

	localRepo, err := github.LocalRepo()
	utils.Check(err)

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

	sha, err := git.Ref(ref)
	if err != nil {
		err = fmt.Errorf("Aborted: no revision could be determined from '%s'", ref)
	}
	utils.Check(err)

	if args.Noop {
		ui.Printf("Would request CI status for %s\n", sha)
	} else {
		gh := github.NewClient(project.Host)
		response, err := gh.FetchCIStatus(project, sha)
		utils.Check(err)

		state := response.State
		if len(response.Statuses) == 0 {
			state = ""
		}

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

		if flagCiStatusVerbose && len(response.Statuses) > 0 {
			verboseFormat(response.Statuses)
		} else {
			if state != "" {
				ui.Println(state)
			} else {
				ui.Println("no status")
			}
		}

		os.Exit(exitCode)
	}
}
Exemple #2
0
func runVersion(cmd *Command, args *Args) {
	gitVersion, err := git.Version()
	utils.Check(err)

	ghVersion := fmt.Sprintf("hub version %s", Version)

	ui.Println(gitVersion)
	ui.Println(ghVersion)

	os.Exit(0)
}
Exemple #3
0
/*
  $ gh ci-status
  > (prints CI state of HEAD and exits with appropriate code)
  > One of: success (0), error (1), failure (1), pending (2), no status (3)

  $ gh ci-status -v
  > (prints CI state of HEAD, the URL to the CI build results and exits with appropriate code)
  > One of: success (0), error (1), failure (1), pending (2), no status (3)

  $ gh ci-status BRANCH
  > (prints CI state of BRANCH and exits with appropriate code)
  > One of: success (0), error (1), failure (1), pending (2), no status (3)

  $ gh ci-status SHA
  > (prints CI state of SHA and exits with appropriate code)
  > One of: success (0), error (1), failure (1), pending (2), no status (3)
*/
func ciStatus(cmd *Command, args *Args) {
	ref := "HEAD"
	if !args.IsParamsEmpty() {
		ref = args.RemoveParam(0)
	}

	localRepo, err := github.LocalRepo()
	utils.Check(err)

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

	sha, err := git.Ref(ref)
	if err != nil {
		err = fmt.Errorf("Aborted: no revision could be determined from '%s'", ref)
	}
	utils.Check(err)

	if args.Noop {
		ui.Printf("Would request CI status for %s\n", sha)
	} else {
		state, targetURL, exitCode, err := fetchCiStatus(project, sha)
		utils.Check(err)
		if flagCiStatusVerbose && targetURL != "" {
			ui.Printf("%s: %s\n", state, targetURL)
		} else {
			ui.Println(state)
		}

		os.Exit(exitCode)
	}
}
Exemple #4
0
func (updater *Updater) PromptForUpdate() (err error) {
	config := autoUpdateConfig()
	if config == "never" || !updater.timeToUpdate() {
		return
	}

	releaseName, version := updater.latestReleaseNameAndVersion()
	if version != "" && version != updater.CurrentVersion {
		switch config {
		case "always":
			err = updater.updateTo(releaseName, version)
		default:
			ui.Println("There is a newer version of hub available.")
			ui.Printf("Would you like to update? ([Y]es/[N]o/[A]lways/N[e]ver): ")
			var confirm string
			fmt.Scan(&confirm)

			always := utils.IsOption(confirm, "a", "always")
			if always || utils.IsOption(confirm, "y", "yes") {
				err = updater.updateTo(releaseName, version)
			}

			saveAutoUpdateConfiguration(confirm, always)
		}
	}

	return
}
Exemple #5
0
func (c *Command) PrintUsage() {
	if c.Runnable() {
		ui.Printf("usage: %s\n\n", c.FormattedUsage())
	}

	ui.Println(strings.Trim(c.Long, "\n"))
}
Exemple #6
0
func runHelp(helpCmd *Command, args *Args) {
	if args.IsParamsEmpty() {
		printUsage()
		os.Exit(0)
	}

	if args.HasFlags("-a", "--all") {
		args.After("echo", "\nhub custom commands\n")
		args.After("echo", " ", strings.Join(customCommands(), "  "))
		return
	}

	command := args.FirstParam()

	if command == "hub" {
		err := displayManPage("hub.1", args)
		if err != nil {
			utils.Check(err)
		}
	}

	if c := lookupCmd(command); c != nil {
		if !args.HasFlags("--plain-text") {
			manPage := fmt.Sprintf("hub-%s.1", c.Name())
			err := displayManPage(manPage, args)
			if err == nil {
				return
			}
		}

		ui.Println(c.HelpText())
		os.Exit(0)
	}
}
Exemple #7
0
func (updater *Updater) Update() (err error) {
	config := autoUpdateConfig()
	if config == "never" {
		ui.Println("Update is disabled")
		return
	}

	releaseName, version := updater.latestReleaseNameAndVersion()
	if version == "" {
		ui.Println("There is no newer version of hub available.")
		return
	}

	if version == updater.CurrentVersion {
		ui.Printf("You're already on the latest version: %s\n", version)
	} else {
		err = updater.updateTo(releaseName, version)
	}

	return
}
Exemple #8
0
func showRelease(cmd *Command, args *Args) {
	tagName := cmd.Arg(0)
	if tagName == "" {
		utils.Check(fmt.Errorf("Missing argument TAG"))
	}

	localRepo, err := github.LocalRepo()
	utils.Check(err)

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

	gh := github.NewClient(project.Host)

	if args.Noop {
		ui.Printf("Would display information for `%s' release\n", tagName)
	} else {
		release, err := gh.FetchRelease(project, tagName)
		utils.Check(err)

		body := strings.TrimSpace(release.Body)

		ui.Println(release.Name)
		if body != "" {
			ui.Printf("\n%s\n", body)
		}
		if flagReleaseShowDownloads {
			ui.Printf("\n## Downloads\n\n")
			for _, asset := range release.Assets {
				ui.Println(asset.DownloadUrl)
			}
			if release.ZipballUrl != "" {
				ui.Println(release.ZipballUrl)
				ui.Println(release.TarballUrl)
			}
		}
	}

	args.NoForward()
}
Exemple #9
0
func report(reportedError error, stack string) {
	title, body, err := reportTitleAndBody(reportedError, stack)
	utils.Check(err)

	project := NewProject(hubProjectOwner, hubProjectName, GitHubHost)

	gh := NewClient(project.Host)

	issue, err := gh.CreateIssue(project, title, body, []string{"Crash Report"})
	utils.Check(err)

	ui.Println(issue.HTMLURL)
}
Exemple #10
0
func release(cmd *Command, args *Args) {
	runInLocalRepo(func(localRepo *github.GitHubRepo, project *github.Project, client *github.Client) {
		if args.Noop {
			ui.Printf("Would request list of releases for %s\n", project)
		} else {
			releases, err := client.Releases(project)
			utils.Check(err)
			var outputs []string
			for _, release := range releases {
				out := fmt.Sprintf("%s (%s)\n%s", release.Name, release.TagName, release.Body)
				outputs = append(outputs, out)
			}

			ui.Println(strings.Join(outputs, "\n\n"))
		}
	})
}
Exemple #11
0
func report(reportedError error, stack string) {
	title, body, err := reportTitleAndBody(reportedError, stack)
	utils.Check(err)

	project := NewProject(hubProjectOwner, hubProjectName, GitHubHost)

	gh := NewClient(project.Host)

	params := map[string]interface{}{
		"title":  title,
		"body":   body,
		"labels": []string{"Crash Report"},
	}

	issue, err := gh.CreateIssue(project, params)
	utils.Check(err)

	ui.Println(issue.HtmlUrl)
}
Exemple #12
0
func (updater *Updater) updateTo(releaseName, version string) (err error) {
	ui.Printf("Updating gh to %s...\n", version)
	downloadURL := fmt.Sprintf("https://%s/github/hub/releases/download/%s/hub%s_%s_%s.zip", updater.Host, releaseName, version, runtime.GOOS, runtime.GOARCH)
	path, err := downloadFile(downloadURL)
	if err != nil {
		return
	}

	exec, err := unzipExecutable(path)
	if err != nil {
		return
	}

	err, _ = goupdate.New().FromFile(exec)
	if err == nil {
		ui.Println("Done!")
	}

	return
}
Exemple #13
0
func createIssue(cmd *Command, args *Args) {
	runInLocalRepo(func(localRepo *github.GitHubRepo, project *github.Project, gh *github.Client) {
		if args.Noop {
			ui.Printf("Would create an issue for %s\n", project)
		} else {
			title, body, err := getTitleAndBodyFromFlags(flagIssueMessage, flagIssueFile)
			utils.Check(err)

			if title == "" {
				title, body, err = writeIssueTitleAndBody(project)
				utils.Check(err)
			}

			issue, err := gh.CreateIssue(project, title, body, flagIssueLabels)
			utils.Check(err)

			ui.Println(issue.HTMLURL)
		}
	})
}
Exemple #14
0
func printBrowseOrCopy(args *Args, msg string, openBrowser bool, performCopy bool) {
	if performCopy {
		if err := clipboard.WriteAll(msg); err != nil {
			ui.Errorf("Error copying %s to clipboard:\n%s\n", msg, err.Error())
		}
	}

	if openBrowser {
		launcher, err := utils.BrowserLauncher()
		utils.Check(err)
		args.Replace(launcher[0], "", launcher[1:]...)
		args.AppendParams(msg)
	}

	if !openBrowser && !performCopy {
		args.AfterFn(func() error {
			ui.Println(msg)
			return nil
		})
	}
}
Exemple #15
0
func listReleases(cmd *Command, args *Args) {
	localRepo, err := github.LocalRepo()
	utils.Check(err)

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

	gh := github.NewClient(project.Host)

	if args.Noop {
		ui.Printf("Would request list of releases for %s\n", project)
	} else {
		releases, err := gh.FetchReleases(project)
		utils.Check(err)

		for _, release := range releases {
			if !release.Draft || flagReleaseIncludeDrafts {
				ui.Println(release.TagName)
			}
		}
	}

	args.NoForward()
}
Exemple #16
0
func createIssue(cmd *Command, args *Args) {
	localRepo, err := github.LocalRepo()
	utils.Check(err)

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

	gh := github.NewClient(project.Host)

	var title string
	var body string
	var editor *github.Editor

	if cmd.FlagPassed("message") {
		title, body = readMsg(flagIssueMessage)
	} else if cmd.FlagPassed("file") {
		title, body, err = readMsgFromFile(flagIssueFile)
		utils.Check(err)
	} else {
		cs := git.CommentChar()
		message := strings.Replace(fmt.Sprintf(`
# Creating an issue for %s
#
# Write a message for this issue. The first block of
# text is the title and the rest is the description.
`, project), "#", cs, -1)

		editor, err := github.NewEditor("ISSUE", "issue", message)
		utils.Check(err)

		title, body, err = editor.EditTitleAndBody()
		utils.Check(err)
	}

	if title == "" {
		utils.Check(fmt.Errorf("Aborting creation due to empty issue title"))
	}

	params := map[string]interface{}{
		"title":     title,
		"body":      body,
		"labels":    flagIssueLabels,
		"assignees": flagIssueAssignees,
	}

	if flagIssueMilestone > 0 {
		params["milestone"] = flagIssueMilestone
	}

	if args.Noop {
		ui.Printf("Would create issue `%s' for %s\n", params["title"], project)
		os.Exit(0)
	} else {
		issue, err := gh.CreateIssue(project, params)
		utils.Check(err)

		if editor != nil {
			editor.DeleteFile()
		}

		if flagIssueBrowse {
			launcher, err := utils.BrowserLauncher()
			utils.Check(err)
			args.Replace(launcher[0], "", launcher[1:]...)
			args.AppendParams(issue.HtmlUrl)
		} else {
			ui.Println(issue.HtmlUrl)
			os.Exit(0)
		}
	}
}
Exemple #17
0
func printError(err error, stack string) {
	ui.Printf("%v\n\n", err)
	ui.Println(stack)
}
Exemple #18
0
func createRelease(cmd *Command, args *Args) {
	if args.IsParamsEmpty() {
		utils.Check(fmt.Errorf("Missed argument TAG"))
		return
	}

	tag := args.LastParam()
	runInLocalRepo(func(localRepo *github.GitHubRepo, project *github.Project, client *github.Client) {
		release, err := client.Release(project, tag)
		utils.Check(err)

		if release == nil {
			commitish := flagReleaseCommitish
			if commitish == "" {
				currentBranch, err := localRepo.CurrentBranch()
				utils.Check(err)
				commitish = currentBranch.ShortName()
			}

			title, body, err := getTitleAndBodyFromFlags(flagReleaseMessage, flagReleaseFile)
			utils.Check(err)

			var editor *github.Editor
			if title == "" {
				cs := git.CommentChar()
				message, err := renderReleaseTpl(cs, tag, project.Name, commitish)
				utils.Check(err)

				editor, err = github.NewEditor("RELEASE", "release", message)
				utils.Check(err)

				title, body, err = editor.EditTitleAndBody()
				utils.Check(err)
			}

			params := octokit.ReleaseParams{
				TagName:         tag,
				TargetCommitish: commitish,
				Name:            title,
				Body:            body,
				Draft:           flagReleaseDraft,
				Prerelease:      flagReleasePrerelease,
			}
			release, err = client.CreateRelease(project, params)
			utils.Check(err)

			if editor != nil {
				defer editor.DeleteFile()
			}
		}

		if len(flagReleaseAssets) > 0 {
			paths := make([]string, 0)
			for _, asset := range flagReleaseAssets {
				finder := assetFinder{}
				p, err := finder.Find(asset)
				utils.Check(err)

				paths = append(paths, p...)
			}

			uploader := assetUploader{
				Client:  client,
				Release: release,
			}
			err = uploader.UploadAll(paths)
			if err != nil {
				ui.Println("")
				utils.Check(err)
			}
		}

		ui.Printf("\n%s\n", release.HTMLURL)
	})
}
Exemple #19
0
func alias(command *Command, args *Args) {
	var shell string
	if args.ParamsSize() > 0 {
		shell = args.FirstParam()
	} else {
		shell = os.Getenv("SHELL")
	}

	if shell == "" {
		cmd := "hub alias <shell>"
		if flagAliasScript {
			cmd = "hub alias -s <shell>"
		}
		utils.Check(fmt.Errorf("Error: couldn't detect shell type. Please specify your shell with `%s`", cmd))
	}

	shells := []string{"bash", "zsh", "sh", "ksh", "csh", "tcsh", "fish"}
	shell = filepath.Base(shell)
	var validShell bool
	for _, s := range shells {
		if s == shell {
			validShell = true
			break
		}
	}

	if !validShell {
		err := fmt.Errorf("hub alias: unsupported shell\nsupported shells: %s", strings.Join(shells, " "))
		utils.Check(err)
	}

	if flagAliasScript {
		var alias string
		switch shell {
		case "csh", "tcsh":
			alias = "alias git hub"
		default:
			alias = "alias git=hub"
		}

		ui.Println(alias)
	} else {
		var profile string
		switch shell {
		case "bash":
			profile = "~/.bash_profile"
		case "zsh":
			profile = "~/.zshrc"
		case "ksh":
			profile = "~/.profile"
		case "fish":
			profile = "~/.config/fish/config.fish"
		case "csh":
			profile = "~/.cshrc"
		case "tcsh":
			profile = "~/.tcshrc"
		default:
			profile = "your profile"
		}

		msg := fmt.Sprintf("# Wrap git automatically by adding the following to %s:\n", profile)
		ui.Println(msg)

		var eval string
		switch shell {
		case "fish":
			eval = `eval (hub alias -s)`
		case "csh", "tcsh":
			eval = "eval \"`hub alias -s`\""
		default:
			eval = `eval "$(hub alias -s)"`
		}
		ui.Println(eval)
	}

	os.Exit(0)
}
Exemple #20
0
func printCommands(cmds []*cmd.Cmd) {
	for _, c := range cmds {
		ui.Println(c)
	}
}
Exemple #21
0
func runVersion(cmd *Command, args *Args) {
	ui.Println(version.FullVersion())
	os.Exit(0)
}
Exemple #22
0
func createRelease(cmd *Command, args *Args) {
	tagName := cmd.Arg(0)
	if tagName == "" {
		utils.Check(fmt.Errorf("Missing argument TAG"))
		return
	}

	localRepo, err := github.LocalRepo()
	utils.Check(err)

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

	gh := github.NewClient(project.Host)

	commitish := flagReleaseCommitish
	if commitish == "" {
		currentBranch, err := localRepo.CurrentBranch()
		utils.Check(err)
		commitish = currentBranch.ShortName()
	}

	var title string
	var body string
	var editor *github.Editor

	if cmd.FlagPassed("message") {
		title, body = readMsg(flagReleaseMessage)
	} else if cmd.FlagPassed("file") {
		title, body, err = readMsgFromFile(flagReleaseFile)
		utils.Check(err)
	} else {
		cs := git.CommentChar()
		message, err := renderReleaseTpl("Creating", cs, tagName, project.String(), commitish)
		utils.Check(err)

		editor, err := github.NewEditor("RELEASE", "release", message)
		utils.Check(err)

		title, body, err = editor.EditTitleAndBody()
		utils.Check(err)
	}

	if title == "" {
		utils.Check(fmt.Errorf("Aborting release due to empty release title"))
	}

	params := &github.Release{
		TagName:         tagName,
		TargetCommitish: commitish,
		Name:            title,
		Body:            body,
		Draft:           flagReleaseDraft,
		Prerelease:      flagReleasePrerelease,
	}

	var release *github.Release

	if args.Noop {
		ui.Printf("Would create release `%s' for %s with tag name `%s'\n", title, project, tagName)
	} else {
		release, err = gh.CreateRelease(project, params)
		utils.Check(err)

		ui.Println(release.HtmlUrl)
	}

	uploadAssets(gh, release, flagReleaseAssets, args)

	if editor != nil {
		editor.DeleteFile()
	}
	os.Exit(0)
}
Exemple #23
0
func runVersion(cmd *Command, args *Args) {
	ui.Println(version.FullVersion())
	args.NoForward()
}
Exemple #24
0
func alias(command *Command, args *Args) {
	var shell string
	if args.ParamsSize() > 0 {
		shell = args.FirstParam()
	} else {
		shell = os.Getenv("SHELL")
	}

	if shell == "" {
		cmd := "hub alias <shell>"
		if flagAliasScript {
			cmd = "hub alias -s <shell>"
		}
		utils.Check(fmt.Errorf("Error: couldn't detect shell type. Please specify your shell with `%s`", cmd))
	}

	shells := []string{"bash", "zsh", "sh", "ksh", "csh", "tcsh", "fish"}
	shell = filepath.Base(shell)
	var validShell bool
	for _, s := range shells {
		if s == shell {
			validShell = true
			break
		}
	}

	if !validShell {
		err := fmt.Errorf("hub alias: unsupported shell\nsupported shells: %s", strings.Join(shells, " "))
		utils.Check(err)
	}

	if flagAliasScript {
		var alias string
		switch shell {
		case "csh", "tcsh":
			alias = "alias git hub"
		default:
			alias = "alias git=hub"
		}

		ui.Println(alias)
	} else {
		var profile string
		switch shell {
		case "bash":
			profile = "~/.bash_profile"
		case "zsh":
			profile = "~/.zshrc"
		case "ksh":
			profile = "~/.profile"
		case "fish":
			profile = "~/.config/fish/functions/git.fish"
		case "csh":
			profile = "~/.cshrc"
		case "tcsh":
			profile = "~/.tcshrc"
		default:
			profile = "your profile"
		}

		msg := fmt.Sprintf("# Wrap git automatically by adding the following to %s:\n", profile)
		ui.Println(msg)

		var eval string
		switch shell {
		case "fish":
			eval = `function git --description 'Alias for hub, which wraps git to provide extra functionality with GitHub.'
	hub $argv
end`
		case "csh", "tcsh":
			eval = "eval \"`hub alias -s`\""
		default:
			eval = `eval "$(hub alias -s)"`
		}

		indent := regexp.MustCompile(`(?m)^\t+`)
		eval = indent.ReplaceAllStringFunc(eval, func(match string) string {
			return strings.Repeat(" ", len(match)*4)
		})

		ui.Println(eval)
	}

	os.Exit(0)
}