Skip to content

Commit 88147f3

Browse files
authored
Merge pull request #4 from gov4git/cache
local disk cache + auth in context
2 parents b8de280 + fd5723e commit 88147f3

14 files changed

Lines changed: 439 additions & 260 deletions

File tree

TODO.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
- [ ] local cache for remote repos
1+
- [] local cache for remote repos
2+
- [] auth in context

git/auth.go

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,26 @@ func MakeSSHFileAuth(ctx context.Context, user string, privKeyFile string) trans
2424
return pubKey
2525
}
2626

27-
// global repo-dependent auth
27+
// auth manager in context
2828

29-
var authManager = NewAuthManager()
29+
type contextKeyAuthManager struct{}
3030

31-
func SetAuth(forRepo URL, a transport.AuthMethod) {
32-
authManager.SetAuth(forRepo, a)
31+
func WithAuth(ctx context.Context, am *AuthManager) context.Context {
32+
if am == nil {
33+
am = NewAuthManager()
34+
}
35+
return context.WithValue(ctx, contextKeyAuthManager{}, am)
36+
}
37+
38+
func SetAuth(ctx context.Context, forRepo URL, a transport.AuthMethod) {
39+
ctx.Value(contextKeyAuthManager{}).(*AuthManager).SetAuth(forRepo, a)
3340
}
3441

3542
func GetAuth(ctx context.Context, forRepo URL) transport.AuthMethod {
36-
return authManager.GetAuth(ctx, forRepo)
43+
return ctx.Value(contextKeyAuthManager{}).(*AuthManager).GetAuth(forRepo)
3744
}
3845

46+
// AuthManager provides authentication methods given a repo URL.
3947
type AuthManager struct {
4048
lk sync.Mutex
4149
url map[URL]transport.AuthMethod
@@ -51,7 +59,7 @@ func (x *AuthManager) SetAuth(forRepo URL, a transport.AuthMethod) {
5159
x.url[forRepo] = a
5260
}
5361

54-
func (x *AuthManager) GetAuth(ctx context.Context, forRepo URL) transport.AuthMethod {
62+
func (x *AuthManager) GetAuth(forRepo URL) transport.AuthMethod {
5563
x.lk.Lock()
5664
defer x.lk.Unlock()
5765
return x.url[forRepo]

git/cache.go

Lines changed: 0 additions & 132 deletions
This file was deleted.

git/cache_test.go

Lines changed: 54 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,28 +6,77 @@ import (
66
"path/filepath"
77
"testing"
88

9+
"github.com/go-git/go-git/v5"
10+
"github.com/go-git/go-git/v5/plumbing"
911
"github.com/gov4git/lib4git/base"
12+
"github.com/gov4git/lib4git/must"
13+
)
14+
15+
var (
16+
testBranch = Branch("test")
17+
test2Branch = Branch("test2")
18+
test3Branch = Branch("test3")
1019
)
1120

1221
func TestCache(t *testing.T) {
1322
base.LogVerbosely()
14-
ctx := context.Background()
23+
ctx := WithAuth(context.Background(), nil)
1524

1625
dir := t.TempDir()
1726
fmt.Println("test root ", dir)
1827
originDir := filepath.Join(dir, "origin")
1928
cacheDir := filepath.Join(dir, "cache")
20-
originAddr := Address{Repo: URL(originDir), Branch: MainBranch}
29+
originAddr := Address{Repo: URL(originDir), Branch: testBranch}
2130

31+
// init origin and cache
2232
InitPlain(ctx, originDir, true)
23-
cache := NewCache(ctx, cacheDir)
33+
cache := NewMirrorCache(ctx, cacheDir)
34+
2435
cloned1 := cache.Clone(ctx, originAddr)
25-
populate(ctx, cloned1.Repo(), "hi", true)
36+
populateNonce(ctx, cloned1.Repo(), "ok1")
2637
cloned1.Push(ctx)
2738

2839
cloned2 := cache.Clone(ctx, originAddr)
29-
populate(ctx, cloned2.Repo(), "ok", false)
40+
findNonce(ctx, cloned2.Repo(), "ok1")
41+
populateNonce(ctx, cloned2.Repo(), "ok2")
42+
cloned2.Tree().Checkout(&git.CheckoutOptions{
43+
Branch: plumbing.NewBranchReferenceName(string(test2Branch)),
44+
Create: true,
45+
})
46+
populateNonce(ctx, cloned2.Repo(), "ok3")
3047
cloned2.Push(ctx)
3148

49+
cloned3 := cache.Clone(ctx, Address{Repo: URL(originDir), Branch: test3Branch})
50+
populateNonce(ctx, cloned3.Repo(), "ok5")
51+
cloned3.Push(ctx)
52+
53+
cloned4 := cache.Clone(ctx, Address{Repo: URL(originDir), Branch: test2Branch})
54+
findNonce(ctx, cloned4.Repo(), "ok3")
55+
populateNonce(ctx, cloned4.Repo(), "ok6")
56+
cloned4.Push(ctx)
57+
3258
// <-(chan int)(nil)
3359
}
60+
61+
func populateNonce(ctx context.Context, r *git.Repository, nonce string) {
62+
w, err := r.Worktree()
63+
must.NoError(ctx, err)
64+
65+
f, err := w.Filesystem.Create(nonce)
66+
must.NoError(ctx, err)
67+
f.Write([]byte(nonce))
68+
err = f.Close()
69+
must.NoError(ctx, err)
70+
_, err = w.Add(nonce)
71+
must.NoError(ctx, err)
72+
_, err = w.Commit(nonce, &git.CommitOptions{})
73+
must.NoError(ctx, err)
74+
}
75+
76+
func findNonce(ctx context.Context, r *git.Repository, nonce string) {
77+
w, err := r.Worktree()
78+
must.NoError(ctx, err)
79+
80+
_, err = w.Filesystem.Stat(nonce)
81+
must.NoError(ctx, err)
82+
}

git/clone.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package git
2+
3+
import (
4+
"context"
5+
"sync"
6+
)
7+
8+
var (
9+
cacheLk sync.Mutex
10+
proxy Proxy
11+
)
12+
13+
func UseCache(ctx context.Context, dir string) {
14+
cacheLk.Lock()
15+
defer cacheLk.Unlock()
16+
proxy = NewMirrorCache(ctx, dir)
17+
}
18+
19+
func getProxy() Proxy {
20+
cacheLk.Lock()
21+
defer cacheLk.Unlock()
22+
return proxy
23+
}
24+
25+
func Clone(ctx context.Context, addr Address) Cloned {
26+
if pxy := getProxy(); pxy != nil {
27+
return pxy.Clone(ctx, addr)
28+
}
29+
return GitClone(ctx, addr)
30+
}
31+
32+
func CloneOrInit(ctx context.Context, addr Address) Cloned {
33+
if pxy := getProxy(); pxy != nil {
34+
return pxy.Clone(ctx, addr)
35+
}
36+
return GitCloneOrInit(ctx, addr)
37+
}

git/embed.go

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,18 @@ import (
1818
func Embed(
1919
ctx context.Context,
2020
repo *Repository,
21-
keys []string,
2221
addrs []Address,
2322
toBranch Branch,
2423
toNS []ns.NS,
2524
allowOverride bool,
2625
) {
2726

2827
// fetch remotes
29-
must.Assertf(ctx, len(toNS) == len(addrs) && len(keys) == len(addrs), "names and keys must match addresses")
30-
remoteTreeHashes := make([]plumbing.Hash, len(keys))
31-
remoteCommitHashes := make([]plumbing.Hash, len(keys))
32-
for i := range keys {
33-
remoteCommit := fetchEmbedding(ctx, repo, keys[i], addrs[i])
28+
must.Assertf(ctx, len(toNS) == len(addrs), "namespaces and addresses must be same count")
29+
remoteTreeHashes := make([]plumbing.Hash, len(addrs))
30+
remoteCommitHashes := make([]plumbing.Hash, len(addrs))
31+
for i := range addrs {
32+
remoteCommit := fetchEmbedding(ctx, repo, addrs[i])
3433
remoteTreeHashes[i] = PrefixTree(ctx, repo, toNS[i], remoteCommit.TreeHash) // prefix with namespace
3534
remoteCommitHashes[i] = remoteCommit.Hash
3635
}
@@ -64,14 +63,10 @@ func Embed(
6463
must.NoError(ctx, err)
6564
}
6665

67-
func fetchEmbedding(
68-
ctx context.Context,
69-
repo *Repository,
70-
key string,
71-
addr Address,
72-
) object.Commit {
66+
func fetchEmbedding(ctx context.Context, repo *Repository, addr Address) object.Commit {
7367

7468
// fetch remote branch using an ephemeral definition of the remote (not stored in the repo)
69+
key := addr.Hash()
7570
nonce := "embedding-" + strconv.FormatUint(uint64(rand.Int63()), 36)
7671
remoteBranchName := plumbing.NewBranchReferenceName(string(addr.Branch))
7772
embeddedBranchName := plumbing.NewBranchReferenceName(filepath.Join("embedding", key))

git/embed_test.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ func TestEmbed(t *testing.T) {
3333
Embed(
3434
ctx,
3535
r1,
36-
[]string{"r2", "r3"},
3736
[]Address{
3837
{Repo: URL(dir2), Branch: Branch(MainBranch)},
3938
{Repo: URL(dir3), Branch: Branch(MainBranch)},
@@ -50,7 +49,6 @@ func TestEmbed(t *testing.T) {
5049
Embed(
5150
ctx,
5251
r1,
53-
[]string{"r2", "r3"},
5452
[]Address{
5553
{Repo: URL(dir2), Branch: Branch(MainBranch)},
5654
{Repo: URL(dir3), Branch: Branch(MainBranch)},

0 commit comments

Comments
 (0)