1// Package repository contains helper methods for working with a Git repo.
2package repository
3
4import (
5 "bytes"
6 "errors"
7 "strings"
8
9 "github.com/MichaelMure/git-bug/util/git"
10 "github.com/MichaelMure/git-bug/util/lamport"
11)
12
13var ErrNoConfigEntry = errors.New("no config entry for the given key")
14var ErrMultipleConfigEntry = errors.New("multiple config entry for the given key")
15
16// RepoCommon represent the common function the we want all the repo to implement
17type RepoCommon interface {
18 // GetPath returns the path to the repo.
19 GetPath() string
20
21 // GetUserName returns the name the the user has used to configure git
22 GetUserName() (string, error)
23
24 // GetUserEmail returns the email address that the user has used to configure git.
25 GetUserEmail() (string, error)
26
27 // GetCoreEditor returns the name of the editor that the user has used to configure git.
28 GetCoreEditor() (string, error)
29
30 // GetRemotes returns the configured remotes repositories.
31 GetRemotes() (map[string]string, error)
32
33 // LocalConfig give access to the repository scoped configuration
34 LocalConfig() Config
35
36 // GlobalConfig give access to the git global configuration
37 GlobalConfig() Config
38}
39
40// Repo represents a source code repository.
41type Repo interface {
42 RepoCommon
43
44 // FetchRefs fetch git refs from a remote
45 FetchRefs(remote string, refSpec string) (string, error)
46
47 // PushRefs push git refs to a remote
48 PushRefs(remote string, refSpec string) (string, error)
49
50 // StoreData will store arbitrary data and return the corresponding hash
51 StoreData(data []byte) (git.Hash, error)
52
53 // ReadData will attempt to read arbitrary data from the given hash
54 ReadData(hash git.Hash) ([]byte, error)
55
56 // StoreTree will store a mapping key-->Hash as a Git tree
57 StoreTree(mapping []TreeEntry) (git.Hash, error)
58
59 // StoreCommit will store a Git commit with the given Git tree
60 StoreCommit(treeHash git.Hash) (git.Hash, error)
61
62 // StoreCommit will store a Git commit with the given Git tree
63 StoreCommitWithParent(treeHash git.Hash, parent git.Hash) (git.Hash, error)
64
65 // UpdateRef will create or update a Git reference
66 UpdateRef(ref string, hash git.Hash) error
67
68 // ListRefs will return a list of Git ref matching the given refspec
69 ListRefs(refspec string) ([]string, error)
70
71 // RefExist will check if a reference exist in Git
72 RefExist(ref string) (bool, error)
73
74 // CopyRef will create a new reference with the same value as another one
75 CopyRef(source string, dest string) error
76
77 // ListCommits will return the list of tree hashes of a ref, in chronological order
78 ListCommits(ref string) ([]git.Hash, error)
79
80 // ListEntries will return the list of entries in a Git tree
81 ListEntries(hash git.Hash) ([]TreeEntry, error)
82
83 // FindCommonAncestor will return the last common ancestor of two chain of commit
84 FindCommonAncestor(hash1 git.Hash, hash2 git.Hash) (git.Hash, error)
85
86 // GetTreeHash return the git tree hash referenced in a commit
87 GetTreeHash(commit git.Hash) (git.Hash, error)
88}
89
90// ClockedRepo is a Repo that also has Lamport clocks
91type ClockedRepo interface {
92 Repo
93
94 // LoadClocks read the clocks values from the on-disk repo
95 LoadClocks() error
96
97 // WriteClocks write the clocks values into the repo
98 WriteClocks() error
99
100 // CreateTime return the current value of the creation clock
101 CreateTime() lamport.Time
102
103 // CreateTimeIncrement increment the creation clock and return the new value.
104 CreateTimeIncrement() (lamport.Time, error)
105
106 // EditTime return the current value of the edit clock
107 EditTime() lamport.Time
108
109 // EditTimeIncrement increment the edit clock and return the new value.
110 EditTimeIncrement() (lamport.Time, error)
111
112 // CreateWitness witness another create time and increment the corresponding
113 // clock if needed.
114 CreateWitness(time lamport.Time) error
115
116 // EditWitness witness another edition time and increment the corresponding
117 // clock if needed.
118 EditWitness(time lamport.Time) error
119}
120
121// Witnesser is a function that will initialize the clocks of a repo
122// from scratch
123type Witnesser func(repo ClockedRepo) error
124
125func prepareTreeEntries(entries []TreeEntry) bytes.Buffer {
126 var buffer bytes.Buffer
127
128 for _, entry := range entries {
129 buffer.WriteString(entry.Format())
130 }
131
132 return buffer
133}
134
135func readTreeEntries(s string) ([]TreeEntry, error) {
136 split := strings.Split(strings.TrimSpace(s), "\n")
137
138 casted := make([]TreeEntry, len(split))
139 for i, line := range split {
140 if line == "" {
141 continue
142 }
143
144 entry, err := ParseTreeEntry(line)
145
146 if err != nil {
147 return nil, err
148 }
149
150 casted[i] = entry
151 }
152
153 return casted, nil
154}