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