treet 0.8.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.
@@ -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