diff --git a/lib/mod/cache/fetch.go b/lib/mod/cache/fetch.go index 3e9591fcf..64f95cb2b 100644 --- a/lib/mod/cache/fetch.go +++ b/lib/mod/cache/fetch.go @@ -14,7 +14,7 @@ import ( "github.com/hofstadter-io/hof/lib/yagu/repos/gitlab" ) -func Fetch(lang, mod, ver string) (err error) { +func Fetch(lang, mod, ver, pev string) (err error) { remote, owner, repo := parseModURL(mod) tag := ver @@ -26,7 +26,8 @@ func Fetch(lang, mod, ver string) (err error) { return err } // not found, try fetching deps - if err := fetch(lang, mod, ver); err != nil { + private := MatchPrefixPatterns(os.Getenv(pev), mod) + if err := fetch(lang, mod, ver, private); err != nil { return err } } @@ -37,25 +38,24 @@ func Fetch(lang, mod, ver string) (err error) { return nil } -func fetch(lang, mod, ver string) error { +func fetch(lang, mod, ver string, private bool) error { remote, owner, repo := parseModURL(mod) tag := ver - switch remote { - case "github.com": + if private { + return fetchGit(lang, remote, owner, repo, tag, true) + } else if remote == "github.com" { return fetchGitHub(lang, owner, repo, tag) - case "gitlab.com": + } else if remote == "gitlab.com" { return fetchGitLab(lang, owner, repo, tag) - default: - return fetchGit(lang, remote, owner, repo, tag) } + return fetchGit(lang, remote, owner, repo, tag, private) } -func fetchGit(lang, remote, owner, repo, tag string) error { +func fetchGit(lang, remote, owner, repo, tag string, private bool) error { FS := memfs.New() - // TODO retreive private config - if err := git.FetchGit(FS, remote, owner, repo, tag, false); err != nil { + if err := git.FetchGit(FS, remote, owner, repo, tag, private); err != nil { return fmt.Errorf("While fetching from git\n%w\n", err) } diff --git a/lib/mod/cache/util.go b/lib/mod/cache/util.go index 5a2f80c43..52f61a7b3 100644 --- a/lib/mod/cache/util.go +++ b/lib/mod/cache/util.go @@ -1,6 +1,9 @@ package cache -import "strings" +import ( + "path" + "strings" +) func parseModURL(mod string) (remote, owner, repo string) { var flds []string @@ -12,3 +15,49 @@ func parseModURL(mod string) (remote, owner, repo string) { return flds[0], flds[1], flds[2] } + +// MatchPrefixPatterns reports whether any path prefix of target matches one of +// the glob patterns (as defined by path.Match) in the comma-separated globs +// list. This implements the algorithm used when matching a module path to the +// GOPRIVATE environment variable, as described by 'go help module-private'. +// +// It ignores any empty or malformed patterns in the list. +func MatchPrefixPatterns(globs, target string) bool { + for globs != "" { + // Extract next non-empty glob in comma-separated list. + var glob string + if i := strings.Index(globs, ","); i >= 0 { + glob, globs = globs[:i], globs[i+1:] + } else { + glob, globs = globs, "" + } + if glob == "" { + continue + } + + // A glob with N+1 path elements (N slashes) needs to be matched + // against the first N+1 path elements of target, + // which end just before the N+1'th slash. + n := strings.Count(glob, "/") + prefix := target + // Walk target, counting slashes, truncating at the N+1'th slash. + for i := 0; i < len(target); i++ { + if target[i] == '/' { + if n == 0 { + prefix = target[:i] + break + } + n-- + } + } + if n > 0 { + // Not enough prefix elements. + continue + } + matched, _ := path.Match(glob, prefix) + if matched { + return true + } + } + return false +} diff --git a/lib/mod/langs/cue.go b/lib/mod/langs/cue.go index 264d28cf1..e475a5812 100644 --- a/lib/mod/langs/cue.go +++ b/lib/mod/langs/cue.go @@ -1,13 +1,14 @@ package langs const CuelangModder = ` -langs: cue: { - Name: "cue" - Version: "v0.4.0" - ModFile: "cue.mods" - SumFile: "cue.sums" - ModsDir: "cue.mod/pkg" - MappingFile: "cue.mod/modules.txt" +cue: { + Name: "cue" + Version: "v0.4.0" + ModFile: "cue.mods" + SumFile: "cue.sums" + ModsDir: "cue.mod/pkg" + MappingFile: "cue.mod/modules.txt" + PrivateEnvVar: "CUEPRIVATE" InitTemplates: { "cue.mod/module.cue": """ module: "{{ .Module }}" diff --git a/lib/mod/langs/go.go b/lib/mod/langs/go.go index 3c504fa21..1b55b663d 100644 --- a/lib/mod/langs/go.go +++ b/lib/mod/langs/go.go @@ -8,6 +8,7 @@ langs: go: { SumFile: "go.sum", ModsDir: "vendor", MappingFile: "vendor/modules.txt", + PrivateEnvVar: "GOPRIVATE" CommandInit: [["go", "mod", "init"]], CommandGraph: [["go", "mod", "graph"]], CommandTidy: [["go", "mod", "tidy"]], diff --git a/lib/mod/modder/modder.go b/lib/mod/modder/modder.go index d5c9ed69e..f306242a0 100644 --- a/lib/mod/modder/modder.go +++ b/lib/mod/modder/modder.go @@ -20,10 +20,11 @@ type Modder struct { Version string `yaml:"Version",omitempty` // Module information - ModFile string `yaml:"ModFile",omitempty` - SumFile string `yaml:"SumFile",omitempty` - ModsDir string `yaml:"ModsDir",omitempty` - MappingFile string `yaml:"MappingFile",omitempty` + ModFile string `yaml:"ModFile",omitempty` + SumFile string `yaml:"SumFile",omitempty` + ModsDir string `yaml:"ModsDir",omitempty` + MappingFile string `yaml:"MappingFile",omitempty` + PrivateEnvVar string `yaml:"PrivateEnvVar",omitempty` // Commands override default, configuragble processing // for things like golang diff --git a/lib/mod/modder/modder_vendor.go b/lib/mod/modder/modder_vendor.go index 7768e8f2d..cf84031a0 100644 --- a/lib/mod/modder/modder_vendor.go +++ b/lib/mod/modder/modder_vendor.go @@ -140,7 +140,7 @@ func (mdr *Modder) LoadRemoteModule(R Replace) error { m.Version = R.NewVersion } - err := cache.Fetch(mdr.Name, R.NewPath, R.NewVersion) + err := cache.Fetch(mdr.Name, R.NewPath, R.NewVersion, mdr.PrivateEnvVar) if err != nil { return err } diff --git a/lib/yagu/repos/git/fetch.go b/lib/yagu/repos/git/fetch.go index 16e3714f5..3ecd7a824 100644 --- a/lib/yagu/repos/git/fetch.go +++ b/lib/yagu/repos/git/fetch.go @@ -104,16 +104,16 @@ func FetchGit(FS billy.Filesystem, remote, owner, repo, tag string, private bool } if private { - if netrc, err := NetrcCredentials(remote); err != nil { + if netrc, err := NetrcCredentials(remote); err == nil { gco.Auth = &http.BasicAuth{ Username: netrc.Login, Password: netrc.Password, } - } else if ssh, err := SSHCredentials(remote); err != nil { + } else if ssh, err := SSHCredentials(remote); err == nil { gco.Auth = ssh.Keys gco.URL = fmt.Sprintf("%s@%s:%s/%s", ssh.User, remote, owner, repo) } else { - return err + gco.URL = fmt.Sprintf("%s@%s:%s/%s", "git", remote, owner, repo) } } diff --git a/lib/yagu/repos/git/netrc.go b/lib/yagu/repos/git/netrc.go index 80c045ce6..7e471f87d 100644 --- a/lib/yagu/repos/git/netrc.go +++ b/lib/yagu/repos/git/netrc.go @@ -33,7 +33,9 @@ func NetrcMachines() map[string]NetrcMachine { } func NetrcCredentials(machine string) (NetrcMachine, error) { - if cred, ok := netrc[machine]; ok { + machines := NetrcMachines() + + if cred, ok := machines[machine]; ok { return cred, nil } diff --git a/lib/yagu/repos/github/client.go b/lib/yagu/repos/github/client.go index e0340cf32..fe083c325 100644 --- a/lib/yagu/repos/github/client.go +++ b/lib/yagu/repos/github/client.go @@ -9,10 +9,12 @@ import ( "github.com/google/go-github/v30/github" ) +const TokenEnv = "GITHUB_TOKEN" + func NewClient() (client *github.Client, err error) { ctx := context.Background() - if token := os.Getenv("GITHUB_TOKEN"); token != "" { + if token := os.Getenv(TokenEnv); token != "" { ts := oauth2.StaticTokenSource( &oauth2.Token{AccessToken: token}, ) diff --git a/lib/yagu/repos/gitlab/client.go b/lib/yagu/repos/gitlab/client.go index 6a95e711a..157cc6783 100644 --- a/lib/yagu/repos/gitlab/client.go +++ b/lib/yagu/repos/gitlab/client.go @@ -6,6 +6,8 @@ import ( "github.com/xanzy/go-gitlab" ) +const TokenEnv = "GITLAB_TOKEN" + func NewClient() (client *gitlab.Client, err error) { - return gitlab.NewClient(os.Getenv("GITLAB_TOKEN")) + return gitlab.NewClient(os.Getenv(TokenEnv)) }