github.com/goreleaser/goreleaser@v1.25.1/internal/git/config.go (about) 1 package git 2 3 import ( 4 "context" 5 "errors" 6 "fmt" 7 "net/url" 8 "path" 9 "strings" 10 11 "github.com/caarlos0/log" 12 "github.com/goreleaser/goreleaser/pkg/config" 13 ) 14 15 // ExtractRepoFromConfig gets the repo name from the Git config. 16 func ExtractRepoFromConfig(ctx context.Context) (result config.Repo, err error) { 17 if !IsRepo(ctx) { 18 return result, errors.New("current folder is not a git repository") 19 } 20 out, err := Clean(Run(ctx, "ls-remote", "--get-url")) 21 if err != nil { 22 return result, fmt.Errorf("no remote configured to list refs from") 23 } 24 // This is a relative remote URL and requires some additional processing 25 if out == "." { 26 return extractRelativeRepoFromConfig(ctx) 27 } 28 log.WithField("rawurl", out).Debugf("got git url") 29 return ExtractRepoFromURL(out) 30 } 31 32 func extractRelativeRepoFromConfig(ctx context.Context) (result config.Repo, err error) { 33 out, err := Clean(Run(ctx, "rev-parse", "--abbrev-ref", "--symbolic-full-name", "@{u}")) 34 if err != nil || out == "" { 35 return result, fmt.Errorf("unable to get upstream while qualifying relative remote") 36 } 37 out, err = Clean(Run(ctx, "config", "--get", fmt.Sprintf("branch.%s.remote", out))) 38 if err != nil || out == "" { 39 return result, fmt.Errorf("unable to get upstream's remote while qualifying relative remote") 40 } 41 out, err = Clean(Run(ctx, "ls-remote", "--get-url", out)) 42 if err != nil { 43 return result, fmt.Errorf("unable to get upstream while qualifying relative remote") 44 } 45 return ExtractRepoFromURL(out) 46 } 47 48 func ExtractRepoFromURL(rawurl string) (config.Repo, error) { 49 // removes the .git suffix and any new lines 50 s := strings.TrimSuffix(strings.TrimSpace(rawurl), ".git") 51 52 // if the URL contains a :, indicating a SSH config, 53 // remove all chars until it, including itself 54 // on HTTP and HTTPS URLs it will remove the http(s): prefix, 55 // which is ok. On SSH URLs the whole user@server will be removed, 56 // which is required. 57 58 // If the url contains more than 1 ':' character, assume we are doing an 59 // http URL with a username/password in it, and normalize the URL. 60 // Gitlab-CI uses this type of URL 61 if strings.Count(s, ":") == 1 { 62 s = s[strings.LastIndex(s, ":")+1:] 63 } 64 65 // now we can parse it with net/url 66 u, err := url.Parse(s) 67 if err != nil { 68 return config.Repo{ 69 RawURL: rawurl, 70 }, err 71 } 72 73 // split the parsed url path by /, the last parts should be the owner and name 74 ss := strings.Split(strings.TrimPrefix(u.Path, "/"), "/") 75 76 // if empty, returns an error 77 if len(ss) == 0 || ss[0] == "" { 78 return config.Repo{ 79 RawURL: rawurl, 80 }, fmt.Errorf("unsupported repository URL: %s", rawurl) 81 } 82 83 // if less than 2 parts, its likely not a valid repository, but we'll allow it. 84 if len(ss) < 2 { 85 return config.Repo{ 86 RawURL: rawurl, 87 Owner: ss[0], 88 }, nil 89 } 90 repo := config.Repo{ 91 RawURL: rawurl, 92 Owner: path.Join(ss[:len(ss)-1]...), 93 Name: ss[len(ss)-1], 94 } 95 log.WithField("owner", repo.Owner).WithField("name", repo.Name).Debugf("parsed url") 96 return repo, nil 97 }