georgi-git_store 0.2.3 → 0.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +1 -0
- data/Rakefile +35 -0
- data/git_store.gemspec +2 -1
- data/lib/git_store.rb +7 -0
- data/test/git_store_spec.rb +141 -141
- metadata +3 -2
data/.gitignore
CHANGED
data/Rakefile
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require "rake/rdoctask"
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'spec/rake/spectask'
|
6
|
+
rescue LoadError
|
7
|
+
puts <<-EOS
|
8
|
+
To use rspec for testing you must install the rspec gem:
|
9
|
+
gem install rspec
|
10
|
+
EOS
|
11
|
+
exit(0)
|
12
|
+
end
|
13
|
+
|
14
|
+
desc "Run all specs"
|
15
|
+
Spec::Rake::SpecTask.new(:spec) do |t|
|
16
|
+
t.spec_opts = ['-cfs']
|
17
|
+
t.spec_files = FileList['test/**/*_spec.rb']
|
18
|
+
end
|
19
|
+
|
20
|
+
desc "Print SpecDocs"
|
21
|
+
Spec::Rake::SpecTask.new(:doc) do |t|
|
22
|
+
t.spec_opts = ["--format", "specdoc"]
|
23
|
+
t.spec_files = FileList['test/*_spec.rb']
|
24
|
+
end
|
25
|
+
|
26
|
+
desc "Generate the RDoc"
|
27
|
+
Rake::RDocTask.new do |rdoc|
|
28
|
+
files = ["README.md", "LICENSE", "lib/**/*.rb"]
|
29
|
+
rdoc.rdoc_files.add(files)
|
30
|
+
rdoc.main = "README.md"
|
31
|
+
rdoc.title = "Git Store - using Git as versioned data store in Ruby"
|
32
|
+
end
|
33
|
+
|
34
|
+
desc "Run the rspec"
|
35
|
+
task :default => :spec
|
data/git_store.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'git_store'
|
3
|
-
s.version = '0.2.
|
3
|
+
s.version = '0.2.4'
|
4
4
|
s.summary = 'a simple data store based on git'
|
5
5
|
s.author = 'Matthias Georgi'
|
6
6
|
s.email = 'matti.georgi@gmail.com'
|
@@ -12,6 +12,7 @@ Gem::Specification.new do |s|
|
|
12
12
|
s.files = %w{
|
13
13
|
.gitignore
|
14
14
|
LICENSE
|
15
|
+
Rakefile
|
15
16
|
README.md
|
16
17
|
git_store.gemspec
|
17
18
|
lib/git_store.rb
|
data/lib/git_store.rb
CHANGED
@@ -45,10 +45,16 @@ class GitStore
|
|
45
45
|
@root = Tree.new(self)
|
46
46
|
@packs = {}
|
47
47
|
|
48
|
+
raise(ArgumentError, "first argument must be a valid Git repository") unless valid?
|
49
|
+
|
48
50
|
load_packs("#{path}/.git/objects/pack")
|
49
51
|
load
|
50
52
|
end
|
51
53
|
|
54
|
+
def valid?
|
55
|
+
File.exists?("#{path}/.git")
|
56
|
+
end
|
57
|
+
|
52
58
|
# The path to the current head file.
|
53
59
|
def head_path
|
54
60
|
"#{path}/.git/refs/heads/#{branch}"
|
@@ -284,6 +290,7 @@ class GitStore
|
|
284
290
|
def initialize(path)
|
285
291
|
@mtime = {}
|
286
292
|
super
|
293
|
+
rescue ArgumentError
|
287
294
|
end
|
288
295
|
|
289
296
|
def load
|
data/test/git_store_spec.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
|
-
require
|
1
|
+
require "#{File.dirname(__FILE__)}/../lib/git_store"
|
2
2
|
|
3
3
|
describe GitStore do
|
4
4
|
|
5
|
-
REPO = File.expand_path(File.dirname(__FILE__) + '/repo')
|
5
|
+
#REPO = File.expand_path(File.dirname(__FILE__) + '/repo')
|
6
|
+
REPO = '/tmp/git_store_test'
|
6
7
|
|
7
|
-
before do
|
8
|
+
before(:each) do
|
8
9
|
FileUtils.rm_rf REPO
|
9
10
|
Dir.mkdir REPO
|
10
11
|
Dir.chdir REPO
|
@@ -24,187 +25,186 @@ describe GitStore do
|
|
24
25
|
end
|
25
26
|
end
|
26
27
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
@use_git = true
|
31
|
-
@store = GitStore.new(REPO)
|
32
|
-
instance_eval(&block)
|
33
|
-
end
|
34
|
-
|
35
|
-
super "#{text} without git" do
|
36
|
-
@use_git = false
|
37
|
-
@store = GitStore::FileStore.new(REPO)
|
38
|
-
instance_eval(&block)
|
39
|
-
end
|
40
|
-
end
|
28
|
+
shared_examples_for 'all stores' do
|
29
|
+
it 'should find modified entries' do
|
30
|
+
store['a'] = 'Hello'
|
41
31
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
file 'a', 'Hello'
|
32
|
+
store.root.should be_modified
|
33
|
+
store.root.table['a'].should be_modified
|
46
34
|
|
47
|
-
|
48
|
-
File.should be_exist(store.object_path(store.read_head))
|
49
|
-
end
|
35
|
+
store.commit
|
50
36
|
|
51
|
-
|
52
|
-
next unless @use_git
|
37
|
+
store['a'] = 'Bello'
|
53
38
|
|
54
|
-
|
39
|
+
store.root.table['a'].should be_modified
|
40
|
+
end
|
55
41
|
|
56
|
-
|
57
|
-
|
42
|
+
it 'should load a repo' do
|
43
|
+
file 'a', 'Hello'
|
44
|
+
file 'b', 'World'
|
45
|
+
|
46
|
+
store.load
|
58
47
|
|
59
|
-
|
60
|
-
|
48
|
+
store['a'].should == 'Hello'
|
49
|
+
store['b'].should == 'World'
|
50
|
+
end
|
61
51
|
|
62
|
-
|
63
|
-
|
52
|
+
it 'should load folders' do
|
53
|
+
file 'x/a', 'Hello'
|
54
|
+
file 'y/b', 'World'
|
55
|
+
|
56
|
+
store.load
|
57
|
+
store['x'].should be_kind_of(GitStore::Tree)
|
58
|
+
store['y'].should be_kind_of(GitStore::Tree)
|
64
59
|
|
65
|
-
|
60
|
+
store['x']['a'].should == 'Hello'
|
61
|
+
store['y']['b'].should == 'World'
|
62
|
+
end
|
66
63
|
|
67
|
-
|
64
|
+
it 'should load yaml' do
|
65
|
+
file 'x/a.yml', '[1, 2, 3, 4]'
|
68
66
|
|
69
|
-
|
70
|
-
|
67
|
+
store.load
|
68
|
+
|
69
|
+
store['x']['a.yml'].should == [1,2,3,4]
|
70
|
+
store['x']['a.yml'] = [1,2,3,4,5]
|
71
|
+
end
|
71
72
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
73
|
+
it 'should resolve paths' do
|
74
|
+
file 'x/a', 'Hello'
|
75
|
+
file 'y/b', 'World'
|
76
|
+
|
77
|
+
store.load
|
78
|
+
|
79
|
+
store['x/a'].should == 'Hello'
|
80
|
+
store['y/b'].should == 'World'
|
77
81
|
|
78
|
-
|
79
|
-
store['b'].should == 'World'
|
80
|
-
end
|
82
|
+
store['y/b'] = 'Now this'
|
81
83
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
file 'a/b', 'Hello'
|
86
|
-
file 'c/d', 'World'
|
84
|
+
store['y']['b'].should == 'Now this'
|
85
|
+
end
|
87
86
|
|
88
|
-
|
89
|
-
store
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
end
|
94
|
-
rescue
|
87
|
+
it 'should create new trees' do
|
88
|
+
store['new/tree'] = 'This tree'
|
89
|
+
store['this', 'tree'] = 'Another'
|
90
|
+
store['new/tree'].should == 'This tree'
|
91
|
+
store['this/tree'].should == 'Another'
|
95
92
|
end
|
96
93
|
|
97
|
-
|
98
|
-
|
99
|
-
|
94
|
+
it 'should delete entries' do
|
95
|
+
store['a'] = 'Hello'
|
96
|
+
store.delete('a')
|
97
|
+
|
98
|
+
store['a'].should be_nil
|
99
|
+
end
|
100
100
|
end
|
101
101
|
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
102
|
+
describe 'with Git' do
|
103
|
+
before(:each) do
|
104
|
+
`git init`
|
105
|
+
@use_git = true
|
106
|
+
@store = GitStore.new(REPO)
|
107
|
+
end
|
107
108
|
|
108
|
-
|
109
|
-
|
110
|
-
|
109
|
+
it_should_behave_like 'all stores'
|
110
|
+
|
111
|
+
it 'should have a head commit' do
|
112
|
+
file 'a', 'Hello'
|
113
|
+
|
114
|
+
store.read_head.should_not be_nil
|
115
|
+
File.should be_exist(store.object_path(store.read_head))
|
111
116
|
end
|
112
117
|
|
113
|
-
|
114
|
-
|
115
|
-
store['a/b'].should == 'Changed'
|
116
|
-
store['c/d'].should == 'World'
|
117
|
-
store['x/a'].should == 'Added'
|
118
|
-
end
|
118
|
+
it 'should detect changes' do
|
119
|
+
file 'a', 'Hello'
|
119
120
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
file 'a/b', 'Hello'
|
121
|
+
store.should be_changed
|
122
|
+
end
|
124
123
|
|
125
|
-
|
124
|
+
it 'should rollback a transaction' do
|
125
|
+
file 'a/b', 'Hello'
|
126
|
+
file 'c/d', 'World'
|
126
127
|
|
127
|
-
|
128
|
-
Thread.start do
|
128
|
+
begin
|
129
129
|
store.transaction do
|
130
|
-
store['a/b'] = 'Changed
|
130
|
+
store['a/b'] = 'Changed'
|
131
|
+
store['x/a'] = 'Added'
|
132
|
+
raise
|
131
133
|
end
|
132
|
-
|
134
|
+
rescue
|
133
135
|
end
|
134
|
-
store['a/b'] = 'Changed'
|
135
|
-
end
|
136
|
-
|
137
|
-
sleep 0.01 until ready
|
138
136
|
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
137
|
+
store['a/b'].should == 'Hello'
|
138
|
+
store['c/d'].should == 'World'
|
139
|
+
store['x/a'].should be_nil
|
140
|
+
end
|
143
141
|
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
store.load
|
149
|
-
store['x'].should be_kind_of(GitStore::Tree)
|
150
|
-
store['y'].should be_kind_of(GitStore::Tree)
|
142
|
+
it 'should commit a transaction' do
|
143
|
+
file 'a/b', 'Hello'
|
144
|
+
file 'c/d', 'World'
|
151
145
|
|
152
|
-
|
153
|
-
|
154
|
-
|
146
|
+
store.transaction do
|
147
|
+
store['a/b'] = 'Changed'
|
148
|
+
store['x/a'] = 'Added'
|
149
|
+
end
|
155
150
|
|
156
|
-
|
157
|
-
next if not @use_git
|
151
|
+
store.load
|
158
152
|
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
`git checkout`
|
165
|
-
|
166
|
-
File.should be_exist('c')
|
167
|
-
File.should be_exist('d')
|
153
|
+
store['a/b'].should == 'Changed'
|
154
|
+
store['c/d'].should == 'World'
|
155
|
+
store['x/a'].should == 'Added'
|
156
|
+
end
|
168
157
|
|
169
|
-
|
170
|
-
|
171
|
-
end
|
158
|
+
it 'should allow only one transaction' do
|
159
|
+
file 'a/b', 'Hello'
|
172
160
|
|
173
|
-
|
174
|
-
file 'x/a.yml', '[1, 2, 3, 4]'
|
161
|
+
ready = false
|
175
162
|
|
176
|
-
|
163
|
+
store.transaction do
|
164
|
+
Thread.start do
|
165
|
+
store.transaction do
|
166
|
+
store['a/b'] = 'Changed by second thread'
|
167
|
+
end
|
168
|
+
ready = true
|
169
|
+
end
|
170
|
+
store['a/b'] = 'Changed'
|
171
|
+
end
|
177
172
|
|
178
|
-
|
179
|
-
store['x']['a.yml'] = [1,2,3,4,5]
|
180
|
-
end
|
173
|
+
sleep 0.01 until ready
|
181
174
|
|
182
|
-
|
183
|
-
file 'x/a', 'Hello'
|
184
|
-
file 'y/b', 'World'
|
175
|
+
store.load
|
185
176
|
|
186
|
-
|
187
|
-
|
188
|
-
store['x/a'].should == 'Hello'
|
189
|
-
store['y/b'].should == 'World'
|
177
|
+
store['a/b'].should == 'Changed by second thread'
|
178
|
+
end
|
190
179
|
|
191
|
-
|
180
|
+
it 'should commit added files' do
|
181
|
+
store.load
|
182
|
+
store['c'] = 'Hello'
|
183
|
+
store['d'] = 'World'
|
184
|
+
store.commit
|
192
185
|
|
193
|
-
|
194
|
-
|
186
|
+
`git checkout`
|
187
|
+
|
188
|
+
File.should be_exist('c')
|
189
|
+
File.should be_exist('d')
|
195
190
|
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
store['new/tree'].should == 'This tree'
|
200
|
-
store['this/tree'].should == 'Another'
|
191
|
+
File.read('c').should == 'Hello'
|
192
|
+
File.read('d').should == 'World'
|
193
|
+
end
|
201
194
|
end
|
202
195
|
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
196
|
+
describe 'without Git' do
|
197
|
+
before(:each) do
|
198
|
+
@use_git = false
|
199
|
+
@store = GitStore::FileStore.new(REPO)
|
200
|
+
end
|
201
|
+
|
202
|
+
it_should_behave_like 'all stores'
|
208
203
|
end
|
209
204
|
|
205
|
+
it 'should fail to initialize without a valid git repository' do
|
206
|
+
lambda {
|
207
|
+
GitStore.new(REPO)
|
208
|
+
}.should raise_error(ArgumentError)
|
209
|
+
end
|
210
210
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: georgi-git_store
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matthias Georgi
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-04-08 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -24,6 +24,7 @@ extra_rdoc_files:
|
|
24
24
|
files:
|
25
25
|
- .gitignore
|
26
26
|
- LICENSE
|
27
|
+
- Rakefile
|
27
28
|
- README.md
|
28
29
|
- git_store.gemspec
|
29
30
|
- lib/git_store.rb
|