diff options
author | Sunny <me@darkowlzz.space> | 2017-12-06 18:51:56 +0530 |
---|---|---|
committer | Máximo Cuadros <mcuadros@gmail.com> | 2017-12-06 14:21:56 +0100 |
commit | eb74b0e1a0ae20075435aded41bffc522bc3554c (patch) | |
tree | 573952f76c2c311d1cf0cbf7627c6af4a68071dc /storage/filesystem/internal/dotgit/dotgit.go | |
parent | f96d46d38f67604f204711ea0e2832e6e047e2ad (diff) | |
download | go-git-eb74b0e1a0ae20075435aded41bffc522bc3554c.tar.gz |
storage: filesystem, add support for git alternates (#663)
This change adds a new method Alternates() in DotGit to check and
query alternate source.
Diffstat (limited to 'storage/filesystem/internal/dotgit/dotgit.go')
-rw-r--r-- | storage/filesystem/internal/dotgit/dotgit.go | 45 |
1 files changed, 44 insertions, 1 deletions
diff --git a/storage/filesystem/internal/dotgit/dotgit.go b/storage/filesystem/internal/dotgit/dotgit.go index 11b2512..ebc6bad 100644 --- a/storage/filesystem/internal/dotgit/dotgit.go +++ b/storage/filesystem/internal/dotgit/dotgit.go @@ -8,9 +8,11 @@ import ( "io" stdioutil "io/ioutil" "os" + "path/filepath" "strings" "time" + "gopkg.in/src-d/go-billy.v4/osfs" "gopkg.in/src-d/go-git.v4/plumbing" "gopkg.in/src-d/go-git.v4/utils/ioutil" @@ -756,11 +758,52 @@ func (d *DotGit) PackRefs() (err error) { return nil } -// Module return a billy.Filesystem poiting to the module folder +// Module return a billy.Filesystem pointing to the module folder func (d *DotGit) Module(name string) (billy.Filesystem, error) { return d.fs.Chroot(d.fs.Join(modulePath, name)) } +// Alternates returns DotGit(s) based off paths in objects/info/alternates if +// available. This can be used to checks if it's a shared repository. +func (d *DotGit) Alternates() ([]*DotGit, error) { + altpath := d.fs.Join("objects", "info", "alternates") + f, err := d.fs.Open(altpath) + if err != nil { + return nil, err + } + defer f.Close() + + var alternates []*DotGit + + // Read alternate paths line-by-line and create DotGit objects. + scanner := bufio.NewScanner(f) + for scanner.Scan() { + path := scanner.Text() + if !filepath.IsAbs(path) { + // For relative paths, we can perform an internal conversion to + // slash so that they work cross-platform. + slashPath := filepath.ToSlash(path) + // If the path is not absolute, it must be relative to object + // database (.git/objects/info). + // https://www.kernel.org/pub/software/scm/git/docs/gitrepository-layout.html + // Hence, derive a path relative to DotGit's root. + // "../../../reponame/.git/" -> "../../reponame/.git" + // Remove the first ../ + relpath := filepath.Join(strings.Split(slashPath, "/")[1:]...) + normalPath := filepath.FromSlash(relpath) + path = filepath.Join(d.fs.Root(), normalPath) + } + fs := osfs.New(filepath.Dir(path)) + alternates = append(alternates, New(fs)) + } + + if err = scanner.Err(); err != nil { + return nil, err + } + + return alternates, nil +} + func isHex(s string) bool { for _, b := range []byte(s) { if isNum(b) { |