11package main
22
33import (
4- "net/http"
54 "net/url"
65 "path"
76 "strings"
@@ -41,54 +40,51 @@ func browse(cfg grit.Config, idx *index.Index, c *cli.Context) error {
4140 Path : strings .TrimSuffix (ep .Path , ".git" ),
4241 }
4342
44- r , err := git .PlainOpen (dir )
45- if err != nil {
43+ if err := injectGitHubTreeViewPath (& u , dir ); err != nil {
4644 return err
4745 }
4846
49- // If we can determine the "HEAD" of the local clone, open the tree view for
50- // that commit. Otherwise, open the repository's root.
51- if head , err := r .Head (); err == nil {
52- // If the head's name is "HEAD", it's a detached HEAD. If the HEAD
53- // refers to a branch, the name will be the reference to that branch.
54- if head .Name () == "HEAD" {
55- // In this case, we check to see if there is a singular tag that
56- // refers to the commit, and if so open the tree for the tag name.
57- //
58- // This is purely for UX, as the user probably expects to see the
59- // tag name in the URL.
60- head = resolveUniqueTag (r , head )
61- }
47+ writef (c , "opening %s" , u .String ())
6248
63- // If we still have a detached head, load the tree view for the commit
64- // hash; we have no more user-friendly tag or branch name.
65- ref := head .Name ().Short ()
66- if ref == "HEAD" {
67- ref = head .Hash ().String ()
68- }
49+ return open .Run (u .String ())
50+ }
6951
70- orig := u .Path
71- u .Path = path .Join (u .Path , "tree" , ref )
52+ func injectGitHubTreeViewPath (u * url.URL , dir string ) error {
53+ // HACK: Assume anything with github in the host is either GitHub.com or a
54+ // GitHub Enterprise Server installation.
55+ if ! strings .Contains (u .Host , "github" ) {
56+ return nil
57+ }
7258
73- // Check if the target URL actually exists, and if not, revert to the
74- // original path.
75- res , err := http .Head (u .String ())
76- if err != nil || res .StatusCode < http .StatusOK || res .StatusCode >= http .StatusBadRequest {
77- u .Path = orig
78- }
59+ r , err := git .PlainOpen (dir )
60+ if err != nil {
61+ return err
7962 }
8063
81- writef (c , "opening %s" , u .String ())
64+ head , err := r .Head ()
65+ if err != nil {
66+ // Most likely a repository with no commits, but we don't want this to
67+ // prevent the user from opening the repository in the browser.
68+ return nil
69+ }
8270
83- return open .Run (u .String ())
71+ if branch , err := r .Branch (head .Name ().Short ()); err == nil {
72+ if branch .Remote != "" {
73+ u .Path = path .Join (u .Path , "tree" , branch .Name )
74+ }
75+ } else if tag , ok := resolveUniqueTag (r , head ); ok {
76+ u .Path = path .Join (u .Path , "tree" , tag .Name ().Short ())
77+ }
78+
79+ return nil
8480}
8581
8682// resolveUniqueTag returns the reference to a tag that refers to ref, if
8783// exactly one exists; otherwise, it returns ref.
88- func resolveUniqueTag (r * git.Repository , ref * plumbing.Reference ) * plumbing.Reference {
84+ func resolveUniqueTag (r * git.Repository , ref * plumbing.Reference ) ( * plumbing.Reference , bool ) {
8985 tags , err := r .Tags ()
9086 if err != nil {
91- return ref
87+ return ref , false
9288 }
9389 defer tags .Close ()
9490
@@ -111,8 +107,8 @@ func resolveUniqueTag(r *git.Repository, ref *plumbing.Reference) *plumbing.Refe
111107 )
112108
113109 if len (refs ) == 1 {
114- return refs [0 ]
110+ return refs [0 ], true
115111 }
116112
117- return ref
113+ return ref , false
118114}
0 commit comments