treet 0.8.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": {
3
+ "first": "Bob",
4
+ "last": "Smith",
5
+ "full": "Robert Smith"
6
+ },
7
+ "emails": [
8
+ {
9
+ "label": "home",
10
+ "email": "bob@newhome.com"
11
+ },
12
+ {
13
+ "label": "work",
14
+ "email": "bob@work.com"
15
+ }
16
+ ],
17
+ "business": {
18
+ "organization": "Acme Inc."
19
+ }
20
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ "name": "My Group",
3
+ "contacts": [
4
+ "1301BC3D-6630-4C05-A345-DDA5047113FD",
5
+ "3DBD340E-9E57-487D-9055-AAD9C0716473",
6
+ "736BA4A8-71DA-434F-814D-FD111D225492",
7
+ "9FD0E465-4514-42B8-8547-8F51F47444C2",
8
+ "DC0151AA-09E4-4D8F-9F93-9E94CC36F2DF",
9
+ "EBADFC69-2254-442E-8EA6-672310454211",
10
+ "F8F5E33D-E911-4828-B593-30BF8F0D1501"
11
+ ],
12
+ "xref": {
13
+ "ab": "F98729F6-AB64-4F99-A833-589562068118"
14
+ }
15
+ }
@@ -0,0 +1,55 @@
1
+ [
2
+ {
3
+ "name": {
4
+ "first": "John",
5
+ "last": "Yaya",
6
+ "full": "John Yaya"
7
+ },
8
+ "emails": [
9
+ {
10
+ "label": "work",
11
+ "email": "johny@yoyodyne.com"
12
+ }
13
+ ]
14
+ },
15
+ {
16
+ "name": {
17
+ "first": "John",
18
+ "last": "Smallberries",
19
+ "full": "John Smallberries"
20
+ },
21
+ "emails": [
22
+ {
23
+ "label": "work",
24
+ "email": "johns@yoyodyne.com"
25
+ },
26
+ {
27
+ "label": "home",
28
+ "email": "johns@lectroid.com"
29
+ }
30
+ ],
31
+ "addresses": [
32
+ {
33
+ "label": "home",
34
+ "planet": "Ten"
35
+ }
36
+ ]
37
+ },
38
+ {
39
+ "name": {
40
+ "first": "John",
41
+ "last": "Bigbooté",
42
+ "full": "John Bigbooté"
43
+ },
44
+ "emails": [
45
+ {
46
+ "label": "work",
47
+ "email": "johnb@yoyodyne.com"
48
+ },
49
+ {
50
+ "label": "home",
51
+ "email": "johnbig@lectroid.com"
52
+ }
53
+ ]
54
+ }
55
+ ]
@@ -0,0 +1,5 @@
1
+ {
2
+ "name": {
3
+ "full": "John Bigbooté"
4
+ }
5
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": {
3
+ "first": "John",
4
+ "last": "Smallberries",
5
+ "full": "John Smallberries"
6
+ },
7
+ "emails": [
8
+ {
9
+ "label": "work",
10
+ "email": "johns@yoyodyne.com"
11
+ },
12
+ {
13
+ "label": "home",
14
+ "email": "johns@lectroid.com"
15
+ }
16
+ ]
17
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": {
3
+ "first": "John",
4
+ "last": "Smallberries",
5
+ "full": "John Smallberries"
6
+ },
7
+ "emails": [
8
+ {
9
+ "label": "home",
10
+ "email": "johns@lectroid.com"
11
+ },
12
+ {
13
+ "label": "work",
14
+ "email": "johns@yoyodyne.com"
15
+ }
16
+ ]
17
+ }
@@ -0,0 +1,65 @@
1
+ # encoding: UTF-8
2
+ require "spec_helper"
3
+
4
+ describe "Repository Farm" do
5
+ it "should export as array of hashes with an xref value" do
6
+ farm = Treet::Farm.new(:root => "#{File.dirname(__FILE__)}/../repos/farm1", :xref => 'test')
7
+ farm.export.should == [
8
+ {
9
+ 'name' => {
10
+ 'full' => 'John Bigbooté'
11
+ },
12
+ 'xref' => {
13
+ 'test' => 'one'
14
+ }
15
+ },
16
+ {
17
+ 'xref' => {
18
+ 'test' => 'two'
19
+ },
20
+ 'name' => {
21
+ 'full' => 'John Smallberries',
22
+ 'first' => 'John',
23
+ 'last' => 'Smallberries'
24
+ },
25
+ 'emails' => [
26
+ {
27
+ "label" => "home",
28
+ "email" => "johns@lectroid.com"
29
+ },
30
+ {
31
+ "label" => "work",
32
+ "email" => "johns@yoyodyne.com"
33
+ }
34
+ ]
35
+ }
36
+ ]
37
+ end
38
+
39
+ it "planting should create a directory of UUID-labeled repos" do
40
+ farm = Treet::Farm.plant(:json => "#{File.dirname(__FILE__)}/../json/master.json", :root => Dir.mktmpdir)
41
+
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
45
+
46
+ FileUtils.rm_rf(farm.root)
47
+ end
48
+
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
54
+
55
+ it "should take additions" do
56
+ farm = Treet::Farm.plant(:json => "#{File.dirname(__FILE__)}/../json/master.json", :root => Dir.mktmpdir)
57
+
58
+ bob_hash = load_json("bob1")
59
+ repo = farm.add(bob_hash)
60
+ repo.root.should =~ /#{farm.root}/
61
+ Dir.glob("#{farm.root}/*").count.should == 4
62
+
63
+ FileUtils.rm_rf(farm.root)
64
+ end
65
+ end
@@ -0,0 +1,132 @@
1
+ # encoding: UTF-8
2
+ require "spec_helper"
3
+
4
+ describe "Hash" do
5
+ it "should inject JSON" do
6
+ hash = Treet::Hash.new("#{File.dirname(__FILE__)}/../json/one.json")
7
+ hash.data.should == {
8
+ 'name' => {'full' => 'John Bigbooté'}
9
+ }
10
+ end
11
+
12
+ it "should compare hashes to file trees" do
13
+ hash = Treet::Hash.new("#{File.dirname(__FILE__)}/../json/one.json")
14
+ repo = Treet::Repo.new("#{File.dirname(__FILE__)}/../repos/one")
15
+ hash.compare(repo).should == []
16
+ end
17
+
18
+ it "should generate repo from hash" do
19
+ hash = Treet::Hash.new("#{File.dirname(__FILE__)}/../json/one.json")
20
+
21
+ Dir.mktmpdir do |dir|
22
+ hash.to_repo(dir)
23
+ JSON.load(File.open("#{dir}/name")).should == {'full' => 'John Bigbooté'}
24
+ end
25
+ end
26
+
27
+ it "should convert arrays to subdirs named with digests" do
28
+ hash = Treet::Hash.new("#{File.dirname(__FILE__)}/../json/two.json")
29
+
30
+ Dir.mktmpdir do |dir|
31
+ hash.to_repo(dir)
32
+ Dir.glob("#{dir}/emails/*").count.should == 2
33
+ emails = Dir.glob("#{dir}/emails/*").map {|f| JSON.load(File.open(f))['email']}.to_set
34
+ emails.should == ['johns@yoyodyne.com', "johns@lectroid.com"].to_set
35
+ hash.to_hash['emails'].each do |h|
36
+ filename = "#{dir}/emails/#{Treet::Hash.digestify(h)}"
37
+ File.should exist(filename)
38
+ end
39
+ # File.read("#{dir}/emails/work/email").should == 'johns@yoyodyne.com'
40
+ end
41
+ end
42
+
43
+ it "should compare array objects independently of order" do
44
+ hash1 = Treet::Hash.new("#{File.dirname(__FILE__)}/../json/two.json")
45
+ hash2 = Treet::Hash.new("#{File.dirname(__FILE__)}/../json/three.json")
46
+
47
+ hash1.compare(hash1).should == []
48
+ hash1.compare(hash2).should == []
49
+
50
+ hash = Treet::Hash.new("#{File.dirname(__FILE__)}/../json/two.json")
51
+ repo = Treet::Repo.new("#{File.dirname(__FILE__)}/../repos/two")
52
+
53
+ hash.compare(repo).should == []
54
+ end
55
+
56
+ it "should find differences independently of order" do
57
+ hash = Treet::Hash.new("#{File.dirname(__FILE__)}/../json/two.json")
58
+ repo = Treet::Repo.new("#{File.dirname(__FILE__)}/../repos/three")
59
+
60
+ hash.compare(repo).should == [
61
+ ["-", "emails[]", {"label"=>"home", "email"=>"johns@lectroid.com"}],
62
+ ["+", "emails[]", {"label"=>"home", "email"=>"johnsmallberries@lectroid.com"}]
63
+ ]
64
+ # hash.compare(repo).should == [["~", "email.home.email", "johns@lectroid.com", "johnsmallberries@lectroid.com"]]
65
+
66
+ hash = Treet::Hash.new("#{File.dirname(__FILE__)}/../json/two.json")
67
+ repo = Treet::Repo.new("#{File.dirname(__FILE__)}/../repos/four")
68
+
69
+ hash.compare(repo).should == [
70
+ ["-", "emails[]", {"label"=>"home", "email"=>"johns@lectroid.com"}],
71
+ ["+", "emails[]", {"label"=>"home", "email"=>"johnsmallberries@lectroid.com"}]
72
+ ]
73
+ # hash.compare(repo).should == [["~", "email.home.email", "johns@lectroid.com", "johnsmallberries@lectroid.com"]]
74
+ end
75
+
76
+ it "should expand arrays of strings to empty files" do
77
+ hash = Treet::Hash.new("#{File.dirname(__FILE__)}/../json/group.json")
78
+ Dir.mktmpdir do |dir|
79
+ hash.to_repo(dir)
80
+ Dir.glob("#{dir}/contacts/*").count.should == 7
81
+ end
82
+ end
83
+
84
+ it "should allow comparison of string (not hash) members" do
85
+ h1 = Treet::Hash.new({'name' => 'Bob'})
86
+ h2 = Treet::Hash.new({'name' => 'Sally'})
87
+ h1.compare(h2).should == [
88
+ ['~', 'name', 'Sally', 'Bob']
89
+ ]
90
+ end
91
+ end
92
+
93
+ describe "shallow comparison of hashes" do
94
+ it "should be blank for identity" do
95
+ h1 = Treet::Hash.new("#{File.dirname(__FILE__)}/../json/bob1.json")
96
+ h2 = Treet::Hash.new("#{File.dirname(__FILE__)}/../json/bob1.json")
97
+ h1.compare(h2).should == []
98
+ end
99
+
100
+ it "should handle keys missing from one or either source hash" do
101
+ h1 = Treet::Hash.new("#{File.dirname(__FILE__)}/../json/bob1.json")
102
+ h2 = Treet::Hash.new("#{File.dirname(__FILE__)}/../json/bob2.json")
103
+ diffs = h1.compare(h2)
104
+ # diffs.should include(["~", "name.full", "Bob Smith", "Robert Smith"])
105
+ # diffs.should include(["+", "business.organization", "Acme Inc."])
106
+ # diffs.should include(["-", "other.notes", "some commentary"])
107
+ diffs.should == [
108
+ ["~", "name.full", "Robert Smith", "Bob Smith"],
109
+ ["-", "emails[]", {"label"=>"home", "email"=>"bob@home.com"}],
110
+ ["-", "emails[]", {"label"=>"other", "email"=>"bob@vacation.com"}],
111
+ ["+", "emails[]", {"label"=>"home", "email"=>"bob@newhome.com"}],
112
+ ["-", "other.notes", "some commentary"],
113
+ ["+", "business.organization", "Acme Inc."]
114
+ ]
115
+
116
+ h3 = h1.patch(diffs)
117
+ h3.compare(h2).should == []
118
+ end
119
+
120
+ describe "arrays of strings should build lists of filenames" do
121
+ hash = Treet::Hash.new(
122
+ :name => 'Foo Bar',
123
+ :entries => ["abc", "def", "ghi"]
124
+ )
125
+ Dir.mktmpdir do |dir|
126
+ hash.to_repo(dir)
127
+ Dir.glob("#{dir}/entries/*").count.should == 3
128
+ File.exist?("#{dir}/entries/def").should == true
129
+ File.exist?("#{dir}/entries/bogus").should == false
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,91 @@
1
+ # encoding: UTF-8
2
+ require "spec_helper"
3
+
4
+ describe "Repo" do
5
+ it "should convert file trees to hashes" do
6
+ repo = Treet::Repo.new("#{File.dirname(__FILE__)}/../repos/one")
7
+ repo.to_hash.should == {
8
+ 'name' => {'full' => 'John Bigbooté'}
9
+ }
10
+ end
11
+
12
+ it "should generate optional " do
13
+ repo = Treet::Repo.new("#{File.dirname(__FILE__)}/../repos/one")
14
+ repo.to_hash.should == {
15
+ 'name' => {'full' => 'John Bigbooté'}
16
+ }
17
+ end
18
+
19
+ it "should compare file trees to hashes" do
20
+ repo = Treet::Repo.new("#{File.dirname(__FILE__)}/../repos/one")
21
+ repo.compare({'name' => {'full' => 'John Yaya'}}).should == [
22
+ ["~", "name.full", "John Yaya", "John Bigbooté"]
23
+ ]
24
+ end
25
+
26
+ it "should flatten numbered subdirs to arrays" do
27
+ repo = Treet::Repo.new("#{File.dirname(__FILE__)}/../repos/two")
28
+ hash = repo.to_hash
29
+ hash['emails'].to_set.should == [
30
+ {
31
+ "label" => "home",
32
+ "email" => "johns@lectroid.com"
33
+ },
34
+ {
35
+ "label" => "work",
36
+ "email" => "johns@yoyodyne.com"
37
+ }
38
+ ].to_set
39
+ end
40
+
41
+ it "should generate file paths correctly from key paths in patches" do
42
+ Treet::Repo.filefor("name.first").should == [".", "name", "first"]
43
+ Treet::Repo.filefor("emails[]").should == ['emails', "", nil]
44
+ end
45
+
46
+ it "should added xref keys when specified" do
47
+ repo = Treet::Repo.new("#{File.dirname(__FILE__)}/../repos/one", :xrefkey => 'foo', :xref => 'bar')
48
+ repo.to_hash.should == {
49
+ 'name' => {'full' => 'John Bigbooté'},
50
+ 'xref' => {'foo' => 'bar'}
51
+ }
52
+ end
53
+
54
+ it "should take patches that add values to missing elements" do
55
+ hash = Treet::Hash.new("#{File.dirname(__FILE__)}/../json/one.json")
56
+ Dir.mktmpdir do |dir|
57
+ repo = hash.to_repo(dir)
58
+ repo.patch([
59
+ [
60
+ "~",
61
+ "name.full",
62
+ "John von Neumann"
63
+ ],
64
+ [
65
+ "+",
66
+ "foo.bar",
67
+ "new value"
68
+ ]
69
+ ])
70
+ newhash = repo.to_hash
71
+ newhash['name']['full'].should == 'John von Neumann'
72
+ newhash['foo']['bar'].should == 'new value'
73
+ end
74
+ end
75
+
76
+ it "should accept patches that edit inside missing subhashes" do
77
+ hash = Treet::Hash.new("#{File.dirname(__FILE__)}/../json/one.json")
78
+ Dir.mktmpdir do |dir|
79
+ repo = hash.to_repo(dir)
80
+ repo.patch([
81
+ [
82
+ "~",
83
+ "foo.bar",
84
+ "new value"
85
+ ]
86
+ ])
87
+ newhash = repo.to_hash
88
+ newhash['foo']['bar'].should == 'new value'
89
+ end
90
+ end
91
+ end
@@ -0,0 +1 @@
1
+ {"full":"John Bigbooté"}
@@ -0,0 +1,4 @@
1
+ {
2
+ "label": "home",
3
+ "email": "johns@lectroid.com"
4
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "label": "work",
3
+ "email": "johns@yoyodyne.com"
4
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "first": "John",
3
+ "last": "Smallberries",
4
+ "full": "John Smallberries"
5
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "label": "work",
3
+ "email": "johns@yoyodyne.com"
4
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "label": "home",
3
+ "email": "johnsmallberries@lectroid.com"
4
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "first": "John",
3
+ "last": "Smallberries",
4
+ "full": "John Smallberries"
5
+ }
@@ -0,0 +1 @@
1
+ {"full":"John Bigbooté"}
@@ -0,0 +1,4 @@
1
+ {
2
+ "label": "home",
3
+ "email": "johnsmallberries@lectroid.com"
4
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "label": "work",
3
+ "email": "johns@yoyodyne.com"
4
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "first": "John",
3
+ "last": "Smallberries",
4
+ "full": "John Smallberries"
5
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "label": "home",
3
+ "email": "johns@lectroid.com"
4
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "label": "work",
3
+ "email": "johns@yoyodyne.com"
4
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "first": "John",
3
+ "last": "Smallberries",
4
+ "full": "John Smallberries"
5
+ }
@@ -0,0 +1,17 @@
1
+ require 'rspec/autorun'
2
+
3
+ # Requires supporting ruby files with custom matchers and macros, etc,
4
+ # in spec/support/ and its subdirectories.
5
+ # Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
6
+
7
+ require File.expand_path('../../lib/treet', __FILE__)
8
+
9
+ require "tmpdir"
10
+ require "fileutils"
11
+
12
+ RSpec.configure do |config|
13
+ end
14
+
15
+ def load_json(filename)
16
+ JSON.load(File.open("#{File.dirname(__FILE__)}/json/#{filename}.json"))
17
+ end
data/treet.gemspec ADDED
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/treet/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Jason May"]
6
+ gem.email = ["jmay@pobox.com"]
7
+ gem.description = %q{Transform between trees of files and JSON blobs}
8
+ gem.summary = %q{Transform between trees of files and JSON blobs}
9
+ gem.homepage = ""
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "treet"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = Treet::VERSION
17
+
18
+ gem.add_dependency 'uuidtools'
19
+
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"
24
+ end