rscm 0.3.8 → 0.3.9

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 CHANGED
@@ -1,5 +1,13 @@
1
1
  = RSCM Changelog
2
2
 
3
+ == Version 0.3.9
4
+
5
+ This release improves Subversion and ClearCase support
6
+
7
+ * Subversion no longer needs a working copy to get revisions and diffs
8
+ * Misc. ClearCase improvements
9
+ * Added RSCM::Base.destroy_working_copy
10
+
3
11
  == Version 0.3.8
4
12
 
5
13
  Bugfix release
data/README CHANGED
@@ -1,4 +1,4 @@
1
- = RSCM - Ruby Source Control Management (0.3.8)
1
+ = RSCM - Ruby Source Control Management (0.3.9)
2
2
 
3
3
  RSCM is to SCM what DBI/JDBC/ODBC are to databases - an SCM-independent API for accessing different SCMs. The features are roughly:
4
4
 
@@ -31,12 +31,12 @@ If you want the latest and greatest, you can get the sources, which live alongsi
31
31
 
32
32
  == Supported SCMs
33
33
 
34
- * CVS - http://www.cvshome.org (stable)
34
+ * CVS - http://www.nongnu.org/cvs (stable)
35
35
  * Subversion - http://subversion.tigris.org (stable)
36
+ * ClearCase - http://www-306.ibm.com/software/awdtools/clearcase (not thoroughly tested)
36
37
 
37
38
  In progress:
38
39
 
39
- * ClearCase -http://www-306.ibm.com/software/awdtools/clearcase (half complete)
40
40
  * Darcs - http://www.abridgegame.org/darcs (very incomplete)
41
41
  * Monotone - http://www.venge.net/monotone (half complete)
42
42
  * Perforce - http://www.perforce.com (nearly complete - a little out of date with recent API)
data/Rakefile CHANGED
@@ -10,7 +10,7 @@ require 'meta_project'
10
10
 
11
11
  PKG_BUILD = ENV['PKG_BUILD'] ? '.' + ENV['PKG_BUILD'] : ''
12
12
  PKG_NAME = 'rscm'
13
- PKG_VERSION = '0.3.8' + PKG_BUILD
13
+ PKG_VERSION = '0.3.9' + PKG_BUILD
14
14
  PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
15
15
 
16
16
  desc "Default Task"
data/lib/rscm/base.rb CHANGED
@@ -21,6 +21,7 @@ module RSCM
21
21
  # * revisions
22
22
  # * uptodate?
23
23
  # * file
24
+ # * destroy_working_copy
24
25
  #
25
26
  # In addition to operations related to working copies, the same instance should provide
26
27
  # methods to administer the working copy's associated 'central' repository. These are:
@@ -92,6 +93,11 @@ module RSCM
92
93
  props.sort!
93
94
  end
94
95
 
96
+ # Destroys the working copy
97
+ def destroy_working_copy
98
+ FileUtils.rm_rf(checkout_dir) unless checkout_dir.nil?
99
+ end
100
+
95
101
  # Whether the physical SCM represented by this instance exists.
96
102
  #
97
103
  def central_exists?
@@ -4,156 +4,176 @@ require 'fileutils'
4
4
  require 'tempfile'
5
5
 
6
6
  module RSCM
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=nil, stgloc=nil, tag=nil, config_spec=nil)
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
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_TOKEN = "9q8w7e6r5t4y"
13
+ STATUSES = {
14
+ "checkin" => RevisionFile::MODIFIED,
15
+ "mkelem" => RevisionFile::ADDED,
16
+ "rmelem" => RevisionFile::DELETED,
17
+ }
18
+ DEFAULT_CONFIG_SPEC = "element * CHECKEDOUT\nelement * /main/LATEST"
19
+
20
+ attr_accessor :stream, :stgloc, :tag, :config_spec
21
+
22
+ def initialize(stream=nil, stgloc=nil, tag=nil, config_spec=DEFAULT_CONFIG_SPEC)
23
+ @stream, @stgloc, @tag, @config_spec = stream, stgloc, tag, config_spec
24
+ end
25
+
26
+ def revisions(from_identifier, to_identifier=Time.infinity, relative_path=nil)
27
+ checkout unless checked_out?
28
+ rules = load_rules
29
+ vob = vob(rules[0])
30
+ result = Revisions.new
31
+
32
+ unless vob
33
+ STDERR.puts "No vob found. Please set load rules in the view: #{checkout_dir}"
34
+ return result
35
+ end
36
+ with_working_dir(checkout_dir) do
37
+ since = (from_identifier + 1).strftime(TIME_FORMAT)
38
+ cmd = "cleartool lshistory -recurse -nco -since #{since} -fmt \"#{LOG_FORMAT}\" -pname #{vob}"
39
+ Better.popen(cmd) do |io|
40
+ # escape all quotes, except the one at the beginning and end. this is a bit ugly...
41
+ raw_yaml = io.read
42
+ fixed_yaml = raw_yaml.gsub(/^ message: \"/, " message: #{MAGIC_TOKEN}")
43
+ fixed_yaml = fixed_yaml.gsub(/\"\n\n/, "#{MAGIC_TOKEN}\n\n")
44
+ fixed_yaml = fixed_yaml.gsub(/\"/, "\\\"")
45
+ fixed_yaml = fixed_yaml.gsub(MAGIC_TOKEN, "\"")
46
+
47
+ files = YAML.load(fixed_yaml)
48
+ files.each do |file|
49
+ file.path.gsub!(/\\/, "/")
50
+ file.status = STATUSES[file.status]
51
+ rev = revision(file.native_revision_identifier)
52
+ if(rev && matches_load_rules?(rules, file.path))
53
+ file.native_revision_identifier = rev
54
+ file.previous_native_revision_identifier = revision(file.previous_native_revision_identifier)
55
+ t = file.time
56
+ # the time now has escaped quotes..
57
+ file.time = Time.utc(t[2..5],t[6..7],t[8..9],t[11..12],t[13..14],t[15..16])
58
+ file.message.strip!
59
+ result.add(file)
60
+ end
61
+ end
62
+ end
63
+ end
64
+ result
65
+ end
66
+
67
+ def checked_out?
68
+ !Dir["#{checkout_dir}/*"].empty?
69
+ end
70
+
71
+ def destroy_working_copy
72
+ Better.popen("cleartool rmview #{checkout_dir}") do |io|
73
+ io.read
74
+ end
75
+ end
76
+
77
+ def import_central(dir, message)
78
+ Better.popen("clearfsimport -recurse -nsetevent #{dir} #{checkout_dir}") do |io|
79
+ io.read
80
+ end
81
+ end
82
+
83
+ ## Non-RSCM API methods
84
+
85
+ def mkview!
83
86
  # Create view (working copy)
84
87
  mkview_cmd = "cleartool mkview -snapshot -stream #{@stream} -stgloc #{@stgloc} -tag #{@tag} #{@checkout_dir}"
85
88
  Better.popen(mkview_cmd) do |io|
86
89
  puts io.read
87
90
  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
91
+ end
92
+
93
+ def update_load_rules!
94
+ Dir.chdir(checkout_dir) do
95
+ # tempfile is broken on windows (!!)
96
+ cfg_spec_file = "__rscm.cfgspec"
97
+ config_spec_file = File.open(cfg_spec_file, "w") do |io|
98
+ io.write(@config_spec)
99
+ end
100
+
101
+ setcs_cmd = "cleartool setcs #{cfg_spec_file}"
102
+ Better.popen(setcs_cmd, "w") do |io|
103
+ io.write "yes\n"
104
+ end
105
+ end
106
+ end
107
+
108
+ def catcs
109
+ Dir.chdir(checkout_dir) do
110
+ catcs_cmd = "cleartool catcs"
111
+ Better.popen(catcs_cmd) do |io|
112
+ yield io
113
+ end
114
+ end
115
+ end
116
+
117
+ def vob(load_rule)
118
+ if(load_rule =~ /[\\\/]*([\w]*)/)
119
+ $1
120
+ else
121
+ nil
122
+ end
123
+ end
124
+
125
+ # What's loaded into view
126
+ def load_rules
127
+ result = []
128
+ catcs do |io|
129
+ io.each_line do |line|
130
+ if(line =~ /^load[\s]*(.*)$/)
131
+ return result << $1
132
+ end
133
+ end
134
+ end
135
+ result
136
+ end
137
+
138
+ protected
139
+
140
+ def checkout_silent(to_identifier=nil)
141
+ if(checked_out?)
142
+ with_working_dir(checkout_dir) do
143
+ Better.popen("cleartool update .") do |io|
144
+ io.read
145
+ end
146
+ end
147
+ else
148
+ mkview!
149
+
150
+ # Set load rules (by setting config spec)
151
+ #update_load_rules!
152
+ end
153
+ end
154
+
155
+ # Administrative files that should be ignored when counting files.
156
+ def ignore_paths
157
+ return [/.*\.updt/]
158
+ end
159
+
160
+ private
161
+
162
+ def revision(s)
163
+ if(s =~ /.*\\([\d]*)/)
164
+ $1.to_i
165
+ else
166
+ nil
167
+ end
168
+ end
169
+
170
+ def matches_load_rules?(rules, path)
171
+ rules.each do |rule|
172
+ rule.gsub!(/\\/, "/")
173
+ return true if path =~ /#{rule[1..-1]}/
174
+ end
175
+ false
176
+ end
177
+
178
+ end
159
179
  end
data/lib/rscm/scm/cvs.rb CHANGED
@@ -190,7 +190,11 @@ module RSCM
190
190
  end
191
191
 
192
192
  def destroy_central
193
- FileUtils.rm_rf(path)
193
+ if(File.exist?(path) && local?)
194
+ FileUtils.rm_rf(path)
195
+ else
196
+ raise "Cannot destroy central repository. '#{path}' doesn't exist or central repo isn't local to this machine"
197
+ end
194
198
  end
195
199
 
196
200
  def central_exists?
@@ -107,11 +107,9 @@ module RSCM
107
107
  end
108
108
 
109
109
  def diff(file, &block)
110
- with_working_dir(@checkout_dir) do
111
- cmd = "svn diff --revision #{file.previous_native_revision_identifier}:#{file.native_revision_identifier} \"#{url}/#{file.path}\""
112
- Better.popen(cmd) do |io|
113
- return(yield(io))
114
- end
110
+ cmd = "svn diff --revision #{file.previous_native_revision_identifier}:#{file.native_revision_identifier} \"#{url}/#{file.path}\""
111
+ Better.popen(cmd) do |io|
112
+ return(yield(io))
115
113
  end
116
114
  end
117
115
 
@@ -126,7 +124,11 @@ module RSCM
126
124
  end
127
125
 
128
126
  def destroy_central
129
- FileUtils.rm_rf(svnrootdir)
127
+ if(File.exist?(svnrootdir) && local?)
128
+ FileUtils.rm_rf(svnrootdir)
129
+ else
130
+ raise "Cannot destroy central repository. '#{svnrootdir}' doesn't exist or central repo isn't local to this machine"
131
+ end
130
132
  end
131
133
 
132
134
  def central_exists?
@@ -200,11 +202,9 @@ module RSCM
200
202
  revisions = nil
201
203
  command = "svn #{changes_command(from_identifier, to_identifier, relative_path)}"
202
204
 
203
- with_working_dir(@checkout_dir) do
204
- Better.popen(command) do |stdout|
205
- parser = SubversionLogParser.new(stdout, @url)
206
- revisions = parser.parse_revisions
207
- end
205
+ Better.popen(command) do |stdout|
206
+ parser = SubversionLogParser.new(stdout, @url)
207
+ revisions = parser.parse_revisions
208
208
  end
209
209
  revisions
210
210
  end
@@ -238,12 +238,10 @@ module RSCM
238
238
  # We therefore don't specify it and get the latest revision from the full url instead.
239
239
  # cmd = "svn log #{login_options} #{repourl} -r HEAD"
240
240
  cmd = "svn log #{login_options} #{url}"
241
- with_working_dir(@checkout_dir) do
242
- Better.popen(cmd) do |stdout|
243
- parser = SubversionLogParser.new(stdout, @url)
244
- revisions = parser.parse_revisions
245
- revisions[0].identifier.to_i
246
- end
241
+ Better.popen(cmd) do |stdout|
242
+ parser = SubversionLogParser.new(stdout, @url)
243
+ revisions = parser.parse_revisions
244
+ revisions[0].identifier.to_i
247
245
  end
248
246
  end
249
247
 
@@ -11,10 +11,11 @@ module RSCM
11
11
  def teardown
12
12
  if @scm
13
13
  begin
14
- @scm.destroy_centra
14
+ @scm.destroy_working_copy
15
+ @scm.destroy_central
15
16
  rescue => e
16
17
  # Fails on windows with TortoiseCVS' cvs because of resident cvslock.exe
17
- STDERR.puts "Couldn't destroy central #{@scm.class.name}"
18
+ STDERR.puts "Couldn't destroy central #{@scm.class.name}: #{e.message}"
18
19
  end
19
20
  end
20
21
  end
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.8
7
- date: 2005-10-11 00:00:00 -04:00
6
+ version: 0.3.9
7
+ date: 2005-10-12 00:00:00 -04:00
8
8
  summary: "RSCM - Ruby Source Control Management"
9
9
  require_paths:
10
10
  - lib