1package commands
2
3import (
4	"fmt"
5	"net/url"
6	"strings"
7
8	"github.com/github/hub/github"
9	"github.com/github/hub/utils"
10)
11
12var cmdBrowse = &Command{
13	Run:   browse,
14	Usage: "browse [-uc] [[<USER>/]<REPOSITORY>|--] [<SUBPAGE>]",
15	Long: `Open a GitHub repository in a web browser.
16
17## Options:
18	-u, --url
19		Print the URL instead of opening it.
20
21	-c, --copy
22		Put the URL in clipboard instead of opening it.
23
24	[<USER>/]<REPOSITORY>
25		Defaults to repository in the current working directory.
26
27	<SUBPAGE>
28		One of "wiki", "commits", "issues", or other (default: "tree").
29
30## Examples:
31		$ hub browse
32		> open https://github.com/REPO
33
34		$ hub browse -- issues
35		> open https://github.com/REPO/issues
36
37		$ hub browse jingweno/gh
38		> open https://github.com/jingweno/gh
39
40		$ hub browse gh wiki
41		> open https://github.com/USER/gh/wiki
42
43## See also:
44
45hub-compare(1), hub(1)
46`,
47}
48
49func init() {
50	CmdRunner.Use(cmdBrowse)
51}
52
53func browse(command *Command, args *Args) {
54	var (
55		dest    string
56		subpage string
57		path    string
58		project *github.Project
59		branch  *github.Branch
60		err     error
61	)
62
63	if !args.IsParamsEmpty() {
64		dest = args.RemoveParam(0)
65	}
66
67	if !args.IsParamsEmpty() {
68		subpage = args.RemoveParam(0)
69	}
70
71	if args.Terminator {
72		subpage = dest
73		dest = ""
74	}
75
76	localRepo, _ := github.LocalRepo()
77	if dest != "" {
78		project = github.NewProject("", dest, "")
79		branch = localRepo.MasterBranch()
80	} else if subpage != "" && subpage != "commits" && subpage != "tree" && subpage != "blob" && subpage != "settings" {
81		project, err = localRepo.MainProject()
82		branch = localRepo.MasterBranch()
83		utils.Check(err)
84	} else {
85		currentBranch, err := localRepo.CurrentBranch()
86		if err != nil {
87			currentBranch = localRepo.MasterBranch()
88		}
89
90		var owner string
91		mainProject, err := localRepo.MainProject()
92		if err == nil {
93			host, err := github.CurrentConfig().PromptForHost(mainProject.Host)
94			if err != nil {
95				utils.Check(github.FormatError("in browse", err))
96			} else {
97				owner = host.User
98			}
99		}
100
101		branch, project, _ = localRepo.RemoteBranchAndProject(owner, currentBranch.IsMaster())
102		if branch == nil {
103			branch = localRepo.MasterBranch()
104		}
105	}
106
107	if project == nil {
108		utils.Check(command.UsageError(""))
109	}
110
111	if subpage == "commits" {
112		path = fmt.Sprintf("commits/%s", branchInURL(branch))
113	} else if subpage == "tree" || subpage == "" {
114		if !branch.IsMaster() {
115			path = fmt.Sprintf("tree/%s", branchInURL(branch))
116		}
117	} else {
118		path = subpage
119	}
120
121	pageUrl := project.WebURL("", "", path)
122
123	args.NoForward()
124	flagBrowseURLPrint := args.Flag.Bool("--url")
125	flagBrowseURLCopy := args.Flag.Bool("--copy")
126	printBrowseOrCopy(args, pageUrl, !flagBrowseURLPrint && !flagBrowseURLCopy, flagBrowseURLCopy)
127}
128
129func branchInURL(branch *github.Branch) string {
130	parts := strings.Split(branch.ShortName(), "/")
131	newPath := make([]string, len(parts))
132	for i, s := range parts {
133		newPath[i] = url.QueryEscape(s)
134	}
135	return strings.Join(newPath, "/")
136}
137