Skip to content

Commit 65351f8

Browse files
committed
Repository.Init now handles non-standard .git location
1 parent f8b5557 commit 65351f8

File tree

4 files changed

+135
-4
lines changed

4 files changed

+135
-4
lines changed

repository.go

+68-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"errors"
55
"fmt"
66
"os"
7+
"path/filepath"
78

89
"srcd.works/go-git.v4/config"
910
"srcd.works/go-git.v4/internal/revision"
@@ -57,9 +58,75 @@ func Init(s storage.Storer, worktree billy.Filesystem) (*Repository, error) {
5758

5859
if worktree == nil {
5960
r.setIsBare(true)
61+
return r, nil
6062
}
6163

62-
return r, nil
64+
return r, setWorktreeAndStoragePaths(r, worktree)
65+
}
66+
67+
func setWorktreeAndStoragePaths(r *Repository, worktree billy.Filesystem) error {
68+
type fsBased interface {
69+
Filesystem() billy.Filesystem
70+
}
71+
72+
// .git file is only created if the storage is file based and the file
73+
// system is osfs.OS
74+
fs, isFSBased := r.Storer.(fsBased)
75+
if !isFSBased {
76+
return nil
77+
}
78+
79+
_, isOS := fs.Filesystem().(*osfs.OS)
80+
if !isOS {
81+
return nil
82+
}
83+
84+
if err := createDotGitFile(worktree, fs.Filesystem()); err != nil {
85+
return err
86+
}
87+
88+
return setConfigWorktree(r, worktree, fs.Filesystem())
89+
}
90+
91+
func createDotGitFile(worktree, storage billy.Filesystem) error {
92+
path, err := filepath.Rel(worktree.Base(), storage.Base())
93+
if err != nil {
94+
path = storage.Base()
95+
}
96+
97+
if path == ".git" {
98+
// not needed, since the folder is the default place
99+
return nil
100+
}
101+
102+
f, err := worktree.Create(".git")
103+
if err != nil {
104+
return err
105+
}
106+
107+
defer f.Close()
108+
_, err = fmt.Fprintf(f, "gitdir: %s\n", path)
109+
return err
110+
}
111+
112+
func setConfigWorktree(r *Repository, worktree, storage billy.Filesystem) error {
113+
path, err := filepath.Rel(storage.Base(), worktree.Base())
114+
if err != nil {
115+
path = worktree.Base()
116+
}
117+
118+
if path == ".." {
119+
// not needed, since the folder is the default place
120+
return nil
121+
}
122+
123+
cfg, err := r.Storer.Config()
124+
if err != nil {
125+
return err
126+
}
127+
128+
cfg.Core.Worktree = path
129+
return r.Storer.SetConfig(cfg)
63130
}
64131

65132
// Open opens a git repository using the given Storer and worktree filesystem,
@@ -280,7 +347,6 @@ func (r *Repository) clone(o *CloneOptions) error {
280347
}
281348

282349
if err := r.updateWorktree(); err != nil {
283-
fmt.Println("q", err)
284350
return err
285351
}
286352

repository_test.go

+49-2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818

1919
. "gopkg.in/check.v1"
2020
"srcd.works/go-billy.v1/memfs"
21+
"srcd.works/go-billy.v1/osfs"
2122
)
2223

2324
type RepositorySuite struct {
@@ -36,6 +37,52 @@ func (s *RepositorySuite) TestInit(c *C) {
3637
c.Assert(cfg.Core.IsBare, Equals, false)
3738
}
3839

40+
func (s *RepositorySuite) TestInitNonStandardDotGit(c *C) {
41+
dir, err := ioutil.TempDir("", "init-non-standard")
42+
c.Assert(err, IsNil)
43+
c.Assert(os.RemoveAll(dir), IsNil)
44+
45+
fs := osfs.New(dir)
46+
storage, err := filesystem.NewStorage(fs.Dir("storage"))
47+
c.Assert(err, IsNil)
48+
49+
r, err := Init(storage, fs.Dir("worktree"))
50+
c.Assert(err, IsNil)
51+
c.Assert(r, NotNil)
52+
53+
f, err := fs.Open("worktree/.git")
54+
c.Assert(err, IsNil)
55+
56+
all, err := ioutil.ReadAll(f)
57+
c.Assert(err, IsNil)
58+
c.Assert(string(all), Equals, "gitdir: ../storage\n")
59+
60+
cfg, err := r.Config()
61+
c.Assert(err, IsNil)
62+
c.Assert(cfg.Core.Worktree, Equals, "../worktree")
63+
}
64+
65+
func (s *RepositorySuite) TestInitStandardDotGit(c *C) {
66+
dir, err := ioutil.TempDir("", "init-standard")
67+
c.Assert(err, IsNil)
68+
c.Assert(os.RemoveAll(dir), IsNil)
69+
70+
fs := osfs.New(dir)
71+
storage, err := filesystem.NewStorage(fs.Dir(".git"))
72+
c.Assert(err, IsNil)
73+
74+
r, err := Init(storage, fs)
75+
c.Assert(err, IsNil)
76+
c.Assert(r, NotNil)
77+
78+
l, err := fs.ReadDir(".git")
79+
c.Assert(len(l) > 0, Equals, true)
80+
81+
cfg, err := r.Config()
82+
c.Assert(err, IsNil)
83+
c.Assert(cfg.Core.Worktree, Equals, "")
84+
}
85+
3986
func (s *RepositorySuite) TestInitBare(c *C) {
4087
r, err := Init(memory.NewStorage(), nil)
4188
c.Assert(err, IsNil)
@@ -306,7 +353,7 @@ func (s *RepositorySuite) TestCloneDeep(c *C) {
306353

307354
fi, err := fs.ReadDir("")
308355
c.Assert(err, IsNil)
309-
c.Assert(fi, HasLen, 9)
356+
c.Assert(fi, HasLen, 8)
310357
}
311358

312359
func (s *RepositorySuite) TestCloneConfig(c *C) {
@@ -431,7 +478,7 @@ func (s *RepositorySuite) TestPullCheckout(c *C) {
431478

432479
fi, err := fs.ReadDir("")
433480
c.Assert(err, IsNil)
434-
c.Assert(fi, HasLen, 9)
481+
c.Assert(fi, HasLen, 8)
435482
}
436483

437484
func (s *RepositorySuite) TestCloneWithProgress(c *C) {

storage/filesystem/storage.go

+9
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import (
1111
// standard git format (this is, the .git directory). Zero values of this type
1212
// are not safe to use, see the NewStorage function below.
1313
type Storage struct {
14+
fs billy.Filesystem
15+
1416
ObjectStorage
1517
ReferenceStorage
1618
IndexStorage
@@ -28,6 +30,8 @@ func NewStorage(fs billy.Filesystem) (*Storage, error) {
2830
}
2931

3032
return &Storage{
33+
fs: fs,
34+
3135
ObjectStorage: o,
3236
ReferenceStorage: ReferenceStorage{dir: dir},
3337
IndexStorage: IndexStorage{dir: dir},
@@ -36,3 +40,8 @@ func NewStorage(fs billy.Filesystem) (*Storage, error) {
3640
ModuleStorage: ModuleStorage{dir: dir},
3741
}, nil
3842
}
43+
44+
// Filesystem returns the underlying filesystem
45+
func (s *Storage) Filesystem() billy.Filesystem {
46+
return s.fs
47+
}

storage/filesystem/storage_test.go

+9
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"srcd.works/go-git.v4/storage/test"
77

88
. "gopkg.in/check.v1"
9+
"srcd.works/go-billy.v1/memfs"
910
"srcd.works/go-billy.v1/osfs"
1011
)
1112

@@ -23,3 +24,11 @@ func (s *StorageSuite) SetUpTest(c *C) {
2324

2425
s.BaseStorageSuite = test.NewBaseStorageSuite(storage)
2526
}
27+
28+
func (s *StorageSuite) TestFilesystem(c *C) {
29+
fs := memfs.New()
30+
storage, err := NewStorage(fs)
31+
c.Assert(err, IsNil)
32+
33+
c.Assert(storage.Filesystem(), Equals, fs)
34+
}

0 commit comments

Comments
 (0)