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,125 @@
1
+ module RSCM
2
+ module TimeExt
3
+ SECOND = 1
4
+ MINUTE = 60
5
+ HOUR = 60 * MINUTE
6
+ DAY = 24 * HOUR
7
+ WEEK = 7 * DAY
8
+ MONTH = 30 * DAY
9
+ YEAR = 365 * DAY
10
+ YEARS = 2 * YEAR
11
+
12
+ def duration_as_text(duration_secs)
13
+ case duration_secs
14
+ when 0 then "0 seconds"
15
+ when SECOND then "#{duration_secs/SECOND} second"
16
+ when SECOND+1..MINUTE-1 then "#{duration_secs/SECOND} seconds"
17
+ when MINUTE..2*MINUTE-1 then "#{duration_secs/MINUTE} minute"
18
+ when 2*MINUTE..HOUR-1 then "#{duration_secs/MINUTE} minutes"
19
+ when HOUR..2*HOUR-1 then "#{duration_secs/HOUR} hour"
20
+ when 2*HOUR..DAY-1 then "#{duration_secs/HOUR} hours"
21
+ when DAY..2*DAY-1 then "#{duration_secs/DAY} day"
22
+ when 2*DAY..WEEK-1 then "#{duration_secs/DAY} days"
23
+ when WEEK..2*WEEK-1 then "#{duration_secs/WEEK} week"
24
+ when 2*WEEK..MONTH-1 then "#{duration_secs/WEEK} weeks"
25
+ when MONTH..2*MONTH-1 then "#{duration_secs/MONTH} month"
26
+ when 2*MONTH..YEAR-1 then "#{duration_secs/MONTH} months"
27
+ when YEAR..2*YEAR-1 then "#{duration_secs/YEAR} year"
28
+ else "#{duration_secs/YEAR} years"
29
+ end
30
+ end
31
+ module_function :duration_as_text
32
+ end
33
+ end
34
+
35
+ # Time mixin that adds some additional utility methods
36
+ class Time
37
+ include RSCM::TimeExt
38
+
39
+ class << self
40
+ def epoch
41
+ Time.utc(1970)
42
+ end
43
+
44
+ def infinity
45
+ Time.utc(2038)
46
+ end
47
+ end
48
+
49
+ def Time.parse_ymdHMS(timestamp_as_ymdHMS)
50
+ Time.utc(
51
+ timestamp_as_ymdHMS[0..3], # year
52
+ timestamp_as_ymdHMS[4..5], # month
53
+ timestamp_as_ymdHMS[6..7], # day
54
+ timestamp_as_ymdHMS[8..9], # hour
55
+ timestamp_as_ymdHMS[10..11], # minute
56
+ timestamp_as_ymdHMS[12..13] # second
57
+ )
58
+ end
59
+
60
+ def to_rfc2822
61
+ utc.strftime("%a, %d %b %Y %H:%M:%S +0000")
62
+ end
63
+
64
+ def to_human
65
+ utc.strftime("%d %b %Y %H:%M:%S")
66
+ end
67
+
68
+ def ymdHMS
69
+ utc.strftime("%Y%m%d%H%M%S")
70
+ end
71
+
72
+ def ==(o)
73
+ return false unless o.is_a?(Time)
74
+ ymdHMS == o.ymdHMS
75
+ end
76
+
77
+ # In many cases (for example when drawing a graph with
78
+ # dates along the x-axis) it can be useful to know what
79
+ # month, week or day a certain timestamp is within.
80
+ #
81
+ # This lets you do that. Call with :day, :week or :month
82
+ # returns period_number, period_start
83
+ #
84
+ # period_number is an int representing the day, week or month number of the year.
85
+ # period_start is a utc time of the start of the period.
86
+ def get_period_info(interval)
87
+ case interval
88
+ when :week then get_week_info
89
+ when :month then get_month_info
90
+ when :day then get_day_info
91
+ end
92
+ end
93
+
94
+ # week_number, week_start_date = get_info(time, :week)
95
+ def get_week_info
96
+ first_day_of_year = Time.utc(utc.year, 1, 1)
97
+ week_day_of_first_day_of_year = first_day_of_year.wday
98
+ # Sunday = 0, .. Monday = 6
99
+ first_monday_of_year = Time.utc(utc.year, 1, ((week_day_of_first_day_of_year % 7) + 1))
100
+
101
+ week_number = nil
102
+ week_start_date = nil
103
+ days = (utc.yday - first_monday_of_year.yday)
104
+ week_number = (days / 7) + 1
105
+ week_start_date = first_monday_of_year + ((week_number-1) * 7) * 60 * 60 * 24
106
+ return week_number, week_start_date
107
+ end
108
+
109
+ # month_number, month_start_date = get_info(time, :month)
110
+ def get_month_info
111
+ return month, Time.utc(utc.year, utc.month, 1)
112
+ end
113
+
114
+ # day_number, day_date = get_info(time, :day)
115
+ def get_day_info
116
+ return yday, Time.utc(utc.year, utc.month, utc.day)
117
+ end
118
+
119
+ def difference_as_text(t)
120
+ raise "t must be a time" unless t.is_a?(Time)
121
+ diff = (self - t).to_i
122
+ duration_as_text(diff)
123
+ end
124
+
125
+ end
@@ -0,0 +1,26 @@
1
+ require 'fileutils'
2
+
3
+ module RSCM
4
+ module GenericSCMTests
5
+ include FileUtils
6
+
7
+ def test_apply_label
8
+ work_dir = new_temp_dir
9
+ checkout_dir = "#{work_dir}/checkout"
10
+ repository_dir = "#{work_dir}/repository"
11
+ scm = create_scm(repository_dir, "damagecontrolled")
12
+ scm.create
13
+
14
+ import_damagecontrolled(scm, "#{work_dir}/damagecontrolled")
15
+ scm.checkout(checkout_dir)
16
+
17
+ add_or_edit_and_commit_file(scm, checkout_dir, "before.txt", "Before label")
18
+ scm.apply_label(checkout_dir, "MY_LABEL")
19
+ add_or_edit_and_commit_file(scm, checkout_dir, "after.txt", "After label")
20
+ scm.checkout(checkout_dir, "MY_LABEL")
21
+ assert(File.exist?("#{checkout_dir}/before.txt"))
22
+ assert(!File.exist?("#{checkout_dir}/after.txt"))
23
+ end
24
+
25
+ end
26
+ end
@@ -0,0 +1,20 @@
1
+ require 'test/unit'
2
+ require 'rscm/changes'
3
+
4
+ module RSCM
5
+ module ChangesFixture
6
+ def setup_changes
7
+ #1
8
+ @change1 = RSCM::Change.new("path/one", "jon", "Fixed CATCH-22", nil, Time.utc(2004,7,5,12,0,2))
9
+ @change2 = RSCM::Change.new("path/two", "jon", "Fixed CATCH-22", nil, Time.utc(2004,7,5,12,0,4))
10
+ #2
11
+ @change3 = RSCM::Change.new("path/three", "jon", "hipp hurra", nil, Time.utc(2004,7,5,12,0,6))
12
+ #3
13
+ @change4 = RSCM::Change.new("path/four", "aslak", "hipp hurraX", nil, Time.utc(2004,7,5,12,0,8))
14
+ #4
15
+ @change5 = RSCM::Change.new("path/five", "aslak", "hipp hurra", nil, Time.utc(2004,7,5,12,0,10))
16
+ @change6 = RSCM::Change.new("path/six", "aslak", "hipp hurra", nil, Time.utc(2004,7,5,12,0,12))
17
+ @change7 = RSCM::Change.new("path/seven", "aslak", "hipp hurra", nil, Time.utc(2004,7,5,12,0,14))
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,129 @@
1
+ require 'yaml'
2
+ require 'rscm/changes_fixture'
3
+
4
+ module RSCM
5
+ class ChangesTest < Test::Unit::TestCase
6
+ include ChangesFixture
7
+
8
+ def setup
9
+ setup_changes
10
+ end
11
+
12
+ def test_convert_changes_to_changesets_should_match_user_message_and_timestamp_
13
+ changesets = ChangeSets.new
14
+ changesets.add(@change1)
15
+ changesets.add(@change2)
16
+ changesets.add(@change3)
17
+ changesets.add(@change4)
18
+ changesets.add(@change5)
19
+ changesets.add(@change6)
20
+ changesets.add(@change7)
21
+
22
+ changeset_0 = ChangeSet.new
23
+ changeset_0 << @change1
24
+ changeset_0 << @change2
25
+
26
+ changeset_1 = ChangeSet.new
27
+ changeset_1 << @change3
28
+
29
+ changeset_2 = ChangeSet.new
30
+ changeset_2 << @change4
31
+
32
+ changeset_3 = ChangeSet.new
33
+ changeset_3 << @change5
34
+ changeset_3 << @change6
35
+ changeset_3 << @change7
36
+
37
+ assert_equal(4, changesets.length)
38
+
39
+ expected_changesets = ChangeSets.new
40
+ expected_changesets.add(changeset_0)
41
+ expected_changesets.add(changeset_1)
42
+ expected_changesets.add(changeset_2)
43
+ expected_changesets.add(changeset_3)
44
+
45
+ assert_equal(expected_changesets, changesets)
46
+ end
47
+
48
+ def test_changesets_can_add_individual_changes_and_group_in_changeset_instances
49
+ changesets = ChangeSets.new
50
+ assert(0, changesets.length)
51
+
52
+ changesets.add(@change1)
53
+ changesets.add(@change2)
54
+ changesets.add(@change3)
55
+ changesets.add(@change4)
56
+ assert(3, changesets.length)
57
+
58
+ tjo_bing_changeset = changesets[0]
59
+ hipp_hurra_changeset = changesets[1]
60
+ hipp_hurraX_changeset = changesets[2]
61
+ assert(2, tjo_bing_changeset.length)
62
+ assert(1, hipp_hurra_changeset.length)
63
+ assert(1, hipp_hurraX_changeset.length)
64
+
65
+ assert_same(@change1, tjo_bing_changeset[0])
66
+ assert_same(@change2, tjo_bing_changeset[1])
67
+ assert_same(@change3, hipp_hurra_changeset[0])
68
+ assert_same(@change4, hipp_hurraX_changeset[0])
69
+ end
70
+
71
+ def test_should_sort_by_time
72
+ changesets = ChangeSets.new
73
+ changesets.add(@change1)
74
+ changesets.add(@change4)
75
+ changesets.add(@change2)
76
+ changesets.add(@change7)
77
+ changesets.add(@change5)
78
+ changesets.add(@change3)
79
+ changesets.add(@change6)
80
+
81
+ changesets = changesets.sort do |a,b|
82
+ a.time <=> b.time
83
+ end
84
+ assert_equal(4, changesets.length)
85
+
86
+ assert_equal(@change2.time, changesets[0].time)
87
+ assert_equal(@change7.time, changesets[-1].time)
88
+ end
89
+
90
+ def test_can_parse_changesets_from_yaml
91
+ changesets = File.open(File.dirname(__FILE__) + "/changesets.yaml") do |io|
92
+ YAML::load(io)
93
+ end
94
+ assert_equal("rinkrank", changesets[0][1].developer)
95
+ assert_equal("En to\ntre buksa \nned\n", changesets[0][1].message)
96
+ end
97
+
98
+ def test_reports_timestamp_of_latest_change
99
+ changeset = ChangeSet.new
100
+ changeset << Change.new(nil, nil, nil, nil, Time.utc(2004))
101
+ changeset << Change.new(nil, nil, nil, nil, Time.utc(2005))
102
+ changeset << Change.new(nil, nil, nil, nil, Time.utc(2003))
103
+ assert_equal(Time.utc(2005), changeset.time)
104
+ end
105
+
106
+ def test_should_sort_changesets
107
+ changesets = ChangeSets.new
108
+ changesets.add(@change1)
109
+ changesets.add(@change4)
110
+ changesets.add(@change2)
111
+ changesets.add(@change7)
112
+ changesets.add(@change5)
113
+ changesets.add(@change3)
114
+ changesets.add(@change6)
115
+
116
+ cs0 = changesets[0]
117
+ cs1 = changesets[1]
118
+ cs2 = changesets[2]
119
+ cs3 = changesets[3]
120
+
121
+ reversed = changesets.reverse
122
+ assert_equal(cs0, reversed[3])
123
+ assert_equal(cs1, reversed[2])
124
+ assert_equal(cs2, reversed[1])
125
+ assert_equal(cs3, reversed[0])
126
+ end
127
+ end
128
+
129
+ end
@@ -0,0 +1,575 @@
1
+ require 'test/unit'
2
+ require 'stringio'
3
+ require 'fileutils'
4
+ require 'rscm/changes'
5
+ require 'rscm/cvs/cvs_log_parser'
6
+
7
+ module RSCM
8
+ class CVSLogParserTest < Test::Unit::TestCase
9
+
10
+ include FileUtils
11
+
12
+ def setup
13
+ @parser = CVSLogParser.new(nil)
14
+ @parser.cvspath = "/scm/damagecontrol"
15
+ @parser.cvsmodule = "damagecontrol"
16
+ end
17
+
18
+ def teardown
19
+ assert(!@parser.had_error?, "parser had errors") unless @parser.nil?
20
+ end
21
+
22
+ def test_read_log_entry
23
+ assert_equal(nil, CVSLogParser.new(StringIO.new("")).next_log_entry)
24
+ end
25
+
26
+ def test_parses_entire_log_into_changesets
27
+ File.open(File.dirname(__FILE__) + "/cvs-test.log") do |io|
28
+ @parser = CVSLogParser.new(io)
29
+ changesets = @parser.parse_changesets
30
+
31
+ assert_equal(24, changesets.length)
32
+ assert_match(/o YAML config \(BuildBootstrapper\)/, changesets[1].message)
33
+ assert_match(/failure/, changesets[8].message)
34
+ end
35
+ end
36
+
37
+ # http://jira.codehaus.org/browse/DC-312
38
+ def test_jira_dc_312
39
+ File.open(File.dirname(__FILE__) + "/cvs-dataforge.log") do |io|
40
+ @parser = CVSLogParser.new(io)
41
+ changesets = @parser.parse_changesets
42
+
43
+ assert_equal(271, changesets.length)
44
+ end
45
+ end
46
+
47
+ def test_parse_changes
48
+ changesets = ChangeSets.new
49
+ @parser.parse_changes(LOG_ENTRY, changesets)
50
+ changesets.sort!
51
+ assert_equal(4, changesets.length)
52
+ assert_equal("src/ruby/damagecontrol/BuildExecutorTest.rb", changesets[0][0].path)
53
+ assert_match(/linux-windows galore/, changesets[1][0].message)
54
+ end
55
+
56
+ def test_sets_previous_revision_to_one_before_the_current
57
+ change = @parser.parse_change(CHANGE_ENTRY)
58
+ assert_equal("1.20", change.revision)
59
+ assert_equal("1.19", change.previous_revision)
60
+ end
61
+
62
+ def test_can_determine_previous_revisions_from_tricky_input
63
+ assert_equal("2.2.1.1", @parser.determine_previous_revision("2.2.1.2"))
64
+ assert_equal(nil, @parser.determine_previous_revision("2.2.1.1"))
65
+ end
66
+
67
+ def test_parse_change
68
+ change = @parser.parse_change(CHANGE_ENTRY)
69
+ assert_equal("1.20", change.revision)
70
+ assert_equal(Time.utc(2003,11,9,17,53,37), change.time)
71
+ assert_equal("tirsen", change.developer)
72
+ assert_match(/Quiet period is configurable for each project/, change.message)
73
+ end
74
+
75
+ def test_can_split_entries_separated_by_line_of_dashes
76
+ entries = @parser.split_entries(LOG_ENTRY)
77
+ assert_equal(5, entries.length)
78
+ assert_equal(CHANGE_ENTRY, entries[1])
79
+ end
80
+
81
+ CHANGE_ENTRY = <<-EOF
82
+ revision 1.20
83
+ date: 2003/11/09 17:53:37; author: tirsen; state: Exp; lines: +3 -4
84
+ Quiet period is configurable for each project
85
+ EOF
86
+
87
+ LOG_ENTRY_WITH_DELETED_FILE = <<EOF
88
+ RCS file: /scm/damagecontrol/damagecontrol/server/damagecontrol/Attic/codehaus.rb,v
89
+ Working file: server/damagecontrol/codehaus.rb
90
+ head: 1.23
91
+ branch:
92
+ locks: strict
93
+ access list:
94
+ keyword substitution: kv
95
+ total revisions: 23; selected revisions: 1
96
+ description:
97
+ ----------------------------
98
+ revision 1.23
99
+ date: 2004/07/13 07:56:26; author: tirsen; state: dead; lines: +0 -0
100
+ remove username check (doesn't work on beaver)
101
+ I do really want to see the url in irc, it's very, very convenient. thank you very much ;-)
102
+ EOF
103
+
104
+ def test_can_parse_changes_with_deleted_file
105
+ changesets = ChangeSets.new
106
+ @parser.parse_changes(LOG_ENTRY_WITH_DELETED_FILE, changesets)
107
+ assert_equal(1, changesets.length)
108
+ assert_equal("server/damagecontrol/codehaus.rb", changesets[0][0].path)
109
+ assert_equal(Change::DELETED, changesets[0][0].status)
110
+ end
111
+
112
+ def test_log_from_e2e_test
113
+ @parser = CVSLogParser.new(StringIO.new(LOG_FROM_E2E_TEST))
114
+ changesets = @parser.parse_changesets
115
+ assert_equal(2, changesets.length)
116
+ assert_match(/foo/, changesets[1].message)
117
+ assert_match(/bar/, changesets[0].message)
118
+ end
119
+
120
+ LOG_FROM_E2E_TEST = <<-EOF
121
+ =============================================================================
122
+
123
+ RCS file: C:\projects\damagecontrol\target\temp_e2e_1081547757\repository/e2eproject/build.bat,v
124
+ Working file: build.bat
125
+ head: 1.2
126
+ branch:
127
+ locks: strict
128
+ access list:
129
+ symbolic names:
130
+ keyword substitution: kv
131
+ total revisions: 2; selected revisions: 2
132
+ description:
133
+ ----------------------------
134
+ revision 1.2
135
+ date: 2004/04/09 21:56:47; author: jtirsen; state: Exp; lines: +1 -1
136
+ foo
137
+ ----------------------------
138
+ revision 1.1
139
+ date: 2004/04/09 21:56:12; author: jtirsen; state: Exp;
140
+ bar
141
+ =============================================================================EOF
142
+ EOF
143
+
144
+ LOG_ENTRY = <<-EOF
145
+ =============================================================================
146
+
147
+ RCS file: /scm/damagecontrol/damagecontrol/src/ruby/damagecontrol/BuildExecutorTest.rb,v
148
+ Working file: src/ruby/damagecontrol/BuildExecutorTest.rb
149
+ head: 1.20
150
+ branch:
151
+ locks: strict
152
+ access list:
153
+ symbolic names:
154
+ keyword substitution: kv
155
+ total revisions: 20; selected revisions: 4
156
+ description:
157
+ ----------------------------
158
+ revision 1.20
159
+ date: 2003/11/09 17:53:37; author: tirsen; state: Exp; lines: +3 -4
160
+ Quiet period is configurable for each project
161
+ ----------------------------
162
+ revision 1.19
163
+ date: 2003/11/09 17:04:18; author: tirsen; state: Exp; lines: +32 -2
164
+ Quiet period implemented for BuildExecutor, but does not yet handle multiple projects (builds are not queued as before)
165
+ ----------------------------
166
+ revision 1.18
167
+ date: 2003/11/09 15:51:50; author: rinkrank; state: Exp; lines: +1 -2
168
+ linux-windows galore
169
+ ----------------------------
170
+ revision 1.17
171
+ date: 2003/11/09 15:00:06; author: rinkrank; state: Exp; lines: +6 -8
172
+ o YAML config (BuildBootstrapper)
173
+ o EmailPublisher
174
+ =============================================================================
175
+ EOF
176
+
177
+ def test_can_parse_path
178
+ assert_equal("testdata/damagecontrolled/src/java/com/thoughtworks/damagecontrolled/Thingy.java",
179
+ @parser.parse_path(LOG_ENTRY_FROM_05_07_2004_19_42))
180
+ end
181
+
182
+ LOG_ENTRY_FROM_05_07_2004_19_42 = <<-EOF
183
+ RCS file: /scm/damagecontrol/damagecontrol/testdata/damagecontrolled/src/java/com/thoughtworks/damagecontrolled/Thingy.java,v
184
+ Working file: testdata/damagecontrolled/src/java/com/thoughtworks/damagecontrolled/Thingy.java
185
+ head: 1.1
186
+ branch:
187
+ locks: strict
188
+ access list:
189
+ symbolic names:
190
+ BEFORE_CENTRAL_REFACTORING: 1.1
191
+ RELEASE_0_1: 1.1
192
+ keyword substitution: kv
193
+ total revisions: 1; selected revisions: 1
194
+ description:
195
+ EOF
196
+
197
+ def test_can_parse_LOG_FROM_05_07_2004_19_41
198
+ @parser = CVSLogParser.new(StringIO.new(LOG_FROM_05_07_2004_19_41))
199
+ assert_equal(11, @parser.split_entries(LOG_FROM_05_07_2004_19_41).size)
200
+ assert_equal("server/damagecontrol/scm/CVS.rb", @parser.parse_path(@parser.split_entries(LOG_FROM_05_07_2004_19_41)[0]))
201
+ changesets = @parser.parse_changesets
202
+
203
+ assert_equal(10, changesets.length)
204
+ expected_change = Change.new
205
+ expected_change.path = "server/damagecontrol/scm/CVS.rb"
206
+ expected_change.developer = "tirsen"
207
+ expected_change.message = "fixed some stuff in the log parser"
208
+ expected_change.revision = "1.19"
209
+ expected_change.time = Time.utc(2004, 7, 5, 9, 41, 51)
210
+
211
+ assert_equal(expected_change, changesets[9][0])
212
+ end
213
+
214
+ LOG_FROM_05_07_2004_19_41 = <<-EOF
215
+
216
+ RCS file: /scm/damagecontrol/damagecontrol/server/damagecontrol/scm/CVS.rb,v
217
+ Working file: server/damagecontrol/scm/CVS.rb
218
+ head: 1.19
219
+ branch:
220
+ locks: strict
221
+ access list:
222
+ symbolic names:
223
+ BEFORE_CENTRAL_REFACTORING: 1.1
224
+ keyword substitution: kv
225
+ total revisions: 19; selected revisions: 19
226
+ description:
227
+ ----------------------------
228
+ revision 1.19
229
+ date: 2004/07/05 09:41:51; author: tirsen; state: Exp; lines: +1 -1
230
+ fixed some stuff in the log parser
231
+ ----------------------------
232
+ revision 1.18
233
+ date: 2004/07/05 09:38:21; author: tirsen; state: Exp; lines: +7 -6
234
+ fixed some stuff in the log parser
235
+ ----------------------------
236
+ revision 1.17
237
+ date: 2004/07/05 09:09:44; author: tirsen; state: Exp; lines: +2 -0
238
+ oops.... log parser can't actually log apparently, well, it can now...
239
+ ----------------------------
240
+ revision 1.16
241
+ date: 2004/07/05 08:52:39; author: tirsen; state: Exp; lines: +23 -26
242
+ refactorings in the web
243
+ fixed footer with css
244
+ some other cssing around
245
+ fixed cvs output so my irc client actually gives me a proper link I can click on
246
+ ----------------------------
247
+ revision 1.15
248
+ date: 2004/07/04 18:04:38; author: rinkrank; state: Exp; lines: +1 -1
249
+ debug debug
250
+ ----------------------------
251
+ revision 1.14
252
+ date: 2004/07/04 17:44:36; author: rinkrank; state: Exp; lines: +23 -8
253
+ improved error logging
254
+ ----------------------------
255
+ revision 1.13
256
+ date: 2004/07/04 15:59:16; author: rinkrank; state: Exp; lines: +1 -0
257
+ debugging cvs timestamps
258
+ ----------------------------
259
+ revision 1.12
260
+ date: 2004/07/03 19:25:19; author: rinkrank; state: Exp; lines: +20 -3
261
+ support for previous_revision in modifications
262
+ ----------------------------
263
+ revision 1.11
264
+ date: 2004/07/02
265
+ CVS and CC refactorings. Improved parsing of trigger command line and bootstrapping
266
+ ----------------------------
267
+ revision 1.1
268
+ date: 2003/10/04 12:04:14; author: tirsen; state: Exp;
269
+ Cleaned up the end-to-end test, did some more work on the CCLogPoller
270
+ EOF
271
+
272
+ LOG_ENTRY_FROM_06_07_2004_19_25_1 = <<EOF
273
+ RCS file: /home/projects/jmock/scm/jmock/core/src/test/jmock/core/testsupport/MockInvocationMat
274
+ V1_0_1: 1.4
275
+ V1_0_0: 1.4
276
+ V1_0_0_RC1: 1.4
277
+ v1_0_0_RC1: 1.4
278
+ before_removing_features_deprecated_pre_1_0_0: 1.1
279
+ keyword substitution: kv
280
+ total revisions: 4; selected revisions: 0
281
+ description:
282
+
283
+ EOF
284
+
285
+ def test_can_parse_LOG_ENTRY_FROM_06_07_2004_19_25_1
286
+ @parser.cvspath = "/home/projects/jmock/scm/jmock"
287
+ @parser.cvsmodule = "core"
288
+ assert_equal("src/test/jmock/core/testsupport/MockInvocationMat", @parser.parse_path(LOG_ENTRY_FROM_06_07_2004_19_25_1))
289
+ end
290
+
291
+ LOG_ENTRY_FROM_06_07_2004_19_19 = <<EOF
292
+ Working file: lib/xmlrpc/datetime.rb
293
+ head: 1.1
294
+ branch:
295
+ locks: strict
296
+ access list:
297
+ symbolic names:
298
+ BEFORE_CENTRAL_REFACTORING: 1.1
299
+ keyword substitution: kv
300
+ total revisions: 1; selected revisions: 0
301
+ description:
302
+
303
+ EOF
304
+
305
+ def test_can_parse_LOG_ENTRY_FROM_06_07_2004_19_19
306
+ assert_equal("lib/xmlrpc/datetime.rb", @parser.parse_path(LOG_ENTRY_FROM_06_07_2004_19_19))
307
+ end
308
+
309
+ LOG_ENTRY_FROM_06_07_2004_19_25_2 = <<EOF
310
+ RC
311
+ Working file: website/templates/logo.gif
312
+ head: 1.2
313
+ branch:
314
+ locks: strict
315
+ access list:
316
+ symbolic names:
317
+ steves_easymock: 1.2.0.2
318
+ Root_steves_easymock: 1.2
319
+ V1_0_1: 1.2
320
+ V1_0_0: 1.2
321
+ V1_0_0_RC1: 1.2
322
+ before_removing_features_deprecated_pre_1_0_0: 1.2
323
+ pre-hotmock-syntax-change: 1.2
324
+ keyword substitution: b
325
+ total revisions: 2; selected revisions: 0
326
+ description:
327
+
328
+ EOF
329
+
330
+ def test_can_parse_LOG_ENTRY_FROM_06_07_2004_19_25_2
331
+ assert_equal("website/templates/logo.gif", @parser.parse_path(LOG_ENTRY_FROM_06_07_2004_19_25_2))
332
+ end
333
+
334
+ # stand in picocontainer's java folder
335
+ # cvs log -d"2003/07/25 12:38:41<=2004/07/08 12:38:41" build.xml
336
+ LOG_WITH_DELETIONS= <<EOF
337
+ RCS file: /home/projects/picocontainer/scm/java/Attic/build.xml,v
338
+ Working file: build.xml
339
+ head: 1.11
340
+ branch:
341
+ locks: strict
342
+ access list:
343
+ symbolic names:
344
+ MERGE_CONTAINER_AND_REGISTRY_REFACTORING_BRANCH: 1.10.0.2
345
+ BEFORE_MERGE_CONTAINER_AND_REGISTRY_REFACTORING_TAG: 1.10
346
+ BEFORE_MULTIPLE_CONSTRUCTORS: 1.10
347
+ keyword substitution: kv
348
+ total revisions: 11; selected revisions: 2
349
+ description:
350
+ ----------------------------
351
+ revision 1.11
352
+ date: 2003/10/13 00:04:54; author: rinkrank; state: dead; lines: +0 -0
353
+ Obsolete
354
+ ----------------------------
355
+ revision 1.10
356
+ date: 2003/07/25 16:32:39; author: rinkrank; state: Exp; lines: +1 -1
357
+ fixed broken url (NANO-8)
358
+ =============================================================================
359
+ EOF
360
+
361
+ def test_can_parse_LOG_WITH_DELETIONS
362
+ @parser = CVSLogParser.new(StringIO.new(LOG_WITH_DELETIONS))
363
+ changesets = @parser.parse_changesets
364
+ assert_equal(2, changesets.length)
365
+
366
+ changeset_delete = changesets[1]
367
+ # assert_equal("MAIN:rinkrank:20031013000454", changeset_delete.revision)
368
+ assert_equal(Time.utc(2003,10,13,00,04,54,0), changeset_delete.time)
369
+ assert_equal("Obsolete", changeset_delete.message)
370
+ assert_equal("rinkrank", changeset_delete.developer)
371
+ assert_equal(1, changeset_delete.length)
372
+ assert_equal("build.xml", changeset_delete[0].path)
373
+ assert_equal("1.11", changeset_delete[0].revision)
374
+ assert_equal("1.10", changeset_delete[0].previous_revision)
375
+ assert(Change::DELETED, changeset_delete[0].status)
376
+
377
+ changeset_fix_url = changesets[0]
378
+ # assert_equal("MAIN:rinkrank:20030725163239", changeset_fix_url.revision)
379
+ assert_equal(Time.utc(2003,07,25,16,32,39,0), changeset_fix_url.time)
380
+ assert_equal("fixed broken url (NANO-8)", changeset_fix_url.message)
381
+ assert_equal("rinkrank", changeset_fix_url.developer)
382
+ assert_equal(1, changeset_fix_url.length)
383
+ assert_equal("build.xml", changeset_fix_url[0].path)
384
+ assert_equal("1.10", changeset_fix_url[0].revision)
385
+ assert_equal("1.9", changeset_fix_url[0].previous_revision)
386
+ assert_equal(Change::MODIFIED, changeset_fix_url[0].status)
387
+ end
388
+
389
+ LOG_WITH_MISSING_ENTRIES = <<EOF
390
+ RCS file: /cvsroot/damagecontrol/damagecontrol/Attic/build.xml,v
391
+ Working file: build.xml
392
+ head: 1.2
393
+ branch:
394
+ locks: strict
395
+ access list:
396
+ symbolic names:
397
+ initial-import: 1.1.1.1
398
+ mgm: 1.1.1
399
+ keyword substitution: kv
400
+ total revisions: 3; selected revisions: 0
401
+ description:
402
+ =============================================================================
403
+
404
+ RCS file: /cvsroot/damagecontrol/damagecontrol/maven.xml,v
405
+ Working file: maven.xml
406
+ head: 1.2
407
+ branch:
408
+ locks: strict
409
+ access list:
410
+ symbolic names:
411
+ keyword substitution: kv
412
+ total revisions: 2; selected revisions: 0
413
+ description:
414
+ =============================================================================
415
+ EOF
416
+
417
+ def test_can_parse_LOG_WITH_MISSING_ENTRIES
418
+ @parser = CVSLogParser.new(StringIO.new(LOG_WITH_MISSING_ENTRIES))
419
+ changesets = @parser.parse_changesets
420
+ assert_equal(0, changesets.length)
421
+ end
422
+
423
+ LOG_WITH_NEW_AND_OLD_FILE = <<EOF
424
+ RCS file: /home/projects/damagecontrol/scm/damagecontrol/dummy.txt,v
425
+ Working file: dummy.txt
426
+ head: 1.1
427
+ branch:
428
+ locks: strict
429
+ access list:
430
+ keyword substitution: kv
431
+ total revisions: 1; selected revisions: 1
432
+ description:
433
+ ----------------------------
434
+ revision 1.1
435
+ date: 2004/07/13 21:50:59; author: rinkrank; state: Exp;
436
+ Debug. Need to see what the log looks like for a new file.
437
+ =============================================================================
438
+
439
+ RCS file: /home/projects/damagecontrol/scm/damagecontrol/license.txt,v
440
+ Working file: license.txt
441
+ head: 1.4
442
+ branch:
443
+ locks: strict
444
+ access list:
445
+ keyword substitution: kv
446
+ total revisions: 4; selected revisions: 4
447
+ description:
448
+ ----------------------------
449
+ revision 1.101
450
+ date: 2004/07/10 17:41:14; author: rinkrank; state: Exp; lines: +2 -2
451
+ typo
452
+ ----------------------------
453
+ revision 1.11
454
+ date: 2004/07/10 17:38:22; author: rinkrank; state: Exp; lines: +2 -2
455
+ fixed http://jira.codehaus.org/browse/DC-123
456
+ ----------------------------
457
+ revision 1.1
458
+ date: 2004/07/02 08:42:51; author: tirsen; state: Exp;
459
+ installer!!!!!! it's getting close to release!!!
460
+ =============================================================================
461
+ EOF
462
+
463
+ def test_can_distinguish_new_file_from_old_file
464
+ @parser = CVSLogParser.new(StringIO.new(LOG_WITH_NEW_AND_OLD_FILE))
465
+ changesets = @parser.parse_changesets
466
+
467
+ assert_equal(Change::ADDED, changesets[0][0].status)
468
+ assert_equal(Change::MODIFIED, changesets[1][0].status)
469
+ assert_equal(Change::MODIFIED, changesets[2][0].status)
470
+ assert_equal(Change::ADDED, changesets[3][0].status)
471
+ end
472
+
473
+ # https://sitemesh.dev.java.net/source/browse/sitemesh/.cvsignore
474
+ # The default commit message probably showed up in vi, and the committer
475
+ # probably just left it there. Not sure why CVS kept it this way
476
+ # (lines starting with CVS: should be ignored in commit message afik).
477
+ # Anyway, the parser nw knows how to deal with this. (AH)
478
+ LOG_WITH_WEIRD_CVS_AND_MANY_DASHES = <<EOF
479
+ ? log.txt
480
+
481
+ RCS file: /cvs/sitemesh/.cvsignore,v
482
+ Working file: .cvsignore
483
+ head: 1.3
484
+ branch:
485
+ locks: strict
486
+ access list:
487
+ keyword substitution: kv
488
+ total revisions: 3; selected revisions: 3
489
+ description:
490
+ ----------------------------
491
+ revision 1.3
492
+ date: 2004/05/03 09:03:56; author: rhallier; state: Exp; lines: +2 -0
493
+ Issue number: SIM-90
494
+
495
+ Obtained from: JIRA
496
+
497
+ Submitted by: rhallier
498
+
499
+ Reviewed by:
500
+
501
+ CVS: ----------------------------------------------------------------------
502
+
503
+ CVS: Issue number:
504
+
505
+ CVS: If this change addresses one or more issues,
506
+
507
+ CVS: then enter the issue number(s) here.
508
+
509
+ CVS: Obtained from:
510
+
511
+ CVS: If this change has been taken from another system,
512
+
513
+ CVS: then name the system in this line, otherwise delete it.
514
+
515
+ CVS: Submitted by:
516
+
517
+ CVS: If this code has been contributed to the project by someone else; i.e.,
518
+
519
+ CVS: they sent us a patch or a set of diffs, then include their name/email
520
+
521
+ CVS: address here. If this is your work then delete this line.
522
+
523
+ CVS: Reviewed by:
524
+
525
+ CVS: If we are doing pre-commit code reviews and someone else has
526
+
527
+ CVS: reviewed your changes, include their name(s) here.
528
+
529
+ CVS: If you have not had it reviewed then delete this line.
530
+ ----------------------------
531
+ revision 1.2
532
+ date: 2003/11/22 07:56:51; author: hani; state: Exp; lines: +2 -1
533
+ Ignore IDEA files
534
+ ----------------------------
535
+ revision 1.1
536
+ date: 2003/11/03 16:27:37; author: mbogaert; state: Exp;
537
+ Moved from SF.
538
+ =============================================================================
539
+
540
+ RCS file: /cvs/sitemesh/CHANGES.txt,v
541
+ Working file: CHANGES.txt
542
+ head: 1.3
543
+ branch:
544
+ locks: strict
545
+ access list:
546
+ keyword substitution: kv
547
+ total revisions: 3; selected revisions: 3
548
+ description:
549
+ ----------------------------
550
+ revision 1.3
551
+ date: 2004/10/08 07:18:38; author: hani; state: Exp; lines: +18 -0
552
+ More files not updated for release
553
+ ----------------------------
554
+ revision 1.2
555
+ date: 2004/09/24 14:04:12; author: jwalnes1; state: Exp; lines: +19 -0
556
+ Preparing for 2.2 release.
557
+ Issue number:
558
+ Obtained from:
559
+ Submitted by:
560
+ Reviewed by:
561
+ ----------------------------
562
+ revision 1.1
563
+ date: 2004/07/22 01:30:27; author: farkas; state: Exp;
564
+ Final changes for 2.1 release
565
+ =============================================================================
566
+ EOF
567
+
568
+ def test_can_parse_logs_with_cvs_and_dashes_in_commit_message
569
+ @parser = CVSLogParser.new(StringIO.new(LOG_WITH_WEIRD_CVS_AND_MANY_DASHES))
570
+ changesets = @parser.parse_changesets
571
+ assert_equal(6, changesets.length)
572
+ end
573
+
574
+ end
575
+ end