-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgitdb.go
More file actions
141 lines (121 loc) · 2.77 KB
/
gitdb.go
File metadata and controls
141 lines (121 loc) · 2.77 KB
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
package gitdb
import (
"errors"
"fmt"
"io/ioutil"
"os"
"sync"
"time"
"gopkg.in/src-d/go-git.v4/plumbing/object"
git "gopkg.in/src-d/go-git.v4"
)
// DB is an interface to the git db
type DB interface {
// Save the given data to the database, creating a new commit with a random msg
Save(data []byte, filename string) error
// Save the given data to the database, creating a new commit wth the given commit msg
SaveWithMessage(data []byte, filename string, commitMessage string) error
// Open the db at the given path
Open(path string) error
// Read a file from the db and return it's contents
Read(filename string) ([]byte, error)
// Version returns the version of the database (hash)
Version() string
}
var instance DB
var once sync.Once
// Errors that could be encountered
var (
ErrorNoDB = errors.New("DB not initialized")
)
// TODO: use interfaces instead so we can mock
type db struct {
m *sync.Mutex
repo *git.Repository
path string
}
// GetInstance gets an instance of the git db
func GetInstance() DB {
once.Do(func() {
instance = &db{
m: &sync.Mutex{},
}
})
return instance
}
func (d *db) Save(data []byte, filename string) error {
return d.save(data, filename, "")
}
func (d *db) SaveWithMessage(data []byte, filename string, commitMessage string) error {
return d.save(data, filename, commitMessage)
}
func (d *db) save(data []byte, filename string, commitMessage string) error {
// synchronize
d.m.Lock()
defer d.m.Unlock()
// check if repo is available
if d.repo == nil {
return ErrorNoDB
}
// (over)write file to path
if err := ioutil.WriteFile(fmt.Sprintf("%s/%s", d.path, filename), data, os.ModePerm); err != nil {
return err
}
// commit with random msg
worktree, err := d.repo.Worktree()
if err != nil {
return err
}
_, err = worktree.Add(filename)
if err != nil {
return err
}
m := commitMessage
if commitMessage == "" {
m = "some message"
}
_, err = worktree.Commit(m, &git.CommitOptions{
Author: &object.Signature{
Name: "gitdb",
Email: "gitdb@github.com",
When: time.Now(),
},
})
if err != nil {
return err
}
return nil
}
func (d *db) Open(path string) error {
// try to init, if error returned, then it already exists
if repo, err := git.PlainInit(path, false); err != nil {
// already exists, simply open
repo, err := git.PlainOpen(path)
if err != nil {
return err
}
d.repo = repo
d.path = path
} else {
d.repo = repo
d.path = path
}
return nil
}
func (d *db) Read(filename string) ([]byte, error) {
// naive file read
d.m.Lock()
defer d.m.Unlock()
contents, err := ioutil.ReadFile(filename)
if err != nil {
return nil, err
}
return contents, nil
}
func (d *db) Version() string {
ref, err := d.repo.Head()
if err != nil {
return "error"
}
return ref.String()
}