1// Package repository contains helper methods for working with a Git repo.
2package repository
3
4import (
5 "errors"
6
7 "github.com/MichaelMure/git-bug/util/lamport"
8 "github.com/go-git/go-billy/v5"
9)
10
11var (
12 // ErrNotARepo is the error returned when the git repo root wan't be found
13 ErrNotARepo = errors.New("not a git repository")
14 // ErrClockNotExist is the error returned when a clock can't be found
15 ErrClockNotExist = errors.New("clock doesn't exist")
16)
17
18// Repo represents a source code repository.
19type Repo interface {
20 RepoConfig
21 RepoKeyring
22 RepoCommon
23 RepoData
24 RepoStorage
25}
26
27// ClockedRepo is a Repo that also has Lamport clocks
28type ClockedRepo interface {
29 Repo
30 RepoClock
31}
32
33// RepoConfig access the configuration of a repository
34type RepoConfig interface {
35 // LocalConfig give access to the repository scoped configuration
36 LocalConfig() Config
37
38 // GlobalConfig give access to the global scoped configuration
39 GlobalConfig() Config
40
41 // AnyConfig give access to a merged local/global configuration
42 AnyConfig() ConfigRead
43}
44
45// RepoKeyring give access to a user-wide storage for secrets
46type RepoKeyring interface {
47 // Keyring give access to a user-wide storage for secrets
48 Keyring() Keyring
49}
50
51// RepoCommon represent the common function the we want all the repo to implement
52type RepoCommon interface {
53 // GetPath returns the path to the repo.
54 GetPath() string
55
56 // GetUserName returns the name the the user has used to configure git
57 GetUserName() (string, error)
58
59 // GetUserEmail returns the email address that the user has used to configure git.
60 GetUserEmail() (string, error)
61
62 // GetCoreEditor returns the name of the editor that the user has used to configure git.
63 GetCoreEditor() (string, error)
64
65 // GetRemotes returns the configured remotes repositories.
66 GetRemotes() (map[string]string, error)
67}
68
69type RepoStorage interface {
70 // Storage returns a billy.Filesystem giving access to $RepoPath/.git/git-bug
71 Storage() billy.Filesystem
72}
73
74// RepoData give access to the git data storage
75type RepoData interface {
76 // FetchRefs fetch git refs from a remote
77 FetchRefs(remote string, refSpec string) (string, error)
78
79 // PushRefs push git refs to a remote
80 PushRefs(remote string, refSpec string) (string, error)
81
82 // StoreData will store arbitrary data and return the corresponding hash
83 StoreData(data []byte) (Hash, error)
84
85 // ReadData will attempt to read arbitrary data from the given hash
86 ReadData(hash Hash) ([]byte, error)
87
88 // StoreTree will store a mapping key-->Hash as a Git tree
89 StoreTree(mapping []TreeEntry) (Hash, error)
90
91 // ReadTree will return the list of entries in a Git tree
92 // The given hash could be from either a commit or a tree
93 ReadTree(hash Hash) ([]TreeEntry, error)
94
95 // StoreCommit will store a Git commit with the given Git tree
96 StoreCommit(treeHash Hash) (Hash, error)
97
98 // StoreCommit will store a Git commit with the given Git tree
99 StoreCommitWithParent(treeHash Hash, parent Hash) (Hash, error)
100
101 // GetTreeHash return the git tree hash referenced in a commit
102 GetTreeHash(commit Hash) (Hash, error)
103
104 // FindCommonAncestor will return the last common ancestor of two chain of commit
105 FindCommonAncestor(commit1 Hash, commit2 Hash) (Hash, error)
106
107 // UpdateRef will create or update a Git reference
108 UpdateRef(ref string, hash Hash) error
109
110 // RemoveRef will remove a Git reference
111 RemoveRef(ref string) error
112
113 // ListRefs will return a list of Git ref matching the given refspec
114 ListRefs(refPrefix string) ([]string, error)
115
116 // RefExist will check if a reference exist in Git
117 RefExist(ref string) (bool, error)
118
119 // CopyRef will create a new reference with the same value as another one
120 CopyRef(source string, dest string) error
121
122 // ListCommits will return the list of tree hashes of a ref, in chronological order
123 ListCommits(ref string) ([]Hash, error)
124}
125
126// RepoClock give access to Lamport clocks
127type RepoClock interface {
128 // GetOrCreateClock return a Lamport clock stored in the Repo.
129 // If the clock doesn't exist, it's created.
130 GetOrCreateClock(name string) (lamport.Clock, error)
131}
132
133// ClockLoader hold which logical clock need to exist for an entity and
134// how to create them if they don't.
135type ClockLoader struct {
136 // Clocks hold the name of all the clocks this loader deal with.
137 // Those clocks will be checked when the repo load. If not present or broken,
138 // Witnesser will be used to create them.
139 Clocks []string
140 // Witnesser is a function that will initialize the clocks of a repo
141 // from scratch
142 Witnesser func(repo ClockedRepo) error
143}
144
145// TestedRepo is an extended ClockedRepo with function for testing only
146type TestedRepo interface {
147 ClockedRepo
148 repoTest
149}
150
151// repoTest give access to test only functions
152type repoTest interface {
153 // AddRemote add a new remote to the repository
154 AddRemote(name string, url string) error
155
156 // GetLocalRemote return the URL to use to add this repo as a local remote
157 GetLocalRemote() string
158
159 // EraseFromDisk delete this repository entirely from the disk
160 EraseFromDisk() error
161}