rscm 0.3.6 → 0.3.7
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/CHANGES +7 -0
- data/README +1 -1
- data/Rakefile +1 -1
- data/lib/rscm/revision_poller.rb +77 -0
- data/lib/rscm/scm/clearcase.rb +154 -76
- data/lib/rscm/scm/monotone.rb +1 -1
- data/lib/rscm/scm/subversion.rb +2 -7
- data/lib/rscm.rb +1 -0
- data/test/rscm/base_test.rb +2 -1
- metadata +4 -3
data/CHANGES
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
= RSCM Changelog
|
2
2
|
|
3
|
+
== Version 0.3.7
|
4
|
+
|
5
|
+
This release improves polling of revisions (changesets) and improves ClearCase support
|
6
|
+
|
7
|
+
* Added RSCM.Base.poll_new_revisions (moved from DamageControl)
|
8
|
+
* Rewrote the ClearCase adapter. There are no tests for ClearCase yet - tested manually.
|
9
|
+
|
3
10
|
== Version 0.3.6
|
4
11
|
|
5
12
|
Bugfix release
|
data/README
CHANGED
data/Rakefile
CHANGED
@@ -0,0 +1,77 @@
|
|
1
|
+
module RSCM
|
2
|
+
class Base
|
3
|
+
attr_accessor :logger
|
4
|
+
|
5
|
+
TWO_WEEKS_AGO = 2*7*24*60*60
|
6
|
+
THIRTY_TWO_WEEKS_AGO = TWO_WEEKS_AGO * 16
|
7
|
+
|
8
|
+
# Polls new revisions for since +last_revision+,
|
9
|
+
# or if +last_revision+ is nil, polls since 'now' - +seconds_before_now+.
|
10
|
+
# If no revisions are found AND the poll was using +seconds_before_now+
|
11
|
+
# (i.e. it's the first poll, and no revisions were found),
|
12
|
+
# calls itself recursively with twice the +seconds_before_now+.
|
13
|
+
# This happens until revisions are found, ot until the +seconds_before_now+
|
14
|
+
# Exceeds 32 weeks, which means it's probably not worth looking further in
|
15
|
+
# the past, the scm is either completely idle or not yet active.
|
16
|
+
def poll_new_revisions(latest_revision=nil, seconds_before_now=TWO_WEEKS_AGO, max_time_before_now=THIRTY_TWO_WEEKS_AGO)
|
17
|
+
max_past = Time.new.utc - max_time_before_now
|
18
|
+
|
19
|
+
if(!central_exists?)
|
20
|
+
logger.info "Not polling for revisions - central scm repo doesn't seem to exist" if logger
|
21
|
+
return []
|
22
|
+
end
|
23
|
+
|
24
|
+
# Default value for start time (in case there are no detected revisions yet)
|
25
|
+
from = Time.new.utc - seconds_before_now
|
26
|
+
if(latest_revision)
|
27
|
+
from = latest_revision.identifier
|
28
|
+
else
|
29
|
+
if(from < max_past)
|
30
|
+
logger.info "Checked for revisions as far back as #{max_past}. There were none, so we give up." if logger
|
31
|
+
return []
|
32
|
+
else
|
33
|
+
logger.info "Latest revision is not known. Checking for revisions since: #{from}" if logger
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
logger.info "Polling revisions after #{from} (#{from.class.name})" if logger
|
38
|
+
|
39
|
+
revisions = revisions(from)
|
40
|
+
if(revisions.empty?)
|
41
|
+
logger.info "No new revisions after #{from}" if logger
|
42
|
+
unless(latest_revision)
|
43
|
+
double_seconds_before_now = 2*seconds_before_now
|
44
|
+
logger.info "Last revision still not found, checking since #{double_seconds_before_now.ago}" if logger
|
45
|
+
return poll_new_revisions(project, double_seconds_before_now, max_time_before_now)
|
46
|
+
end
|
47
|
+
else
|
48
|
+
logger.info "There were #{revisions.length} new revision(s) after #{from}" if logger
|
49
|
+
end
|
50
|
+
|
51
|
+
if(!revisions.empty? && !transactional?)
|
52
|
+
# We're dealing with a non-transactional SCM (like CVS/StarTeam/ClearCase,
|
53
|
+
# unlike Subversion/Monotone). Sleep a little, get the revisions again.
|
54
|
+
# When the revisions are not changing, we can consider the last commit done
|
55
|
+
# and the quiet period elapsed. This is not 100% failsafe, but will work
|
56
|
+
# under most circumstances. In the worst case, we'll miss some files in
|
57
|
+
# the revisions for really slow commits, but they will be part of the next
|
58
|
+
# revision (on next poll).
|
59
|
+
commit_in_progress = true
|
60
|
+
quiet_period = project.quiet_period || DEFAULT_QUIET_PERIOD
|
61
|
+
while(commit_in_progress)
|
62
|
+
logger.info "Sleeping for #{quiet_period} seconds because #{visual_name} is not transactional." if logger
|
63
|
+
|
64
|
+
sleep(quiet_period)
|
65
|
+
previous_revisions = revisions
|
66
|
+
revisions = revisions(from)
|
67
|
+
commit_in_progress = revisions != previous_revisions
|
68
|
+
if(commit_in_progress)
|
69
|
+
logger.info "Commit still in progress." if logger
|
70
|
+
end
|
71
|
+
end
|
72
|
+
logger.info "Quiet period elapsed" if logger
|
73
|
+
end
|
74
|
+
return revisions
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
data/lib/rscm/scm/clearcase.rb
CHANGED
@@ -1,81 +1,159 @@
|
|
1
1
|
require 'rscm/base'
|
2
2
|
require 'rscm/path_converter'
|
3
3
|
require 'fileutils'
|
4
|
+
require 'tempfile'
|
4
5
|
|
5
6
|
module RSCM
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
7
|
+
class ClearCase < Base
|
8
|
+
register self
|
9
|
+
|
10
|
+
LOG_FORMAT = "- !ruby/object:RSCM::RevisionFile\\n developer: %u\\n time: \\\"%Nd\\\"\\n native_revision_identifier: %Vn\\n previous_native_revision_identifier: %PVn\\n path: %En\\n status: %o\\n message: \\\"%Nc\\\"\\n\\n"
|
11
|
+
TIME_FORMAT = "%d-%b-%Y.%H:%M:%S"
|
12
|
+
MAGIC = "9q8w7e6r5t4y"
|
13
|
+
STATUSES = {
|
14
|
+
"checkin" => RevisionFile::MODIFIED,
|
15
|
+
"mkelem" => RevisionFile::ADDED,
|
16
|
+
"rmelem" => RevisionFile::DELETED,
|
17
|
+
}
|
18
|
+
|
19
|
+
attr_accessor :stream, :stgloc, :tag, :config_spec
|
20
|
+
|
21
|
+
def initialize(stream, stgloc, tag, config_spec)
|
22
|
+
@stream, @stgloc, @tag, @config_spec = stream, stgloc, tag, config_spec
|
23
|
+
end
|
24
|
+
|
25
|
+
def revisions(from_identifier, to_identifier=Time.infinity, relative_path=nil)
|
26
|
+
checkout unless checked_out?
|
27
|
+
|
28
|
+
rules = load_rules
|
29
|
+
vob = vob(rules[0])
|
30
|
+
|
31
|
+
result = Revisions.new
|
32
|
+
with_working_dir(checkout_dir) do
|
33
|
+
since = (from_identifier + 1).strftime(TIME_FORMAT)
|
34
|
+
cmd = "cleartool lshistory -recurse -nco -since #{since} -fmt \"#{LOG_FORMAT}\" -pname #{vob}"
|
35
|
+
Better.popen(cmd) do |io|
|
36
|
+
# escape all quotes, except the one at the beginning and end. this is a bit ugly...
|
37
|
+
raw_yaml = io.read
|
38
|
+
fixed_yaml = raw_yaml.gsub(/^ message: \"/, " message: #{MAGIC}")
|
39
|
+
fixed_yaml = fixed_yaml.gsub(/\"\n\n/, "#{MAGIC}\n\n")
|
40
|
+
fixed_yaml = fixed_yaml.gsub(/\"/, "\\\"")
|
41
|
+
fixed_yaml = fixed_yaml.gsub(MAGIC, "\"")
|
42
|
+
|
43
|
+
files = YAML.load(fixed_yaml)
|
44
|
+
files.each do |file|
|
45
|
+
file.path.gsub!(/\\/, "/")
|
46
|
+
file.status = STATUSES[file.status]
|
47
|
+
rev = revision(file.native_revision_identifier)
|
48
|
+
if(rev && matches_load_rules?(rules, file.path))
|
49
|
+
file.native_revision_identifier = rev
|
50
|
+
file.previous_native_revision_identifier = revision(file.previous_native_revision_identifier)
|
51
|
+
t = file.time
|
52
|
+
# the time now has escaped quotes..
|
53
|
+
file.time = Time.utc(t[2..5],t[6..7],t[8..9],t[11..12],t[13..14],t[15..16])
|
54
|
+
file.message.strip!
|
55
|
+
result.add(file)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
result
|
61
|
+
end
|
62
|
+
|
63
|
+
def checked_out?
|
64
|
+
File.exist?(checkout_dir)
|
65
|
+
end
|
66
|
+
|
67
|
+
def destroy_working_copy
|
68
|
+
Better.popen("cleartool rmview #{checkout_dir}") do |io|
|
69
|
+
io.read
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
protected
|
74
|
+
|
75
|
+
def checkout_silent(to_identifier=nil)
|
76
|
+
if(checked_out?)
|
77
|
+
with_working_dir(checkout_dir) do
|
78
|
+
Better.popen("cleartool update .") do |io|
|
79
|
+
io.read
|
80
|
+
end
|
81
|
+
end
|
82
|
+
else
|
83
|
+
# Create view (working copy)
|
84
|
+
mkview_cmd = "cleartool mkview -snapshot -stream #{@stream} -stgloc #{@stgloc} -tag #{@tag} #{@checkout_dir}"
|
85
|
+
Better.popen(mkview_cmd) do |io|
|
86
|
+
puts io.read
|
87
|
+
end
|
88
|
+
|
89
|
+
# Set load rules (by setting config spec)
|
90
|
+
Dir.chdir(checkout_dir) do
|
91
|
+
# tempfile is broken on windows (!!)
|
92
|
+
cfg_spec_file = "__rscm.cfgspec"
|
93
|
+
config_spec_file = File.open(cfg_spec_file, "w") do |io|
|
94
|
+
io.write(@config_spec)
|
95
|
+
end
|
96
|
+
|
97
|
+
setcs_cmd = "cleartool setcs #{cfg_spec_file}"
|
98
|
+
Better.popen(setcs_cmd, "w") do |io|
|
99
|
+
io.write "yes\n"
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
# Administrative files that should be ignored when counting files.
|
106
|
+
def ignore_paths
|
107
|
+
return [/.*\.updt/]
|
108
|
+
end
|
109
|
+
|
110
|
+
private
|
111
|
+
|
112
|
+
def vob(rule)
|
113
|
+
if(rule =~ /[\\\/]*([\w]*)/)
|
114
|
+
$1
|
115
|
+
else
|
116
|
+
nil
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
# What's loaded into view
|
121
|
+
def load_rules
|
122
|
+
result = []
|
123
|
+
config_spec do |io|
|
124
|
+
io.each_line do |line|
|
125
|
+
if(line =~ /^load[\s]*(.*)$/)
|
126
|
+
return result << $1
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
result
|
131
|
+
end
|
132
|
+
|
133
|
+
def config_spec
|
134
|
+
Dir.chdir(checkout_dir) do
|
135
|
+
catcs_cmd = "cleartool catcs"
|
136
|
+
Better.popen(catcs_cmd) do |io|
|
137
|
+
yield io
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def revision(s)
|
143
|
+
if(s =~ /.*\\([\d]*)/)
|
144
|
+
$1.to_i
|
145
|
+
else
|
146
|
+
nil
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def matches_load_rules?(rules, path)
|
151
|
+
rules.each do |rule|
|
152
|
+
rule.gsub!(/\\/, "/")
|
153
|
+
return true if path =~ /#{rule[1..-1]}/
|
154
|
+
end
|
155
|
+
false
|
156
|
+
end
|
157
|
+
|
158
|
+
end
|
159
|
+
end
|
data/lib/rscm/scm/monotone.rb
CHANGED
data/lib/rscm/scm/subversion.rb
CHANGED
@@ -76,13 +76,8 @@ module RSCM
|
|
76
76
|
absolute_path = PathConverter.nativepath_to_filepath(native_absolute_path)
|
77
77
|
if(File.exist?(absolute_path) && !File.directory?(absolute_path))
|
78
78
|
native_checkout_dir = PathConverter.filepath_to_nativepath(@checkout_dir, false)
|
79
|
-
relative_path =
|
80
|
-
|
81
|
-
relative_path = native_absolute_path[native_checkout_dir.length+1..-1].chomp
|
82
|
-
relative_path = relative_path.gsub(/\\/, "/")
|
83
|
-
else
|
84
|
-
relative_path = absolute_path
|
85
|
-
end
|
79
|
+
relative_path = native_absolute_path[native_checkout_dir.length+1..-1].chomp
|
80
|
+
relative_path = relative_path.gsub(/\\/, "/")
|
86
81
|
checked_out_files << relative_path
|
87
82
|
yield relative_path if block_given?
|
88
83
|
end
|
data/lib/rscm.rb
CHANGED
data/test/rscm/base_test.rb
CHANGED
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.8.11
|
|
3
3
|
specification_version: 1
|
4
4
|
name: rscm
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.3.
|
7
|
-
date: 2005-10-
|
6
|
+
version: 0.3.7
|
7
|
+
date: 2005-10-11 00:00:00 -04:00
|
8
8
|
summary: "RSCM - Ruby Source Control Management"
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -47,6 +47,7 @@ files:
|
|
47
47
|
- lib/rscm/path_converter.rb
|
48
48
|
- lib/rscm/revision.rb
|
49
49
|
- lib/rscm/revision_file.rb
|
50
|
+
- lib/rscm/revision_poller.rb
|
50
51
|
- lib/rscm/scm
|
51
52
|
- lib/rscm/tempdir.rb
|
52
53
|
- lib/rscm/time_ext.rb
|
@@ -78,9 +79,9 @@ files:
|
|
78
79
|
- test/rscm/mockit_test.rb
|
79
80
|
- test/rscm/parser_test.rb
|
80
81
|
- test/rscm/path_converter_test.rb
|
81
|
-
- test/rscm/revisions.yaml
|
82
82
|
- test/rscm/revision_fixture.rb
|
83
83
|
- test/rscm/revision_test.rb
|
84
|
+
- test/rscm/revisions.yaml
|
84
85
|
- test/rscm/scm
|
85
86
|
- test/rscm/scm/clearcase.log
|
86
87
|
- test/rscm/scm/clearcase_test.rb
|