-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathdriver_git.go
150 lines (125 loc) · 3.39 KB
/
driver_git.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
package gitdb
import (
"errors"
"fmt"
"os"
"path/filepath"
"strings"
"time"
"github.com/bouggo/log"
)
type gitDriver struct {
driver gitDBDriver
absDBPath string
}
func (d *gitDriver) name() string {
return d.driver.name()
}
// if .db directory does not exist, create it and attempt
// to do a git clone from remote
func (d *gitDriver) setup(db *gitdb) error {
d.absDBPath = db.dbDir()
if err := d.driver.setup(db); err != nil {
return err
}
// create .ssh dir
if err := db.generateSSHKeyPair(); err != nil {
return err
}
// force git to only use generated ssh key and not fallback to ssh_config or ssh-agent
sshCmd := fmt.Sprintf("ssh -F none -i '%s' -o IdentitiesOnly=yes -o StrictHostKeyChecking=no", db.privateKeyFilePath())
if err := os.Setenv("GIT_SSH_COMMAND", sshCmd); err != nil {
return err
}
dataDir := db.dbDir()
dotGitDir := filepath.Join(dataDir, ".git")
if _, err := os.Stat(dataDir); err != nil {
log.Info("database not initialized")
// create db directory
if err := os.MkdirAll(dataDir, 0755); err != nil {
return err
}
if len(db.config.OnlineRemote) > 0 {
if err := d.clone(); err != nil {
return err
}
if err := d.addRemote(); err != nil {
return err
}
} else if err := d.init(); err != nil {
return err
}
} else if _, err := os.Stat(dotGitDir); err != nil {
log.Info(err.Error())
return errors.New(db.config.DBPath + " is not a git repository")
} else if len(db.config.OnlineRemote) > 0 { // TODO Review this properly
// if remote is configured i.e stat .git/refs/remotes/online
// if remote dir does not exist add remotes
remotesPath := filepath.Join(dataDir, ".git", "refs", "remotes", "online")
if _, err := os.Stat(remotesPath); err != nil {
if err := d.addRemote(); err != nil {
return err
}
}
}
return nil
}
// this function is only called once. I.e when a initializing the database for the
// very first time. In this case we must clone the online repo
func (d *gitDriver) init() error {
// we take this very seriously
if err := d.driver.init(); err != nil {
if err := os.RemoveAll(d.absDBPath); err != nil {
return err
}
}
return nil
}
func (d *gitDriver) clone() error {
// we take this very seriously
log.Info("cloning down database...")
if err := d.driver.clone(); err != nil {
// TODO if err is authentication related generate key pair
if err := os.RemoveAll(d.absDBPath); err != nil {
return err
}
if strings.Contains(err.Error(), "denied") {
return ErrAccessDenied
}
return err
}
return nil
}
func (d *gitDriver) addRemote() error {
// we take this very seriously
if err := d.driver.addRemote(); err != nil {
if !strings.Contains(err.Error(), "already exists") {
if err := os.RemoveAll(d.absDBPath); err != nil { // TODO is this necessary?
return err
}
return err
}
}
return nil
}
func (d *gitDriver) sync() error {
return d.driver.sync()
}
func (d *gitDriver) commit(filePath string, msg string, user *User) error {
mu.Lock()
defer mu.Unlock()
if err := d.driver.commit(filePath, msg, user); err != nil {
// todo: update to return this error but for now at least log it
log.Error(err.Error())
}
return nil
}
func (d *gitDriver) undo() error {
return d.driver.undo()
}
func (d *gitDriver) changedFiles() []string {
return d.driver.changedFiles()
}
func (d *gitDriver) lastCommitTime() (time.Time, error) {
return d.driver.lastCommitTime()
}