Skip to content
This repository was archived by the owner on Sep 11, 2020. It is now read-only.

Commit 415a31f

Browse files
committed
storage: filesystem, add support for git alternates
This change adds a new method `Alternates()` in `DotGit` to check and query alternate source. ``` func (d *DotGit) Alternates() (string, error) ``` This is used by `ObjectStorage.EncodedObject` to check for alternates and get the queried object from the alternate source.
1 parent 60c567f commit 415a31f

File tree

3 files changed

+66
-1
lines changed

3 files changed

+66
-1
lines changed

storage/filesystem/internal/dotgit/dotgit.go

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package dotgit
33

44
import (
55
"bufio"
6+
"bytes"
67
"errors"
78
"fmt"
89
stdioutil "io/ioutil"
@@ -502,11 +503,29 @@ func (d *DotGit) readReferenceFile(path, name string) (ref *plumbing.Reference,
502503
return plumbing.NewReferenceFromStrings(name, line), nil
503504
}
504505

505-
// Module return a billy.Filesystem poiting to the module folder
506+
// Module return a billy.Filesystem pointing to the module folder
506507
func (d *DotGit) Module(name string) (billy.Filesystem, error) {
507508
return d.fs.Chroot(d.fs.Join(modulePath, name))
508509
}
509510

511+
// Alternates returns the content of objects/info/alternates if available.
512+
// This can be used to checks if it's a shared repository.
513+
func (d *DotGit) Alternates() (string, error) {
514+
altpath := d.fs.Join("objects", "info", "alternates")
515+
f, err := d.fs.Open(altpath)
516+
if os.IsNotExist(err) {
517+
return "", err
518+
}
519+
520+
buf := new(bytes.Buffer)
521+
_, err = buf.ReadFrom(f)
522+
if err != nil {
523+
return "", err
524+
}
525+
526+
return buf.String(), nil
527+
}
528+
510529
func isHex(s string) bool {
511530
for _, b := range []byte(s) {
512531
if isNum(b) {

storage/filesystem/internal/dotgit/dotgit_test.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,3 +487,30 @@ func (s *SuiteDotGit) TestSubmodules(c *C) {
487487
c.Assert(err, IsNil)
488488
c.Assert(strings.HasSuffix(m.Root(), m.Join(".git", "modules", "basic")), Equals, true)
489489
}
490+
491+
func (s *SuiteDotGit) TestAlternates(c *C) {
492+
tmp, err := ioutil.TempDir("", "dot-git")
493+
c.Assert(err, IsNil)
494+
defer os.RemoveAll(tmp)
495+
496+
// Create a new billy fs.
497+
fs := osfs.New(tmp)
498+
499+
// Create a new dotgit object and initialize.
500+
dir := New(fs)
501+
err = dir.Initialize()
502+
c.Assert(err, IsNil)
503+
504+
// Create alternates file.
505+
altpath := filepath.Join("objects", "info", "alternates")
506+
f, err := fs.Create(altpath)
507+
c.Assert(err, IsNil)
508+
509+
content := []byte("/Users/username/rep1//.git/objects")
510+
f.Write(content)
511+
f.Close()
512+
513+
alt, err := dir.Alternates()
514+
c.Assert(err, IsNil)
515+
c.Assert(alt, Equals, "/Users/username/rep1//.git/objects")
516+
}

storage/filesystem/object.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package filesystem
33
import (
44
"io"
55
"os"
6+
"path/filepath"
67

78
"gopkg.in/src-d/go-git.v4/plumbing"
89
"gopkg.in/src-d/go-git.v4/plumbing/cache"
@@ -15,6 +16,7 @@ import (
1516
"gopkg.in/src-d/go-git.v4/utils/ioutil"
1617

1718
"gopkg.in/src-d/go-billy.v4"
19+
"gopkg.in/src-d/go-billy.v4/osfs"
1820
)
1921

2022
const DefaultMaxDeltaBaseCacheSize = 92 * cache.MiByte
@@ -133,6 +135,23 @@ func (s *ObjectStorage) EncodedObject(t plumbing.ObjectType, h plumbing.Hash) (p
133135
obj, err = s.getFromPackfile(h, false)
134136
}
135137

138+
// If the error is still object not found, check if it's a shared object
139+
// repository.
140+
if err == plumbing.ErrObjectNotFound {
141+
alt, e := s.dir.Alternates()
142+
if e == nil {
143+
// Create a new object storage pointing to the path in the
144+
// alternates file.
145+
fs := osfs.New(filepath.Dir(alt))
146+
dir := dotgit.New(fs)
147+
o, oe := newObjectStorage(dir)
148+
if oe != nil {
149+
return nil, oe
150+
}
151+
return o.EncodedObject(t, h)
152+
}
153+
}
154+
136155
if err != nil {
137156
return nil, err
138157
}

0 commit comments

Comments
 (0)