treet 0.8.2 → 0.10.2

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.
@@ -1,22 +1,17 @@
1
1
  # encoding: UTF-8
2
- require "spec_helper"
2
+ require "test_helper"
3
3
 
4
4
  describe "Repository Farm" do
5
5
  it "should export as array of hashes with an xref value" do
6
6
  farm = Treet::Farm.new(:root => "#{File.dirname(__FILE__)}/../repos/farm1", :xref => 'test')
7
- farm.export.should == [
7
+ farm.repos.count.must_equal 2
8
+ farm.export.must_equal [
8
9
  {
9
10
  'name' => {
10
11
  'full' => 'John Bigbooté'
11
- },
12
- 'xref' => {
13
- 'test' => 'one'
14
12
  }
15
13
  },
16
14
  {
17
- 'xref' => {
18
- 'test' => 'two'
19
- },
20
15
  'name' => {
21
16
  'full' => 'John Smallberries',
22
17
  'first' => 'John',
@@ -39,26 +34,34 @@ describe "Repository Farm" do
39
34
  it "planting should create a directory of UUID-labeled repos" do
40
35
  farm = Treet::Farm.plant(:json => "#{File.dirname(__FILE__)}/../json/master.json", :root => Dir.mktmpdir)
41
36
 
42
- Dir.glob("#{farm.root}/*").count.should == 3
43
- Dir.glob("#{farm.root}/*/emails/*").count.should == 5
44
- Dir.glob("#{farm.root}/*/addresses/*").count.should == 1
37
+ Dir.glob("#{farm.root}/*").count.must_equal 3
38
+ Dir.glob("#{farm.root}/*/emails/*").count.must_equal 5
39
+ Dir.glob("#{farm.root}/*/addresses/*").count.must_equal 1
45
40
 
46
41
  FileUtils.rm_rf(farm.root)
47
42
  end
48
43
 
49
- it "should be retrievable by repo label/xref" do
50
- farm = Treet::Farm.new(:root => "#{File.dirname(__FILE__)}/../repos/farm1", :xref => 'test')
51
- farm['two'].root.should == "#{File.dirname(__FILE__)}/../repos/farm1/two"
52
- farm['two'].to_hash['xref'].should == {'test' => 'two'}
53
- end
44
+ # it "should be retrievable by repo label/xref" do
45
+ # farm = Treet::Farm.new(:root => "#{File.dirname(__FILE__)}/../repos/farm1", :xref => 'test')
46
+ # farm['two'].root.must_equal "#{File.dirname(__FILE__)}/../repos/farm1/two"
47
+ # farm['two'].to_hash['xref'].must_equal {'test' => 'two'}
48
+ # end
54
49
 
55
50
  it "should take additions" do
56
51
  farm = Treet::Farm.plant(:json => "#{File.dirname(__FILE__)}/../json/master.json", :root => Dir.mktmpdir)
52
+ farm.repos.count.must_equal 3
57
53
 
58
54
  bob_hash = load_json("bob1")
59
55
  repo = farm.add(bob_hash)
60
- repo.root.should =~ /#{farm.root}/
61
- Dir.glob("#{farm.root}/*").count.should == 4
56
+ repo.root.must_match /#{farm.root}/
57
+ Dir.glob("#{farm.root}/*").count.must_equal 4
58
+
59
+ farm.repos.count.must_equal 4
60
+
61
+ # now try with a predefined ID
62
+ repo = farm.add(bob_hash, :id => '12345')
63
+ repo.root.must_equal "#{farm.root}/12345"
64
+ Dir.glob("#{farm.root}/*").count.must_equal 5
62
65
 
63
66
  FileUtils.rm_rf(farm.root)
64
67
  end
@@ -0,0 +1,63 @@
1
+ # encoding: UTF-8
2
+ require "test_helper"
3
+ require "pp"
4
+
5
+ describe Treet::Gitfarm do
6
+ def self.empty_gitfarm
7
+ f = Treet::Gitfarm.new(
8
+ :root => Dir.mktmpdir('farm', $topdir),
9
+ :xref => 'testapp',
10
+ :author => {:name => 'Bob', :email => 'bob@example.com'}
11
+ )
12
+ # puts "MADE AN EMPTY FARM OF #{f.repotype}"
13
+ f
14
+ end
15
+
16
+ describe "a directory of labeled git repos" do
17
+ def self.plantfarm
18
+ @farm ||= Treet::Gitfarm.plant(
19
+ :json => jsonfile('master'),
20
+ :root => Dir.mktmpdir('farm', $topdir),
21
+ :author => {:name => 'Bob', :email => 'bob@example.com'},
22
+ :xref => 'myapp'
23
+ )
24
+ end
25
+
26
+ let(:farm) { self.class.plantfarm }
27
+
28
+ it "should be populated" do
29
+ farm.repos.count.must_equal 3
30
+ end
31
+
32
+ it "should all be gitified" do
33
+ farm.repos.each do |id, repo|
34
+ repo.head.wont_be_nil
35
+ repo.tags.must_be_empty
36
+ end
37
+ end
38
+ end
39
+
40
+ describe "new repo in empty farm" do
41
+ def self.dofarm
42
+ @farm ||= begin
43
+ farm = empty_gitfarm
44
+ farm.add(load_json('bob1'), :tag => "app1")
45
+ farm
46
+ end
47
+ end
48
+
49
+ let(:farm) { self.class.dofarm }
50
+
51
+ it "is the only repo" do
52
+ farm.repos.count.must_equal 1
53
+ end
54
+
55
+ it "can be tagged" do
56
+ farm.must_be_instance_of Treet::Gitfarm
57
+ bob = farm.repos.values.first
58
+ bob.wont_be_nil
59
+ bob.must_be_instance_of Treet::Gitrepo
60
+ bob.tags.first.name.must_equal 'refs/tags/app1'
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,346 @@
1
+ # encoding: UTF-8
2
+ require "test_helper"
3
+ require "pp"
4
+
5
+ # convert a hash to a gitrepo
6
+ # convert a plain repo to a gitrepo
7
+ # convert a gitrepo to a plain repo
8
+ # initialize a treet git from an existing gitrepo (with a treet::repo structure)
9
+ # patch a gitrepo (with commit) - verify commit structure
10
+ # pulling past snapshots
11
+
12
+ describe Treet::Gitrepo do
13
+ def self.make_gitrepo(filename, opts = {})
14
+ thash = Treet::Hash.new(load_json(filename))
15
+ trepo = thash.to_repo(Dir.mktmpdir('repo', $topdir))
16
+ Treet::Gitrepo.new(trepo.root, opts)
17
+ end
18
+
19
+ def make_gitrepo(filename, opts = {})
20
+ self.class.make_gitrepo(filename, opts)
21
+ end
22
+
23
+ def hashalike(h1, h2)
24
+ Treet::Hash.diff(h1, h2).empty?
25
+ end
26
+
27
+ describe "creation" do
28
+ it "must have an author" do
29
+ ->{ make_gitrepo('one') }.must_raise(ArgumentError, "xxx")
30
+ end
31
+
32
+ # TODO: must have an existing & non-empty directory tree
33
+ end
34
+
35
+ describe "a minimal non-empty untagged gitrepo" do
36
+ def self.make_johnb
37
+ @memo ||= begin
38
+ data = {
39
+ "name" => {
40
+ "full" => "John Bigbooté"
41
+ }
42
+ }
43
+ thash = Treet::Hash.new(data)
44
+ trepo = thash.to_repo(Dir.mktmpdir('repo', $topdir))
45
+ Treet::Gitrepo.new(trepo.root, :author => {:name => 'Bob', :email => 'bob@example.com'})
46
+ end
47
+ end
48
+
49
+ let(:johnb) { self.class.make_johnb }
50
+
51
+ it "should have exactly one commit" do
52
+ johnb.head.wont_be_nil
53
+ johnb.refs.count.must_equal 1
54
+ johnb.refs.first.target.must_equal johnb.head.target
55
+ r = Rugged::Repository.new(johnb.root)
56
+ r.lookup(johnb.head.target).parents.must_be_empty
57
+ end
58
+
59
+ it "should have a single entry" do
60
+ johnb.index.count.must_equal 1
61
+ johnb.entries.must_equal ['name']
62
+ end
63
+
64
+ it "should fetch data content" do
65
+ johnb.to_hash.must_equal load_json('one')
66
+ end
67
+
68
+ it "should have no tags" do
69
+ johnb.tags.must_be_empty
70
+ end
71
+
72
+ it "should fail on unknown tag lookups" do
73
+ ->{johnb.to_hash(:tag => 'nosuchtag')}.must_raise ArgumentError
74
+ end
75
+
76
+ it "should have no branches" do
77
+ johnb.branches.must_be_empty
78
+ end
79
+
80
+ it "should return commit SHA for version label" do
81
+ johnb.version.must_equal johnb.head.target
82
+ end
83
+
84
+ it "should return nil for unknown tag versions" do
85
+ johnb.version(:tag => 'nosuchtag').must_be_nil
86
+ end
87
+ end
88
+
89
+
90
+ describe "a patched gitrepo" do
91
+ def self.patch_johnb
92
+ @memo ||= begin
93
+ data = {
94
+ "name" => {
95
+ "full" => "John Bigbooté"
96
+ }
97
+ }
98
+ thash = Treet::Hash.new(data)
99
+ trepo = thash.to_repo(Dir.mktmpdir('repo', $topdir))
100
+ r = Treet::Gitrepo.new(trepo.root, :author => {:name => 'Bob', :email => 'bob@example.com'})
101
+ r.patch([
102
+ [
103
+ "+",
104
+ "org.name",
105
+ "Bigcorp"
106
+ ]
107
+ ])
108
+ r
109
+ end
110
+ end
111
+
112
+ let(:repo) { self.class.patch_johnb }
113
+
114
+ it "should have correct git index" do
115
+ repo.index.count.must_equal 2
116
+ repo.entries.must_include 'name'
117
+ repo.entries.must_include 'org'
118
+ end
119
+
120
+ it "should hashify correctly" do
121
+ expectation = load_json('one').merge({'org' => {'name' => 'Bigcorp'}})
122
+ repo.to_hash.must_equal expectation
123
+ end
124
+
125
+ it "should have 2 commits" do
126
+ r = Rugged::Repository.new(repo.root)
127
+ latest_commit = r.head.target
128
+ r.lookup(latest_commit).parents.count.must_equal 1
129
+ previous_commit = r.lookup(latest_commit).parents.first
130
+ previous_commit.parents.must_be_empty
131
+ end
132
+
133
+ it "should have no tags" do
134
+ repo.tags.must_be_empty
135
+ end
136
+
137
+ # it "should be able to reverse-engineer the patch from the git history" do
138
+ # skip
139
+ # # rugged has a `Rugged::Commit#diff-tree` on the roadmap (see `USAGE.rb`), not yet implemented
140
+ # end
141
+ end
142
+
143
+ describe "patched with a delete" do
144
+ let(:repo) do
145
+ r = make_gitrepo('two', :author => {:name => 'Bob', :email => 'bob@example.com'})
146
+ r.patch([
147
+ [
148
+ "-",
149
+ "emails[]",
150
+ { "label" => "home", "email" => "johns@lectroid.com" }
151
+ ]
152
+ ])
153
+ r
154
+ end
155
+
156
+ it "should have correct git index" do
157
+ repo.index.count.must_equal 2
158
+ repo.entries.must_include 'name'
159
+ repo.entries.grep(/emails/).wont_be_empty
160
+ end
161
+
162
+ it "should hashify correctly" do
163
+ # should reflect the deletion in current state
164
+ expectation = load_json('two')
165
+ expectation['emails'].delete_if {|v| v['label'] == 'home'}
166
+ repo.to_hash.must_equal expectation
167
+ end
168
+
169
+ it "should have 2 commits" do
170
+ r = Rugged::Repository.new(repo.root)
171
+ latest_commit = r.head.target
172
+ r.lookup(latest_commit).parents.count.must_equal 1
173
+ previous_commit = r.lookup(latest_commit).parents.first
174
+ previous_commit.parents.must_be_empty
175
+ end
176
+
177
+ it "should show the original state in the previous commit" do
178
+ r = Rugged::Repository.new(repo.root)
179
+ latest_commit = r.head.target
180
+ r.lookup(latest_commit).parents.count.must_equal 1
181
+ previous_commit = r.lookup(latest_commit).parents.first
182
+ assert hashalike(repo.to_hash(:commit => previous_commit.oid), load_json('two'))
183
+ end
184
+ end
185
+
186
+ describe "a tagged & patched repo" do
187
+ def self.makerepo
188
+ @cache ||= begin
189
+ r = make_gitrepo('two',
190
+ :author => {:name => 'Bob', :email => 'bob@example.com'},
191
+ :xrefkey => 'app1',
192
+ :xref => 'APP1_ID'
193
+ )
194
+ r.tag('app1')
195
+ r.patch([
196
+ [
197
+ "-",
198
+ "emails[]",
199
+ { "label" => "home", "email" => "johns@lectroid.com" }
200
+ ],
201
+ [
202
+ "+",
203
+ "name.first",
204
+ "Ralph"
205
+ ]
206
+ ])
207
+ r
208
+ end
209
+ end
210
+
211
+ let(:repo) { self.class.makerepo }
212
+
213
+ it "should correctly commit the existing updated git artifacts" do
214
+ repo.to_hash(:commit => repo.head.target)['name']['first'].must_equal 'Ralph'
215
+ end
216
+
217
+ it "should not have an index entry for the removed item" do
218
+ repo.entries.must_include 'name'
219
+ repo.entries.grep(/^emails/).wont_be_empty
220
+ repo.index.count.must_equal 2
221
+ end
222
+
223
+ it "should have tag not pointing to HEAD" do
224
+ repo.tags.count.must_equal 1
225
+ repo.tags.first.name.must_equal "refs/tags/app1"
226
+ repo.tags.first.target.wont_equal repo.head.target
227
+ end
228
+
229
+ it "should have the original image for the tag" do
230
+ refute hashalike(repo.to_hash, repo.to_hash(:tag => 'app1'))
231
+ assert hashalike(repo.to_hash(:tag => 'app1'), load_json('two'))
232
+ end
233
+
234
+ it "should have no branches" do
235
+ repo.branches.must_be_empty
236
+ end
237
+
238
+ it "should track version label by tag" do
239
+ repo.version.must_equal repo.head.target
240
+ repo.version(:tag => 'app1').must_equal repo.tags.first.target
241
+ end
242
+ end
243
+
244
+ describe "a tagged repo" do
245
+ let(:repo) do
246
+ r = make_gitrepo('two', :author => {:name => 'Bob', :email => 'bob@example.com'})
247
+ r.tag('source1')
248
+ r
249
+ end
250
+
251
+ it "should have tags" do
252
+ repo.tags.count.must_equal 1
253
+ repo.tags.first.name.must_equal "refs/tags/source1"
254
+ end
255
+
256
+ it "should have no branches" do
257
+ repo.branches.must_be_empty
258
+ end
259
+
260
+ it "should retrieve same image for default and by tag" do
261
+ assert hashalike(repo.to_hash(:tag => 'source1'), load_json('two'))
262
+ end
263
+
264
+ it "should point the tag at the commit" do
265
+ repo.tags.first.target.must_equal repo.head.target
266
+ repo.version.must_equal repo.version(:tag => 'source1')
267
+ end
268
+ end
269
+
270
+ describe "a multiply-patched gitrepo" do
271
+ def self.makerepo
272
+ @cache ||= begin
273
+ r = make_gitrepo('two', :author => {:name => 'Bob', :email => 'bob@example.com'})
274
+ r.tag('app1')
275
+ r.tag('app2')
276
+ image1 = r.to_hash
277
+ r.patch([
278
+ [
279
+ "+",
280
+ "org.name",
281
+ "BigCorp"
282
+ ]
283
+ ])
284
+ r.tag('app2')
285
+ image2 = r.to_hash
286
+ r.patch([
287
+ [
288
+ "-",
289
+ "org.name",
290
+ "BigCorp"
291
+ ]
292
+ ])
293
+ r.tag('app3')
294
+ image3 = r.to_hash
295
+ r.patch([
296
+ [
297
+ "-",
298
+ "emails[]",
299
+ { "label" => "home", "email" => "johns@lectroid.com" }
300
+ ]
301
+ ])
302
+ r.tag('app4')
303
+ image4 = r.to_hash
304
+
305
+ {
306
+ :repo => r,
307
+ :image1 => image1,
308
+ :image2 => image2,
309
+ :image3 => image3,
310
+ :image4 => image4
311
+ }
312
+ end
313
+ end
314
+
315
+ let(:repo) { self.class.makerepo }
316
+
317
+ it "should remember all the tags" do
318
+ repo[:repo].tags.count.must_equal 4
319
+ end
320
+
321
+ it "should fetch different images by tag" do
322
+ assert hashalike(repo[:repo].to_hash(:tag => 'app1'), repo[:image1])
323
+ assert hashalike(repo[:repo].to_hash(:tag => 'app2'), repo[:image2])
324
+ assert hashalike(repo[:repo].to_hash(:tag => 'app3'), repo[:image3])
325
+ assert hashalike(repo[:repo].to_hash(:tag => 'app4'), repo[:image4])
326
+ assert hashalike(repo[:repo].to_hash, repo[:image4])
327
+ end
328
+
329
+ it "should have different version labels for each tag" do
330
+ versions = ['app1', 'app2', 'app3', 'app4'].map {|s| repo[:repo].version(:tag => s)}
331
+ versions.uniq.count.must_equal 4
332
+ end
333
+ end
334
+
335
+ describe "a branched gitrepo" do
336
+ let(:repo) do
337
+ r = make_gitrepo('one', :author => {:name => 'Bob', :email => 'bob@example.com'})
338
+ r.branch('mybranch')
339
+ r
340
+ end
341
+
342
+ it "should show a branch" do
343
+ repo.branches.must_equal ['refs/heads/mybranch']
344
+ end
345
+ end
346
+ end
@@ -0,0 +1,25 @@
1
+ require 'minitest/spec'
2
+
3
+ require File.expand_path('../../lib/treet', __FILE__)
4
+
5
+ require "tmpdir"
6
+ require "fileutils"
7
+
8
+ $topdir ||= Dir.mktmpdir("treet-tests-")
9
+
10
+ def jsonfile(filename)
11
+ "#{File.dirname(__FILE__)}/json/#{filename}.json"
12
+ end
13
+
14
+ def load_json(filename)
15
+ JSON.load(File.open(jsonfile(filename)))
16
+ end
17
+
18
+ MiniTest::Unit.after_tests do
19
+ $stderr.puts "Erasing #{$topdir}"
20
+ FileUtils.rm_rf $topdir
21
+ $topdir = nil
22
+ end
23
+
24
+ # MUST PUT THIS AT *END* OF FILE OR CLEANUP WILL HAPPEN BEFORE TESTS ARE RUN!
25
+ require 'minitest/autorun'
data/treet.gemspec CHANGED
@@ -15,10 +15,12 @@ Gem::Specification.new do |gem|
15
15
  gem.require_paths = ["lib"]
16
16
  gem.version = Treet::VERSION
17
17
 
18
- gem.add_dependency 'uuidtools'
18
+ gem.add_dependency 'thor'
19
+ gem.add_dependency 'rugged', "~> 0.17.0.b6"
19
20
 
20
- gem.add_development_dependency "rake", "~> 0.9.2"
21
- gem.add_development_dependency "rspec", "~> 2.9.0"
22
- gem.add_development_dependency "guard-rspec", "~> 0.7.0"
23
- gem.add_development_dependency "ruby_gntp", "~> 0.3.4"
21
+ gem.add_development_dependency "rake"
22
+ gem.add_development_dependency "rspec"
23
+ gem.add_development_dependency "guard-rspec"
24
+ gem.add_development_dependency "guard-minitest"
25
+ gem.add_development_dependency "ruby_gntp"
24
26
  end