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.
- data/README +198 -0
- data/Rakefile +118 -0
- data/ext/rscm.jar +0 -0
- data/lib/rscm.rb +10 -0
- data/lib/rscm/abstract_log_parser.rb +49 -0
- data/lib/rscm/abstract_scm.rb +229 -0
- data/lib/rscm/changes.rb +271 -0
- data/lib/rscm/cvs/cvs.rb +363 -0
- data/lib/rscm/cvs/cvs_log_parser.rb +161 -0
- data/lib/rscm/darcs/darcs.rb +69 -0
- data/lib/rscm/line_editor.rb +46 -0
- data/lib/rscm/logging.rb +5 -0
- data/lib/rscm/monotone/monotone.rb +107 -0
- data/lib/rscm/mooky/mooky.rb +13 -0
- data/lib/rscm/parser.rb +39 -0
- data/lib/rscm/path_converter.rb +92 -0
- data/lib/rscm/perforce/perforce.rb +415 -0
- data/lib/rscm/starteam/starteam.rb +99 -0
- data/lib/rscm/svn/svn.rb +337 -0
- data/lib/rscm/svn/svn_log_parser.rb +134 -0
- data/lib/rscm/time_ext.rb +125 -0
- data/test/rscm/apply_label_scm_tests.rb +26 -0
- data/test/rscm/changes_fixture.rb +20 -0
- data/test/rscm/changes_test.rb +129 -0
- data/test/rscm/cvs/cvs_log_parser_test.rb +575 -0
- data/test/rscm/cvs/cvs_test.rb +22 -0
- data/test/rscm/darcs/darcs_test.rb +14 -0
- data/test/rscm/difftool_test.rb +40 -0
- data/test/rscm/file_ext.rb +12 -0
- data/test/rscm/generic_scm_tests.rb +282 -0
- data/test/rscm/line_editor_test.rb +76 -0
- data/test/rscm/mockit.rb +130 -0
- data/test/rscm/mockit_test.rb +117 -0
- data/test/rscm/monotone/monotone_test.rb +19 -0
- data/test/rscm/mooky/mooky_test.rb +14 -0
- data/test/rscm/parser_test.rb +47 -0
- data/test/rscm/path_converter_test.rb +52 -0
- data/test/rscm/perforce/perforce_test.rb +14 -0
- data/test/rscm/starteam/starteam_test.rb +36 -0
- data/test/rscm/svn/svn_log_parser_test.rb +111 -0
- data/test/rscm/svn/svn_test.rb +28 -0
- data/test/rscm/tempdir.rb +12 -0
- 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
|