Class: RSCM::Accurev::API
- Inherits:
-
Base
- Object
- Base
- RSCM::Accurev::API
- Defined in:
- lib/rscm/scm/accurev/api.rb
Overview
RSCM implementation for Accurev (www.accurev.com).
Requires an accurev cli executable on the path (see also RSCM::Accurev::Command), and the correct environment configuration for ac server/principal/password.
Example
# Checkout a new workspace:
api = RSCM::Accurev::API.new( "./ws/proj-1", "proj", "proj-1" )
api.checkout() each do |file|
puts "Updated #{file}..."
end
# Checkout a new (read-only) stream:
api = RSCM::Accurev::API.new( "./ws/proj-1", "proj" )
api.checkout() each {|f| ...}
# Update a checked-out workspace or copy:
api = RSCM::Accurev::API.new( "./ws/proj-1" )
api.checkout() each{|f| ... }
Constant Summary collapse
- STATUSES =
status flag mappings for “stat”, “file” commands
{ '(backed)' => :backed, '(external)' => :external, '(modified)' => :modified, '(kept)' => :kept, '(defunct)' => :defunct, '(missing)' => :missing, '(stranded)' => :stranded, '(overlap)' => :overlap }
Instance Attribute Summary collapse
-
#backing_stream ⇒ Object
Returns the value of attribute backing_stream.
-
#depot ⇒ Object
Returns the value of attribute depot.
-
#overwrite ⇒ Object
Returns the value of attribute overwrite.
-
#workspace_stream ⇒ Object
Returns the value of attribute workspace_stream.
Instance Method Summary collapse
-
#ac_files(relative_path) ⇒ Object
remember: ac_files is non-recursive.
-
#ac_hist(from, to = Time.infinite) ⇒ Object
yeilds the TransactionData objects for the given time period (promotes only).
-
#ac_info ⇒ Object
Performs an “accurev info” command in the workspace.
- #ac_keep(files = [], message = "") ⇒ Object
- #ac_move(current_file, new_file) ⇒ Object
- #ac_promote(files = [], message = "") ⇒ Object
- #ac_purge(files = []) ⇒ Object
- #ac_revert(files = []) ⇒ Object
- #ac_stat(flag = "-a") ⇒ Object
- #ac_update(relative_path = ".") ⇒ Object
-
#add(relative_filename) ⇒ Object
“Adds
relative_filename
to the working copy.”. -
#attempt_init_from_info ⇒ Object
Runs an ‘ac info` command in @checkout_dir, and tries to set @backing_stream and @workspace_stream from the output.
-
#checkout(to_identifier = Time.infinite) ⇒ Object
“Checks out or updates contents from a central SCM to
checkout_dir
- a local working copy.”. - #checkout_pop ⇒ Object
- #checkout_workspace ⇒ Object
-
#co_filepath ⇒ Object
psuedo-accessor (cached).
- #edit(relative_filename) ⇒ Object
-
#initialize(checkout_dir = nil, backing_stream = nil, workspace_stream = nil) ⇒ API
constructor
A new instance of API.
-
#map_status(status_line) ⇒ Object
Takes a status flags line (eg, “(modified)(kept)”) and returns a list of status flags.
- #name ⇒ Object
-
#revisions(from_identifier, to_identifier = Time.infinity) ⇒ Object
“Returns a Revisions object for the period specified …
-
#supports_trigger? ⇒ Boolean
accurev actually does have triggers, but I haven’t implemented that yet.
-
#transactional? ⇒ Boolean
Accurev operations are atomic: returns true.
-
#update(to_identifier = Time.infinite) ⇒ Object
Updates an existing workspace stream checked out to @checkout_dir.
Constructor Details
#initialize(checkout_dir = nil, backing_stream = nil, workspace_stream = nil) ⇒ API
Returns a new instance of API.
72 73 74 75 76 77 78 |
# File 'lib/rscm/scm/accurev/api.rb', line 72 def initialize(checkout_dir=nil, backing_stream=nil, workspace_stream=nil) @depot = nil # will be pulled from files cmd output @workspace_stream = workspace_stream @backing_stream = backing_stream @checkout_dir = checkout_dir @overwrite = false end |
Instance Attribute Details
#backing_stream ⇒ Object
Returns the value of attribute backing_stream.
57 58 59 |
# File 'lib/rscm/scm/accurev/api.rb', line 57 def backing_stream @backing_stream end |
#depot ⇒ Object
Returns the value of attribute depot.
54 55 56 |
# File 'lib/rscm/scm/accurev/api.rb', line 54 def depot @depot end |
#overwrite ⇒ Object
Returns the value of attribute overwrite.
70 71 72 |
# File 'lib/rscm/scm/accurev/api.rb', line 70 def overwrite @overwrite end |
#workspace_stream ⇒ Object
Returns the value of attribute workspace_stream.
63 64 65 |
# File 'lib/rscm/scm/accurev/api.rb', line 63 def workspace_stream @workspace_stream end |
Instance Method Details
#ac_files(relative_path) ⇒ Object
remember: ac_files is non-recursive
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 |
# File 'lib/rscm/scm/accurev/api.rb', line 143 def ac_files( relative_path ) cmd = Command.instance ret = [] with_working_dir( co_filepath ) do acresponse = cmd.accurev( "files", relative_path ) if acresponse['element'].nil? return [] end acresponse['element'].each do |fd| yield fd if block_given? ret << fd end end return ret end |
#ac_hist(from, to = Time.infinite) ⇒ Object
yeilds the TransactionData objects for the given time period (promotes only)
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 |
# File 'lib/rscm/scm/accurev/api.rb', line 175 def ac_hist( from, to=Time.infinite ) cmd = Command.instance lower = from.to_accurev upper = "now" unless to == Time.infinite upper = to.to_accurev end with_working_dir( self.co_filepath ) do acresponse = cmd.accurev( "hist", "-t", "'#{upper}-#{lower}'", "-k", "promote" ) ret = [] acresponse['transaction'].each do |txn| ret << txn yield txn if block_given? end return ret end end |
#ac_info ⇒ Object
Performs an “accurev info” command in the workspace. Returns a map of
ac info: shows eg, backing stream but doesn’t support -fx!
230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 |
# File 'lib/rscm/scm/accurev/api.rb', line 230 def ac_info() co = RSCM::PathConverter.nativepath_to_filepath( @checkout_dir ) unless File.exists?( co ) raise AccurevException.new( "Checkout dir #{co} does not exist" ) end info = {} with_working_dir( co ) do cmd = Command.instance io = StringIO.new( cmd.accurev_nofx( "info" ) ) io.each_line do |line| next unless line =~ /\S/ if line =~ /^(.*?):\s+(.*)$/ info[$1] = $2 end end end return info end |
#ac_keep(files = [], message = "") ⇒ Object
196 197 198 |
# File 'lib/rscm/scm/accurev/api.rb', line 196 def ac_keep( files=[], ="" ) raise "XXX implement me" end |
#ac_move(current_file, new_file) ⇒ Object
219 220 221 |
# File 'lib/rscm/scm/accurev/api.rb', line 219 def ac_move( current_file, new_file ) raise "XXX implement me" end |
#ac_promote(files = [], message = "") ⇒ Object
200 201 202 |
# File 'lib/rscm/scm/accurev/api.rb', line 200 def ac_promote( files=[], ="" ) raise "XXX implement me" end |
#ac_purge(files = []) ⇒ Object
211 212 213 |
# File 'lib/rscm/scm/accurev/api.rb', line 211 def ac_purge( files=[] ) raise "XXX implement me" end |
#ac_revert(files = []) ⇒ Object
215 216 217 |
# File 'lib/rscm/scm/accurev/api.rb', line 215 def ac_revert( files=[] ) raise "XXX implement me" end |
#ac_stat(flag = "-a") ⇒ Object
159 160 161 162 163 164 165 166 167 168 169 170 171 |
# File 'lib/rscm/scm/accurev/api.rb', line 159 def ac_stat( flag="-a" ) cmd = Command.instance ret = [] with_working_dir( co_filepath ) do acresponse = cmd.accurev( "stat", flag ) return [] if acresponse['element'].nil? acresponse['element'].each do |fd| yield fd if block_given? ret << fd end end return ret end |
#ac_update(relative_path = ".") ⇒ Object
204 205 206 207 208 209 |
# File 'lib/rscm/scm/accurev/api.rb', line 204 def ac_update( relative_path="." ) d = accurev( "update", relative_path ) if xxx_error_stale raise StaleWorkspaceError.new( "#{relative_path} is stale -- keep/anchor all changes and re-update" ) end end |
#add(relative_filename) ⇒ Object
“Adds relative_filename
to the working copy.”
90 91 92 |
# File 'lib/rscm/scm/accurev/api.rb', line 90 def add( relative_filename ) raise "XXX implement me" end |
#attempt_init_from_info ⇒ Object
Runs an ‘ac info` command in @checkout_dir, and tries to set @backing_stream and @workspace_stream from the output.
399 400 401 402 403 404 405 406 407 408 409 |
# File 'lib/rscm/scm/accurev/api.rb', line 399 def attempt_init_from_info() if File.exists?( self.co_filepath ) info = self.ac_info if info.has_key?( "Basis" ) @backing_stream = info["Basis"] end if info.has_key?( "ws/ref" ) @workspace_stream = info["ws/ref"] end end end |
#checkout(to_identifier = Time.infinite) ⇒ Object
“Checks out or updates contents from a central SCM to checkout_dir
- a local working copy.”
“The to_identifier
parameter may be optionally specified to obtain files up to a particular time or label.”
For accurev, this:
-
checks to see if @checkout_dir exists and appears checked out. If it’s already checked out, this calls update(). If @checkout_dir exists and
to_identifier
is given, an exception is raised. -
otherwise, this creates a new workspace stream and populates it at @checkout_dir.
This both returns and yields a list of updated files. Only updated files are returned, not directories.
Current, ac_update returns both files and directories, including deleted files.
270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 |
# File 'lib/rscm/scm/accurev/api.rb', line 270 def checkout( to_identifier=Time.infinite ) co = RSCM::PathConverter.nativepath_to_filepath( @checkout_dir ) if @backing_stream.nil? self.attempt_init_from_info() end if @workspace_stream.nil? self.checkout_pop() else unless File.exists?( co ) # create new workspace self.checkout_workspace() end # update workspace self.update( to_identifier ) end end |
#checkout_pop ⇒ Object
287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 |
# File 'lib/rscm/scm/accurev/api.rb', line 287 def checkout_pop() co = RSCM::PathConverter.nativepath_to_filepath( @checkout_dir ) raise "A backing stream is required" if @backing_stream.nil? raise "A working stream may not be given" unless @working_stream.nil? # for `accurev pop`: remove and re-pop the checkout copy if File.exists?( co ) unless @overwrite raise "Checkout dir #{co} already exists (@overwrite=#@overwrite)" end rm_rf( co ) end mkdir(co) with_working_dir( co ) do cmd = Command.instance pop_out = cmd.accurev_nofx("pop", "-R", "-v", @backing_stream, "-L", ".", ".") elems = [] popio = StringIO.new( pop_out ) popio.each_line do |line| if line =~ /^Populating element \/.\/(.*)$/ loc = $1 elems << loc yield loc if block_given? end end return elems end end |
#checkout_workspace ⇒ Object
318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 |
# File 'lib/rscm/scm/accurev/api.rb', line 318 def checkout_workspace() co = RSCM::PathConverter.nativepath_to_filepath( @checkout_dir ) raise "A backing stream is required" if @backing_stream.nil? raise "A workspace is required" if @working_stream.nil? if File.exist?( co ) and !@overwrite raise "Checkout dir #{co} already exists (@overwrite=#@overwrite)" end cmd = Command.instance mkws_out = cmd.accurev_nofx( "mkws", "-b", @backing_stream, "-w", @workspace_stream, "-l", co ) # kinda sucks: if ( mkws_out =~ /already exists/ ) raise AccurevException.new( "Failed to checkout", mkws_out ) end end |
#co_filepath ⇒ Object
psuedo-accessor (cached)
388 389 390 391 392 393 |
# File 'lib/rscm/scm/accurev/api.rb', line 388 def co_filepath if @co_filepath.nil? @co_filepath = RSCM::PathConverter.nativepath_to_filepath( @checkout_dir ) end return @co_filepath end |
#edit(relative_filename) ⇒ Object
94 95 96 |
# File 'lib/rscm/scm/accurev/api.rb', line 94 def edit( relative_filename ) # NOP - not required for ac end |
#map_status(status_line) ⇒ Object
Takes a status flags line (eg, “(modified)(kept)”) and returns a list of status flags.
413 414 415 |
# File 'lib/rscm/scm/accurev/api.rb', line 413 def map_status( status_line ) l = status_line.split( " " ).map {|x| x.trim} end |
#name ⇒ Object
80 81 82 |
# File 'lib/rscm/scm/accurev/api.rb', line 80 def name() return "Accurev" end |
#revisions(from_identifier, to_identifier = Time.infinity) ⇒ Object
“Returns a Revisions object for the period specified … (inclusive).”
list txns (promotes to bs) from hist within the period
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 |
# File 'lib/rscm/scm/accurev/api.rb', line 102 def revisions( from_identifier, to_identifier=Time.infinity ) revisions = RSCM::Revisions.new() self.ac_hist( from_identifier, to_identifier ).each do |txn| txnrev = RSCM::Revision.new txnrev.identifier = txn.id txnrev.developer = txn.user txnrev. = txn['comment'].join("\n") unless txn['comment'].nil? txnrev.time = Time.at( txn.time.to_i ) txn['version'].each do |v| f = RSCM::RevisionFile.new() f.path = v.path # i think to get real status, you'd need to analyze keep txns f.status = RSCM::RevisionFile::MODIFIED # XXX? txn.type==promote here f.developer = txn.user f.native_revision_identifier = v.real # XXX or .virtual? f.time = Time.at( txn.time.to_i ) txnrev << f end revisions.add( txnrev ) end return revisions end |
#supports_trigger? ⇒ Boolean
accurev actually does have triggers, but I haven’t implemented that yet
133 134 135 |
# File 'lib/rscm/scm/accurev/api.rb', line 133 def supports_trigger? false end |
#transactional? ⇒ Boolean
Accurev operations are atomic: returns true.
85 86 87 |
# File 'lib/rscm/scm/accurev/api.rb', line 85 def transactional? return true end |
#update(to_identifier = Time.infinite) ⇒ Object
Updates an existing workspace stream checked out to @checkout_dir
339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 |
# File 'lib/rscm/scm/accurev/api.rb', line 339 def update( to_identifier=Time.infinite ) co = RSCM::PathConverter.nativepath_to_filepath( @checkout_dir ) unless File.exists?( co ) raise AccurevException.new( "Workspace does not exist!" ) end updated = [] with_working_dir( co ) do cmd = Command.instance acresponse = cmd.accurev( "update" ) if acresponse.error if acresponse.error =~ /workspace have been modified/ raise StaleWorkspaceException.new( "Workspace stale", acresponse.error ) else # some other update problem raise AccurevException.new( "Error on update", acresponse.error ) end end if acresponse['element'] acresponse['element'].each do |up| # "ac update" on a new workspace yields element locations # with leading "/"s, which should be removed to get a proper # relative path: loc = up.location.sub( /^\//, "" ) yield loc if block_given? updated << loc end end end return updated end |