forked from keybase/kbfs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathworktree_storer.go
88 lines (78 loc) · 3.22 KB
/
worktree_storer.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
// Copyright 2017 Keybase Inc. All rights reserved.
// Use of this source code is governed by a BSD
// license that can be found in the LICENSE file.
package libgit
import (
"github.com/pkg/errors"
"gopkg.in/src-d/go-git.v4/plumbing"
"gopkg.in/src-d/go-git.v4/plumbing/format/index"
"gopkg.in/src-d/go-git.v4/plumbing/storer"
"gopkg.in/src-d/go-git.v4/storage"
)
// worktreeStorer fakes out the storage layer in such a way that it
// stores its index, and any reference modifications, in a .git/
// directory in the worktree, but everything else goes through the
// main repo's .git directory. This is useful for making a quick
// checkout of a git repo in a new directory, without making a full
// git clone. For example, consider the following instance:
//
// * `storage.Storer` points to a bare repo stored in KBFS, say
// `/keybase/team/keybase/.kbfs_git/secrets/`.
// * `delta` is the same as above, but cast as a `DeltaObjectStorer`.
// * `wtDotgit` can be pointed anywhere else in KBFS where you want to
// track a checked-out version of the keybase secrets repo, say
// `/keybase/private/strib/.kbfs_autogit/team/keybase/secrets/.git/`
//
// Any calls to update the index or set a reference will be routed to
// `wtDotgit`, and everything else goes to `storage.Storer`. That
// means that the caller can use this to "reset" the autogit worktree
// to some commit stored in the main bare repo, without having to do a
// full clone and copy the git history, etc.
//
// This storage layer should only be used for read-only workloads,
// where the entire git history isn't needed.
type worktreeStorer struct {
storage.Storer // main dotgit where all the objects/refs are
delta storer.DeltaObjectStorer
wtDotgit storage.Storer // worktree dotgit where the index and HEAD are
}
var _ storage.Storer = (*worktreeStorer)(nil)
var _ storer.DeltaObjectStorer = (*worktreeStorer)(nil)
// DeltaObject implements the storer.DeltaObjectStorer interface for
// worktreeStorer.
func (wts *worktreeStorer) DeltaObject(
ot plumbing.ObjectType, hash plumbing.Hash) (
plumbing.EncodedObject, error) {
return wts.delta.DeltaObject(ot, hash)
}
// SetIndex implements the storer.IndexStorer interface for worktreeStorer.
func (wts *worktreeStorer) SetIndex(in *index.Index) error {
return wts.wtDotgit.SetIndex(in)
}
// Index implements the storer.IndexStorer interface for worktreeStorer.
func (wts *worktreeStorer) Index() (*index.Index, error) {
return wts.wtDotgit.Index()
}
// SetReference implements the storer.ReferenceStorer interface for
// worktreeStorer.
func (wts *worktreeStorer) SetReference(ref *plumbing.Reference) error {
// Steal the hash and set HEAD to it in the worktree, so next time
// we can read it.
if ref.Type() != plumbing.HashReference {
return errors.New("Can't set a non-hash reference")
}
headRef := plumbing.NewHashReference(plumbing.HEAD, ref.Hash())
return wts.wtDotgit.SetReference(headRef)
}
// Reference implements the storer.ReferenceStorer interface for
// worktreeStorer
func (wts *worktreeStorer) Reference(name plumbing.ReferenceName) (
*plumbing.Reference, error) {
if name == plumbing.HEAD {
ref, err := wts.wtDotgit.Reference(name)
if err == nil {
return ref, nil
}
}
return wts.Storer.Reference(name)
}