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
33// Repo represents a source code repository.
34type Repo interface {
35 RepoCommon
36
37 // FetchRefs fetch git refs from a remote
38 FetchRefs(remote string, refSpec string) (string, error)
39
40 // PushRefs push git refs to a remote
41 PushRefs(remote string, refSpec string) (string, error)
42
43 // StoreData will store arbitrary data and return the corresponding hash
44 StoreData(data []byte) (git.Hash, error)
45
46 // ReadData will attempt to read arbitrary data from the given hash
47 ReadData(hash git.Hash) ([]byte, error)
48
49 // StoreTree will store a mapping key-->Hash as a Git tree
50 StoreTree(mapping []TreeEntry) (git.Hash, error)
51
52 // StoreCommit will store a Git commit with the given Git tree
53 StoreCommit(treeHash git.Hash) (git.Hash, error)
54
55 // StoreCommit will store a Git commit with the given Git tree
56 StoreCommitWithParent(treeHash git.Hash, parent git.Hash) (git.Hash, error)
57
58 // UpdateRef will create or update a Git reference
59 UpdateRef(ref string, hash git.Hash) error
60
61 // ListRefs will return a list of Git ref matching the given refspec
62 ListRefs(refspec string) ([]string, error)
63
64 // RefExist will check if a reference exist in Git
65 RefExist(ref string) (bool, error)
66
67 // CopyRef will create a new reference with the same value as another one
68 CopyRef(source string, dest string) error
69
70 // ListCommits will return the list of tree hashes of a ref, in chronological order
71 ListCommits(ref string) ([]git.Hash, error)
72
73 // ListEntries will return the list of entries in a Git tree
74 ListEntries(hash git.Hash) ([]TreeEntry, error)
75
76 // FindCommonAncestor will return the last common ancestor of two chain of commit
77 FindCommonAncestor(hash1 git.Hash, hash2 git.Hash) (git.Hash, error)
78
79 // GetTreeHash return the git tree hash referenced in a commit
80 GetTreeHash(commit git.Hash) (git.Hash, error)
81}
82
83type ClockedRepo interface {
84 Repo
85
86 // LoadClocks read the clocks values from the on-disk repo
87 LoadClocks() error
88
89 // WriteClocks write the clocks values into the repo
90 WriteClocks() error
91
92 // CreateTimeIncrement increment the creation clock and return the new value.
93 CreateTimeIncrement() (lamport.Time, error)
94
95 // EditTimeIncrement increment the edit clock and return the new value.
96 EditTimeIncrement() (lamport.Time, error)
97
98 // CreateWitness witness another create time and increment the corresponding
99 // clock if needed.
100 CreateWitness(time lamport.Time) error
101
102 // EditWitness witness another edition time and increment the corresponding
103 // clock if needed.
104 EditWitness(time lamport.Time) error
105}
106
107func prepareTreeEntries(entries []TreeEntry) bytes.Buffer {
108 var buffer bytes.Buffer
109
110 for _, entry := range entries {
111 buffer.WriteString(entry.Format())
112 }
113
114 return buffer
115}
116
117func readTreeEntries(s string) ([]TreeEntry, error) {
118 split := strings.Split(s, "\n")
119
120 casted := make([]TreeEntry, len(split))
121 for i, line := range split {
122 if line == "" {
123 continue
124 }
125
126 entry, err := ParseTreeEntry(line)
127
128 if err != nil {
129 return nil, err
130 }
131
132 casted[i] = entry
133 }
134
135 return casted, nil
136}