nsync 0.0.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,261 @@
1
+ require File.join(File.dirname(__FILE__), "helper")
2
+
3
+ class NsyncProducerTest < Test::Unit::TestCase
4
+ def setup
5
+ #Grit.debug = true
6
+ Nsync.reset_config
7
+ @lock_file = "/private/tmp/nsync_test_#{Process.pid}.lock"
8
+ FileUtils.rm @lock_file, :force => true
9
+ Nsync.config.lock_file = @lock_file
10
+ end
11
+
12
+ context "Initializing Producer" do
13
+ context "when the repo already exists" do
14
+ setup do
15
+ @repo = TestRepo.new
16
+
17
+ Nsync.config.repo_path = @repo.repo_path
18
+ end
19
+
20
+ should "not try to reinitialize it" do
21
+ Grit::Git.any_instance.expects(:init).never
22
+ @producer = Nsync::Producer.new
23
+ end
24
+ end
25
+
26
+ context "when the repo does not exist" do
27
+ setup do
28
+ @repo_path = TestRepo.repo_path
29
+ Nsync.config.repo_path = @repo_path
30
+ FileUtils.rm_rf @repo_path
31
+ end
32
+
33
+ should "initialize it and make a base commit" do
34
+ Grit::Repo.expects(:init).with(@repo_path).once
35
+ Nsync::Producer.any_instance.expects(:write_file).with(".gitignore", "").once
36
+ Nsync::Producer.any_instance.expects(:commit).returns(true).once
37
+ Nsync::Producer.new
38
+ end
39
+
40
+ should "initialize the repo into a working state" do
41
+ @producer = Nsync::Producer.new
42
+ assert_equal "Initial Commit", @producer.repo.head.commit.message
43
+ assert File.exists?(File.join(@repo_path, ".gitignore"))
44
+ end
45
+ end
46
+ end
47
+
48
+ context "Consumer methods that are probably not what you want" do
49
+ setup do
50
+ @repo = TestRepo.new
51
+
52
+ Nsync.config.repo_path = @repo.repo_path
53
+ @producer = Nsync::Producer.new
54
+ end
55
+
56
+ should "be protected" do
57
+ assert_equal [], @producer.public_methods & ["update", "apply_changes"]
58
+ end
59
+ end
60
+
61
+
62
+ context "Writing a file" do
63
+ setup do
64
+ @repo = TestRepo.new
65
+
66
+ Nsync.config.repo_path = @repo.repo_path
67
+ @producer = Nsync::Producer.new
68
+ end
69
+
70
+ context "when creating a file" do
71
+ setup do
72
+ @file = "foo/1.json"
73
+ @hash = {"id" => 1, "val" => "Shazam"}
74
+ end
75
+
76
+ should "write the file to disk, add it to the index, but not commit" do
77
+ @producer.repo.expects(:add).with(File.join(@repo.repo_path, @file)).once
78
+ @producer.expects(:commit).never
79
+ @producer.repo.expects(:commit_all).never
80
+ @producer.write_file(@file, @hash)
81
+
82
+ assert_equal JSON.load(File.read(File.join(@repo.repo_path, @file))), @hash
83
+ end
84
+ end
85
+
86
+ context "when modifying a file" do
87
+ setup do
88
+ @file = "foo/1.json"
89
+ @hash = {"id" => 1, "val" => "Shazam"}
90
+ @producer.write_file(@file, @hash)
91
+ end
92
+
93
+ should "behave just like a create" do
94
+ new_hash = {"id" => 1, "val" => "Kaboom"}
95
+ @producer.repo.expects(:add).with(File.join(@repo.repo_path, @file)).once
96
+ @producer.expects(:commit).never
97
+ @producer.write_file(@file, new_hash)
98
+
99
+ assert_equal JSON.load(File.read(File.join(@repo.repo_path, @file))), new_hash
100
+ end
101
+
102
+ context "but then removing it" do
103
+ setup do
104
+ @producer.remove_file(@file)
105
+ end
106
+
107
+ should "just be gone" do
108
+ assert !File.exists?(File.join(@repo.repo_path, @file))
109
+ end
110
+ end
111
+ end
112
+ end
113
+
114
+ context "Committing changes" do
115
+ setup do
116
+ @repo = TestRepo.new
117
+
118
+ Nsync.config.repo_path = @repo.repo_path
119
+ @producer = Nsync::Producer.new
120
+ end
121
+
122
+ should "commit all changes as well as push" do
123
+ @msg = "Test Update"
124
+ @producer.repo.expects(:commit_all).with(@msg).once
125
+ @producer.expects(:push).once
126
+ @producer.commit(@msg)
127
+ end
128
+ end
129
+
130
+ context "Pushing changes" do
131
+ setup do
132
+ @repo = TestRepo.new
133
+
134
+ Nsync.config.repo_path = @repo.repo_path
135
+ @producer = Nsync::Producer.new
136
+ end
137
+
138
+ context "when there is a remote push url" do
139
+ setup do
140
+ @push_url = "/tmp/foo/bar"
141
+ Nsync.config.repo_push_url = @push_url
142
+ end
143
+
144
+ should "push changes to that" do
145
+ @producer.repo.git.expects(:push).with({}, @push_url, "+master").once
146
+ @producer.push
147
+ end
148
+ end
149
+
150
+ context "when there is no remote push url" do
151
+ should "not try to push" do
152
+ @producer.repo.git.expects(:push).never
153
+ @producer.push
154
+ end
155
+ end
156
+ end
157
+
158
+ context "Because a producer is a consumer that consumes itself" do
159
+ setup do
160
+ @repo = TestRepo.new
161
+
162
+ Nsync.config.repo_path = @repo.repo_path
163
+ @producer = Nsync::Producer.new
164
+ end
165
+
166
+ context "the class mapping" do
167
+ setup do
168
+ Nsync.config.map_class "NsyncTestBar", "NsyncTestFoo"
169
+ end
170
+
171
+ context "when unset for a class" do
172
+ should "return the producer class" do
173
+ assert_equal [NsyncTestFoo],
174
+ @producer.send(:consumer_classes_and_id_from_path, "nsync_test_foo/1.json")[0]
175
+ end
176
+ end
177
+
178
+ context "when set for a class" do
179
+ should "return a consumer class normally" do
180
+ assert_equal [NsyncTestFoo],
181
+ @producer.send(:consumer_classes_and_id_from_path, "nsync_test_bar/1.json")[0]
182
+ end
183
+ end
184
+ end
185
+
186
+ context "rollback behaves quite differently" do
187
+ setup do
188
+ Nsync.config.version_manager = stub(:version => "bad_rev",
189
+ :previous_version => "good_rev")
190
+ end
191
+
192
+ should "reset from bad to good, apply changes between bad and good, and push" do
193
+ @producer.repo.git.expects(:reset).never
194
+ @producer.repo.git.expects(:reset).with({:hard => true}, "good_rev").once
195
+ @producer.expects(:apply_changes).with("bad_rev", "good_rev").once
196
+ @producer.expects(:push).once
197
+ @producer.rollback
198
+ end
199
+ end
200
+ end
201
+
202
+ context "basic flow" do
203
+ setup do
204
+ @repo_path = TestRepo.repo_path
205
+ @repo_push_url = TestRepo.bare_consumer_repo_path
206
+ FileUtils.rm_rf @repo_path
207
+ FileUtils.rm_rf @repo_push_url
208
+
209
+ @remote_repo = Grit::Repo.init_bare(@repo_push_url)
210
+ Nsync.config.repo_path = @repo_path
211
+ Nsync.config.repo_push_url = @repo_push_url
212
+ Nsync.config.version_manager = Nsync::GitVersionManager.new
213
+
214
+ @producer = Nsync::Producer.new
215
+ @repo = @producer.repo
216
+ end
217
+
218
+ should "work" do
219
+ @producer.write_file("nsync_test_foo/1.json", {:id => 1, :val => "Party"})
220
+ @producer.write_file("nsync_test_bar/2.json", {:id => 2, :val => "Study"})
221
+ assert_equal 1, @repo.commits.size
222
+ assert_equal 1, @remote_repo.commits.size
223
+ assert File.exists?(File.join(@repo_path, "nsync_test_foo/1.json"))
224
+ assert File.exists?(File.join(@repo_path, "nsync_test_bar/2.json"))
225
+ @producer.commit("Added some files")
226
+
227
+ assert_equal 2, @repo.commits.size
228
+ assert_equal 2, @remote_repo.commits.size
229
+
230
+ @producer.write_file("nsync_test_foo/2.json", {:id => 2, :val => "Rock"})
231
+ assert File.exists?(File.join(@repo_path, "nsync_test_foo/2.json"))
232
+ @producer.commit("And another")
233
+
234
+ assert_equal 3, @repo.commits.size
235
+ assert_equal 3, @remote_repo.commits.size
236
+
237
+ @producer.remove_file("nsync_test_bar/2.json")
238
+ assert !File.exists?(File.join(@repo_path, "nsync_test_bar/2.json"))
239
+ @producer.commit("Remove the no-fun brigade")
240
+
241
+ assert_equal 4, @repo.commits.size
242
+ assert_equal 4, @remote_repo.commits.size
243
+
244
+ NsyncTestBar.expects(:nsync_find).with('2').returns([]).once
245
+ NsyncTestBar.expects(:nsync_add_data).once
246
+
247
+ @producer.rollback
248
+
249
+ assert File.exists?(File.join(@repo_path, "nsync_test_bar/2.json"))
250
+ assert_equal 3, @repo.commits.size
251
+ assert_equal 3, @remote_repo.commits.size
252
+
253
+ @producer.write_file("nsync_test_bar/5.json", {:id => 5, :val => "No Fun"})
254
+ assert File.exists?(File.join(@repo_path, "nsync_test_bar/5.json"))
255
+ @producer.commit("Life goes on")
256
+
257
+ assert_equal 4, @repo.commits.size
258
+ assert_equal 4, @remote_repo.commits.size
259
+ end
260
+ end
261
+ end
data/test/repo.rb ADDED
@@ -0,0 +1,64 @@
1
+ class TestRepo
2
+ attr_accessor :repo
3
+
4
+ def initialize(opts={})
5
+ FileUtils.rm_rf(repo_path)
6
+ self.repo = Grit::Repo.init(repo_path)
7
+ add_file(".gitignore", "")
8
+ commit("Initial Commit")
9
+ end
10
+
11
+ def cd
12
+ old_pwd = FileUtils.pwd
13
+ begin
14
+ FileUtils.cd repo_path
15
+ yield
16
+ ensure
17
+ FileUtils.cd old_pwd
18
+ end
19
+ end
20
+
21
+ def repo_path
22
+ self.class.repo_path
23
+ end
24
+
25
+ def self.repo_path
26
+ "/private/tmp/nsync_test_repo_#{Process.pid}"
27
+ end
28
+
29
+ def bare_consumer_repo_path
30
+ self.class.bare_consumer_repo_path
31
+ end
32
+
33
+ def self.bare_consumer_repo_path
34
+ "#{repo_path}_consumer.git"
35
+ end
36
+
37
+ def self.repo_push_path
38
+ "#{repo_path}_producer_push.git"
39
+ end
40
+
41
+ def add_file(filename, content)
42
+ cd do
43
+ dir = File.dirname(filename)
44
+ if ![".", "/"].include?(dir) && !File.exists?(dir)
45
+ FileUtils.mkdir_p(File.join(repo_path, dir))
46
+ end
47
+ File.open(File.join(repo_path, filename), "w") do |f|
48
+ f.write((content.is_a?(Hash))? content.to_json : content)
49
+ end
50
+ repo.add(File.join(repo_path, filename))
51
+ end
52
+ end
53
+
54
+ def remove_file(filename)
55
+ FileUtils.rm File.join(repo_path, filename)
56
+ end
57
+
58
+ def commit(message)
59
+ cd do
60
+ repo.commit_all(message)
61
+ end
62
+ end
63
+
64
+ end
metadata ADDED
@@ -0,0 +1,165 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: nsync
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 2
9
+ version: 0.0.2
10
+ platform: ruby
11
+ authors:
12
+ - Ben Hughes
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-12-06 00:00:00 -05:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: json
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 0
29
+ version: "0"
30
+ type: :runtime
31
+ version_requirements: *id001
32
+ - !ruby/object:Gem::Dependency
33
+ name: activesupport
34
+ prerelease: false
35
+ requirement: &id002 !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ~>
38
+ - !ruby/object:Gem::Version
39
+ segments:
40
+ - 2
41
+ - 3
42
+ - 5
43
+ version: 2.3.5
44
+ type: :runtime
45
+ version_requirements: *id002
46
+ - !ruby/object:Gem::Dependency
47
+ name: schleyfox-grit
48
+ prerelease: false
49
+ requirement: &id003 !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ segments:
54
+ - 2
55
+ - 3
56
+ - 0
57
+ - 1
58
+ version: 2.3.0.1
59
+ type: :runtime
60
+ version_requirements: *id003
61
+ - !ruby/object:Gem::Dependency
62
+ name: schleyfox-lockfile
63
+ prerelease: false
64
+ requirement: &id004 !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ segments:
69
+ - 1
70
+ - 0
71
+ - 0
72
+ version: 1.0.0
73
+ type: :runtime
74
+ version_requirements: *id004
75
+ - !ruby/object:Gem::Dependency
76
+ name: shoulda
77
+ prerelease: false
78
+ requirement: &id005 !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ segments:
83
+ - 0
84
+ version: "0"
85
+ type: :development
86
+ version_requirements: *id005
87
+ - !ruby/object:Gem::Dependency
88
+ name: mocha
89
+ prerelease: false
90
+ requirement: &id006 !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ segments:
95
+ - 0
96
+ version: "0"
97
+ type: :development
98
+ version_requirements: *id006
99
+ description: |-
100
+ Nsync is designed to allow you to have a separate data
101
+ processing app with its own data processing optimized database and a consumer
102
+ app with its own database, while keeping the data as in sync as you want it.
103
+ email: ben@pixelmachine.org
104
+ executables: []
105
+
106
+ extensions: []
107
+
108
+ extra_rdoc_files:
109
+ - LICENSE
110
+ - README.md
111
+ files:
112
+ - LICENSE
113
+ - README.md
114
+ - Rakefile
115
+ - VERSION
116
+ - jeweler_monkey_patch.rb
117
+ - lib/nsync.rb
118
+ - lib/nsync/active_record/consumer/methods.rb
119
+ - lib/nsync/active_record/methods.rb
120
+ - lib/nsync/active_record/producer/methods.rb
121
+ - lib/nsync/class_methods.rb
122
+ - lib/nsync/config.rb
123
+ - lib/nsync/consumer.rb
124
+ - lib/nsync/git_version_manager.rb
125
+ - lib/nsync/producer.rb
126
+ - lib/nsync/producer/methods.rb
127
+ - nsync.gemspec
128
+ has_rdoc: true
129
+ homepage: http://github.com/schleyfox/nsync
130
+ licenses: []
131
+
132
+ post_install_message:
133
+ rdoc_options: []
134
+
135
+ require_paths:
136
+ - lib
137
+ required_ruby_version: !ruby/object:Gem::Requirement
138
+ requirements:
139
+ - - ">="
140
+ - !ruby/object:Gem::Version
141
+ segments:
142
+ - 0
143
+ version: "0"
144
+ required_rubygems_version: !ruby/object:Gem::Requirement
145
+ requirements:
146
+ - - ">="
147
+ - !ruby/object:Gem::Version
148
+ segments:
149
+ - 0
150
+ version: "0"
151
+ requirements: []
152
+
153
+ rubyforge_project:
154
+ rubygems_version: 1.3.6
155
+ signing_key:
156
+ specification_version: 3
157
+ summary: Keep your data processors and apps in sync
158
+ test_files:
159
+ - test/active_record_test.rb
160
+ - test/classes.rb
161
+ - test/helper.rb
162
+ - test/nsync_config_test.rb
163
+ - test/nsync_consumer_test.rb
164
+ - test/nsync_producer_test.rb
165
+ - test/repo.rb