rscm 0.1.0

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.
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