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
86// ClockedRepo is a Repo that also has Lamport clocks
87type ClockedRepo interface {
88 Repo
89
90 // LoadClocks read the clocks values from the on-disk repo
91 LoadClocks() error
92
93 // WriteClocks write the clocks values into the repo
94 WriteClocks() error
95
96 // CreateTime return the current value of the creation clock
97 CreateTime() lamport.Time
98
99 // CreateTimeIncrement increment the creation clock and return the new value.
100 CreateTimeIncrement() (lamport.Time, error)
101
102 // EditTime return the current value of the edit clock
103 EditTime() lamport.Time
104
105 // EditTimeIncrement increment the edit clock and return the new value.
106 EditTimeIncrement() (lamport.Time, error)
107
108 // CreateWitness witness another create time and increment the corresponding
109 // clock if needed.
110 CreateWitness(time lamport.Time) error
111
112 // EditWitness witness another edition time and increment the corresponding
113 // clock if needed.
114 EditWitness(time lamport.Time) error
115}
116
117// Witnesser is a function that will initialize the clocks of a repo
118// from scratch
119type Witnesser func(repo ClockedRepo) error
120
121func prepareTreeEntries(entries []TreeEntry) bytes.Buffer {
122 var buffer bytes.Buffer
123
124 for _, entry := range entries {
125 buffer.WriteString(entry.Format())
126 }
127
128 return buffer
129}
130
131func readTreeEntries(s string) ([]TreeEntry, error) {
132 split := strings.Split(strings.TrimSpace(s), "\n")
133
134 casted := make([]TreeEntry, len(split))
135 for i, line := range split {
136 if line == "" {
137 continue
138 }
139
140 entry, err := ParseTreeEntry(line)
141
142 if err != nil {
143 return nil, err
144 }
145
146 casted[i] = entry
147 }
148
149 return casted, nil
150}