rscm 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. data/README +198 -0
  2. data/Rakefile +118 -0
  3. data/ext/rscm.jar +0 -0
  4. data/lib/rscm.rb +10 -0
  5. data/lib/rscm/abstract_log_parser.rb +49 -0
  6. data/lib/rscm/abstract_scm.rb +229 -0
  7. data/lib/rscm/changes.rb +271 -0
  8. data/lib/rscm/cvs/cvs.rb +363 -0
  9. data/lib/rscm/cvs/cvs_log_parser.rb +161 -0
  10. data/lib/rscm/darcs/darcs.rb +69 -0
  11. data/lib/rscm/line_editor.rb +46 -0
  12. data/lib/rscm/logging.rb +5 -0
  13. data/lib/rscm/monotone/monotone.rb +107 -0
  14. data/lib/rscm/mooky/mooky.rb +13 -0
  15. data/lib/rscm/parser.rb +39 -0
  16. data/lib/rscm/path_converter.rb +92 -0
  17. data/lib/rscm/perforce/perforce.rb +415 -0
  18. data/lib/rscm/starteam/starteam.rb +99 -0
  19. data/lib/rscm/svn/svn.rb +337 -0
  20. data/lib/rscm/svn/svn_log_parser.rb +134 -0
  21. data/lib/rscm/time_ext.rb +125 -0
  22. data/test/rscm/apply_label_scm_tests.rb +26 -0
  23. data/test/rscm/changes_fixture.rb +20 -0
  24. data/test/rscm/changes_test.rb +129 -0
  25. data/test/rscm/cvs/cvs_log_parser_test.rb +575 -0
  26. data/test/rscm/cvs/cvs_test.rb +22 -0
  27. data/test/rscm/darcs/darcs_test.rb +14 -0
  28. data/test/rscm/difftool_test.rb +40 -0
  29. data/test/rscm/file_ext.rb +12 -0
  30. data/test/rscm/generic_scm_tests.rb +282 -0
  31. data/test/rscm/line_editor_test.rb +76 -0
  32. data/test/rscm/mockit.rb +130 -0
  33. data/test/rscm/mockit_test.rb +117 -0
  34. data/test/rscm/monotone/monotone_test.rb +19 -0
  35. data/test/rscm/mooky/mooky_test.rb +14 -0
  36. data/test/rscm/parser_test.rb +47 -0
  37. data/test/rscm/path_converter_test.rb +52 -0
  38. data/test/rscm/perforce/perforce_test.rb +14 -0
  39. data/test/rscm/starteam/starteam_test.rb +36 -0
  40. data/test/rscm/svn/svn_log_parser_test.rb +111 -0
  41. data/test/rscm/svn/svn_test.rb +28 -0
  42. data/test/rscm/tempdir.rb +12 -0
  43. metadata +81 -0
@@ -0,0 +1,22 @@
1
+ require 'test/unit'
2
+ require 'rscm/cvs/cvs'
3
+ require 'rscm/generic_scm_tests'
4
+
5
+ module RSCM
6
+ class CVSTest < Test::Unit::TestCase
7
+
8
+ include GenericSCMTests
9
+ include ApplyLabelTest
10
+
11
+ def create_scm(repository_root_dir, path)
12
+ CVS.local(repository_root_dir, path)
13
+ end
14
+
15
+ def test_should_fail_on_bad_command
16
+ assert_raise(RuntimeError) do
17
+ CVS.new("").create
18
+ end
19
+ end
20
+
21
+ end
22
+ end
@@ -0,0 +1,14 @@
1
+ require 'test/unit'
2
+ require 'fileutils'
3
+ require 'rscm/generic_scm_tests'
4
+ require 'rscm/darcs/darcs'
5
+
6
+ module RSCM
7
+ class DarcsTest < Test::Unit::TestCase
8
+ include GenericSCMTests
9
+
10
+ def create_scm(repository_root_dir, path)
11
+ Darcs.new(repository_root_dir)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,40 @@
1
+ require 'test/unit'
2
+ require 'rscm/tempdir'
3
+ require 'rscm/path_converter'
4
+
5
+ module Test
6
+ module Unit
7
+ class TestCase
8
+ # assertion method that reports differences as diff.
9
+ # useful when comparing big strings
10
+ def assert_equal_with_diff(expected, actual)
11
+ dir = RSCM.new_temp_dir("diff")
12
+
13
+ expected_file = "#{dir}/expected"
14
+ actual_file = "#{dir}/actual"
15
+ File.open(expected_file, "w") {|io| io.write(expected)}
16
+ File.open(actual_file, "w") {|io| io.write(actual)}
17
+
18
+ difftool = WINDOWS ? File.dirname(__FILE__) + "/../../bin/diff.exe" : "diff"
19
+ IO.popen("#{difftool} #{RSCM::PathConverter.filepath_to_nativepath(expected_file, false)} #{RSCM::PathConverter.filepath_to_nativepath(actual_file, false)}") do |io|
20
+ diff = io.read
21
+ assert_equal("", diff, diff)
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ module RSCM
29
+ class DiffPersisterTest < Test::Unit::TestCase
30
+ def test_diffing_fails_with_diff_when_different
31
+ assert_raises(Test::Unit::AssertionFailedError) {
32
+ assert_equal_with_diff("This is a\nmessage with\nsome text", "This is a\nmessage without\nsome text")
33
+ }
34
+ end
35
+
36
+ def test_diffing_passes_with_diff_when_equal
37
+ assert_equal_with_diff("This is a\nmessage with\nsome text", "This is a\nmessage with\nsome text")
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,12 @@
1
+ class File
2
+ def read_fix_nl
3
+ result = ""
4
+ self.each_line do |line|
5
+ chomped = line.chomp
6
+ result << chomped
7
+ result << "\n" if chomped != line
8
+ end
9
+ result
10
+ end
11
+ end
12
+
@@ -0,0 +1,282 @@
1
+ require 'fileutils'
2
+ require 'rscm/tempdir'
3
+ require 'rscm/path_converter'
4
+
5
+ module RSCM
6
+
7
+ module GenericSCMTests
8
+ include FileUtils
9
+
10
+ # Acceptance test for scm implementations
11
+ #
12
+ # 1) Create a repo
13
+ # 2) Import a test project
14
+ # 3) Verify that CheckoutHere is not uptodate
15
+ # 4) Check out to CheckoutHere
16
+ # 5) Verify that the checked out files were those imported
17
+ # 6) Verify that the initial total changesets (from epoch to infinity) represents those from the import
18
+ # 7) Verify that CheckoutHere is uptodate
19
+ # 8) Change some files in DeveloperOne's working copy
20
+ # 9) Check out to CheckoutHereToo
21
+ # 10) Verify that CheckoutHereToo is uptodate
22
+ # 11) Verify that CheckoutHere is uptodate
23
+ # 12) Commit modifications in CheckoutHere is uptodate
24
+ # 13) Verify that CheckoutHere is uptodate
25
+ # 14) Verify that CheckoutHereToo is not uptodate
26
+ # 15) Check out to CheckoutHereToo
27
+ # 16) Verify that CheckoutHereToo is uptodate
28
+ # 17) Add and commit a file in CheckoutHere
29
+ # 18) Verify that the changeset (since last changeset) for CheckoutHereToo contains only one file
30
+ def test_basics
31
+ work_dir = RSCM.new_temp_dir("basics")
32
+ checkout_dir = "#{work_dir}/CheckoutHere"
33
+ other_checkout_dir = "#{work_dir}/CheckoutHereToo"
34
+ repository_dir = "#{work_dir}/repository"
35
+ scm = create_scm(repository_dir, "damagecontrolled")
36
+ scm.create
37
+ assert(scm.name)
38
+
39
+ import_damagecontrolled(scm, "#{work_dir}/damagecontrolled")
40
+
41
+ # test twice - to verify that uptodate? doesn't check out.
42
+ assert(!scm.uptodate?(checkout_dir, Time.new.utc))
43
+ assert(!scm.uptodate?(checkout_dir, Time.new.utc))
44
+ yielded_files = []
45
+ files = scm.checkout(checkout_dir) do |file_name|
46
+ yielded_files << file_name
47
+ end
48
+
49
+ assert_equal(4, files.length)
50
+ assert_equal(files, yielded_files)
51
+ files.sort!
52
+ yielded_files.sort!
53
+ assert_equal(files, yielded_files)
54
+
55
+ assert_equal("build.xml", files[0])
56
+ assert_equal("project.xml", files[1])
57
+ assert_equal("src/java/com/thoughtworks/damagecontrolled/Thingy.java", files[2])
58
+ assert_equal("src/test/com/thoughtworks/damagecontrolled/ThingyTestCase.java", files[3])
59
+
60
+ initial_changesets = scm.changesets(checkout_dir, nil, nil, files)
61
+ assert_equal(1, initial_changesets.length)
62
+ initial_changeset = initial_changesets[0]
63
+ assert_equal("imported\nsources", initial_changeset.message)
64
+ assert_equal(4, initial_changeset.length)
65
+ assert(scm.uptodate?(checkout_dir, initial_changesets.latest.time + 1))
66
+
67
+ # modify file and commit it
68
+ change_file(scm, "#{checkout_dir}/build.xml")
69
+ change_file(scm, "#{checkout_dir}/src/java/com/thoughtworks/damagecontrolled/Thingy.java")
70
+
71
+ scm.checkout(other_checkout_dir)
72
+ assert(scm.uptodate?(other_checkout_dir, Time.new.utc))
73
+ assert(scm.uptodate?(checkout_dir, Time.new.utc))
74
+
75
+ scm.commit(checkout_dir, "changed\nsomething")
76
+
77
+ # check that we now have one more change
78
+ changesets = scm.changesets(checkout_dir, initial_changesets.time + 1)
79
+
80
+ assert_equal(1, changesets.length)
81
+ changeset = changesets[0]
82
+ assert_equal(2, changeset.length)
83
+
84
+ assert_equal("changed\nsomething", changeset.message)
85
+
86
+ # why is this nil when running as the dcontrol user on codehaus? --jon
87
+ #assert_equal(username, changeset.developer)
88
+ assert(changeset.developer)
89
+ assert(changeset.identifier)
90
+
91
+ assert_equal("build.xml", changeset[0].path)
92
+ assert(changeset[0].revision)
93
+ assert(changeset[0].previous_revision)
94
+ assert_equal("src/java/com/thoughtworks/damagecontrolled/Thingy.java", changeset[1].path)
95
+ assert(changeset[1].revision)
96
+ assert(changeset[1].previous_revision)
97
+
98
+ assert(!scm.uptodate?(other_checkout_dir, changesets.latest.time+1))
99
+ assert(!scm.uptodate?(other_checkout_dir, changesets.latest.time+1))
100
+ assert(scm.uptodate?(checkout_dir, changesets.latest.time+1))
101
+ assert(scm.uptodate?(checkout_dir, changesets.latest.time+1))
102
+
103
+ files = scm.checkout(other_checkout_dir).sort
104
+ assert_equal(2, files.length)
105
+ assert_equal("build.xml", files[0])
106
+ assert_equal("src/java/com/thoughtworks/damagecontrolled/Thingy.java", files[1])
107
+
108
+ assert(scm.uptodate?(other_checkout_dir, Time.new.utc))
109
+
110
+ add_or_edit_and_commit_file(scm, checkout_dir, "src/java/com/thoughtworks/damagecontrolled/Hello.txt", "Bla bla")
111
+ assert(!scm.uptodate?(other_checkout_dir, Time.new.utc))
112
+ changesets = scm.changesets(other_checkout_dir, changesets.time + 1)
113
+ assert_equal(1, changesets.length)
114
+ assert_equal(1, changesets[0].length)
115
+ assert("src/java/com/thoughtworks/damagecontrolled/Hello.txt", changesets[0][0].path)
116
+ assert("src/java/com/thoughtworks/damagecontrolled/Hello.txt", scm.checkout(other_checkout_dir).sort[0])
117
+ end
118
+
119
+ def test_trigger
120
+ work_dir = RSCM.new_temp_dir("trigger")
121
+ path = "OftenModified"
122
+ checkout_dir = "#{work_dir}/#{path}/checkout"
123
+ repository_dir = "#{work_dir}/repository"
124
+ scm = create_scm(repository_dir, path)
125
+ scm.create
126
+
127
+ trigger_files_checkout_dir = File.expand_path("#{checkout_dir}/../trigger")
128
+ trigger_command = "bla bla"
129
+ (1..3).each do
130
+ assert(!scm.trigger_installed?(trigger_command, trigger_files_checkout_dir))
131
+ scm.install_trigger(trigger_command, trigger_files_checkout_dir)
132
+ assert(scm.trigger_installed?(trigger_command, trigger_files_checkout_dir))
133
+ scm.uninstall_trigger(trigger_command, trigger_files_checkout_dir)
134
+ end
135
+ end
136
+
137
+ def test_checkout_changeset_identifier
138
+ work_dir = RSCM.new_temp_dir("label")
139
+ checkout_dir = "#{work_dir}/checkout"
140
+ repository_dir = "#{work_dir}/repository"
141
+ scm = create_scm(repository_dir, "damagecontrolled")
142
+ scm.create
143
+
144
+ import_damagecontrolled(scm, "#{work_dir}/damagecontrolled")
145
+ scm.checkout(checkout_dir)
146
+ add_or_edit_and_commit_file(scm, checkout_dir, "before.txt", "Before label")
147
+ before_cs = scm.changesets(checkout_dir, Time.epoch)
148
+
149
+ add_or_edit_and_commit_file(scm, checkout_dir, "after.txt", "After label")
150
+ next_identifier = before_cs.latest.identifier + 1
151
+ after_cs = scm.changesets(checkout_dir, next_identifier)
152
+ assert_equal(1, after_cs.length)
153
+ assert_equal("after.txt", after_cs[0][0].path)
154
+
155
+ scm.checkout(checkout_dir, before_cs.latest.identifier)
156
+
157
+ assert(File.exist?("#{checkout_dir}/before.txt"))
158
+ assert(!File.exist?("#{checkout_dir}/after.txt"))
159
+ end
160
+
161
+ def test_should_allow_creation_with_empty_constructor
162
+ scm = create_scm(RSCM.new_temp_dir, ".")
163
+ scm2 = scm.class.new
164
+ assert_same(scm.class, scm2.class)
165
+ end
166
+
167
+ def test_diff
168
+ work_dir = RSCM.new_temp_dir("diff")
169
+ path = "diffing"
170
+ checkout_dir = "#{work_dir}/#{path}/checkout"
171
+ repository_dir = "#{work_dir}/repository"
172
+ import_dir = "#{work_dir}/import/diffing"
173
+ scm = create_scm(repository_dir, path)
174
+ scm.create
175
+
176
+ mkdir_p(import_dir)
177
+ File.open("#{import_dir}/afile.txt", "w") do |io|
178
+ io.puts("one two three")
179
+ io.puts("four five six")
180
+ end
181
+ File.open("#{import_dir}/afile.txt", "w") do |io|
182
+ io.puts("")
183
+ end
184
+
185
+ scm.import(import_dir, "Imported a file to diff against")
186
+ scm.checkout(checkout_dir)
187
+
188
+ scm.edit("#{checkout_dir}/afile.txt")
189
+ File.open("#{checkout_dir}/afile.txt", "w") do |io|
190
+ io.puts("one two three four")
191
+ io.puts("five six")
192
+ end
193
+ File.open("#{checkout_dir}/anotherfile.txt", "w") do |io|
194
+ io.puts("one quick brown")
195
+ io.puts("fox jumped over")
196
+ end
197
+ scm.commit(checkout_dir, "Modified file to diff")
198
+
199
+ scm.edit("#{checkout_dir}/afile.txt")
200
+ File.open("#{checkout_dir}/afile.txt", "w") do |io|
201
+ io.puts("one to threee")
202
+ io.puts("hello")
203
+ io.puts("four five six")
204
+ end
205
+ File.open("#{checkout_dir}/anotherfile.txt", "w") do |io|
206
+ io.puts("one quick brown")
207
+ io.puts("fox jumped over the lazy dog")
208
+ end
209
+ scm.commit(checkout_dir, "Modified file to diff again")
210
+
211
+ changesets = scm.changesets(checkout_dir, Time.epoch)
212
+ end
213
+
214
+ private
215
+
216
+ def import_damagecontrolled(scm, import_copy_dir)
217
+ mkdir_p(import_copy_dir)
218
+ path = File.dirname(__FILE__) + "/../../testproject/damagecontrolled"
219
+ path = File.expand_path(path)
220
+ dirname = File.dirname(import_copy_dir)
221
+ cp_r(path, dirname)
222
+ todelete = Dir.glob("#{import_copy_dir}/**/.svn")
223
+ rm_rf(todelete)
224
+ scm.import(import_copy_dir, "imported\nsources")
225
+ end
226
+
227
+ def change_file(scm, file)
228
+ file = File.expand_path(file)
229
+ scm.edit(file)
230
+ File.open(file, "w+") do |io|
231
+ io.puts("changed\n")
232
+ end
233
+ end
234
+
235
+ def add_or_edit_and_commit_file(scm, checkout_dir, relative_filename, content)
236
+ existed = false
237
+ absolute_path = File.expand_path("#{checkout_dir}/#{relative_filename}")
238
+ File.mkpath(File.dirname(absolute_path))
239
+ existed = File.exist?(absolute_path)
240
+ File.open(absolute_path, "w") do |file|
241
+ file.puts(content)
242
+ end
243
+ scm.add(checkout_dir, relative_filename) unless(existed)
244
+
245
+ message = existed ? "editing" : "adding"
246
+
247
+ sleep(1)
248
+ scm.commit(checkout_dir, "#{message} #{relative_filename}")
249
+ end
250
+ end
251
+
252
+ module LabelTest
253
+ def test_label
254
+ work_dir = RSCM.new_temp_dir("label")
255
+ checkout_dir = "#{work_dir}/LabelTest"
256
+ repository_dir = "#{work_dir}/repository"
257
+ scm = create_scm(repository_dir, "damagecontrolled")
258
+ scm.create
259
+
260
+ import_damagecontrolled(scm, "#{work_dir}/damagecontrolled")
261
+
262
+ scm.checkout(checkout_dir)
263
+
264
+ # TODO: introduce a Revision class which implements comparator methods
265
+ assert_equal(
266
+ "1",
267
+ scm.label(checkout_dir)
268
+ )
269
+ change_file(scm, "#{checkout_dir}/build.xml")
270
+ scm.commit(checkout_dir, "changed something")
271
+ scm.checkout(checkout_dir)
272
+ assert_equal(
273
+ "2",
274
+ scm.label(checkout_dir)
275
+ )
276
+ end
277
+ end
278
+
279
+ module ApplyLabelTest
280
+
281
+ end
282
+ end
@@ -0,0 +1,76 @@
1
+ require 'stringio'
2
+ require 'ftools'
3
+ require 'fileutils'
4
+ require 'test/unit'
5
+ require 'rscm/line_editor'
6
+
7
+ module RSCM
8
+ class LineEditorTest < Test::Unit::TestCase
9
+
10
+ include LineEditor
11
+ include FileUtils
12
+
13
+ ORIGINAL_FILE = <<-EOF
14
+ dette er en helt
15
+ alminnelig fil med et
16
+ # denne er allerede utkommentert
17
+ som vi skal editere
18
+ EOF
19
+
20
+ ORIGINAL_FILE_WITH_HASH_STYLE_COMMENT = <<-EOF
21
+ # dette er en helt
22
+ alminnelig fil med et
23
+ # denne er allerede utkommentert
24
+ # som vi skal editere
25
+ EOF
26
+
27
+ ORIGINAL_FILE_WITH_DELETED_LINES = <<-EOF
28
+ alminnelig fil med et
29
+ EOF
30
+
31
+ def test_should_comment_out_matching_lines_with_hash
32
+ original = StringIO.new(ORIGINAL_FILE)
33
+ output = ""
34
+ assert(comment_out(original, /er/, "# ", output))
35
+ assert(!comment_out(original, /not in file/, "# ", output))
36
+ assert_equal(ORIGINAL_FILE_WITH_HASH_STYLE_COMMENT, output)
37
+ end
38
+
39
+ def test_should_delete_matching_lines
40
+ original = StringIO.new(ORIGINAL_FILE)
41
+ output = ""
42
+ assert(comment_out(original, /er/, nil, output))
43
+ assert_equal(ORIGINAL_FILE_WITH_DELETED_LINES, output)
44
+ end
45
+
46
+ def test_should_delete_matching_lines_in_file
47
+ orig_file = File.dirname(__FILE__) + "/file_to_edit"
48
+ orig_file_after_edit = File.dirname(__FILE__) + "/file_after_edit"
49
+
50
+ orig_file_copy = File.dirname(__FILE__) + "/../../target/file_to_edit"
51
+ mkdir_p(File.dirname(orig_file_copy))
52
+ File.copy(orig_file, orig_file_copy)
53
+
54
+ assert(File.comment_out(orig_file_copy, /er/, nil))
55
+ assert_equal(File.open(orig_file_after_edit).read, File.open(orig_file_copy).read)
56
+ end
57
+
58
+ def test_should_work_with_windows_paths
59
+ output = ""
60
+ winstuff = "c:\\Projects\\damagecontrol\\bin\\requestbuild --url http://53.233.149.7:4712/private/xmlrpc --projectname bla"
61
+ original = StringIO.new(winstuff)
62
+
63
+ with_backslash = "Projects\\damagecontrol"
64
+ regexp = /#{Regexp.escape(with_backslash)}/
65
+
66
+ assert(comment_out(original, regexp, "# ", output))
67
+ end
68
+
69
+ def test_should_work_with_unix_paths
70
+ uxstuff = "/Projects/damagecontrol/bin/requestbuild --url http://53.233.149.7:4712/private/xmlrpc --projectname bla"
71
+ original = StringIO.new(uxstuff)
72
+ output = ""
73
+ assert(comment_out(original, /#{uxstuff}/, "# ", output))
74
+ end
75
+ end
76
+ end