Class RSCM::Base
In: lib/rscm/base.rb
Parent: Object

This class defines the RSCM API, which offers access to an SCM working copy as well as a ‘central’ repository.

Concrete subclasses of this class (concrete adapters) implement the integration with the respective SCMs.

Most of the methods take an optional options Hash (named parameters), allowing the following options:

  • :stdout: Path to file name where stdout of SCM operations are written.
  • :stdout: Path to file name where stderr of SCM operations are written.

In stead of specifying the options parameters for every API method, it’s possible to assign default options via the default_options attribute.

Some of the methods in this API use from_identifier and to_identifier. These identifiers can be either a UTC Time (according to the SCM’s clock) or a String or Integer representing a label/revision (according to the SCM’s native label/revision scheme).

If from_identifier or to_identifier are nil they should respectively default to Time.epoch or Time.infinite.


Included Modules



default_options  [W] 
store_revisions_command  [W] 

Public Instance methods


     # File lib/rscm/base.rb, line 258
258:     def ==(other_scm)
259:       return false if self.class != other_scm.class
260:       self.instance_variables.each do |var|
261:         return false if self.instance_eval(var) != other_scm.instance_eval(var)
262:       end
263:       true
264:     end

Adds relative_filename to the working copy.


     # File lib/rscm/base.rb, line 110
110:     def add(relative_filename, options={})
111:       raise NotImplementedError
112:     end

Alias for transactional?

Returns true if the underlying SCM tool is available on this system.


    # File lib/rscm/base.rb, line 40
40:     def available?
41:       raise NotImplementedError
42:     end

Whether a repository can be created.


     # File lib/rscm/base.rb, line 105
105:     def can_create_central?
106:       false
107:     end

Alias for supports_trigger?

Whether or not the SCM represented by this instance exists.


    # File lib/rscm/base.rb, line 73
73:     def central_exists?
74:       # The default implementation assumes yes - override if it can be

75:       # determined programmatically.

76:       true
77:     end

Whether the project is checked out from the central repository or not. Subclasses should override this to check for SCM-specific administrative files if appliccable


     # File lib/rscm/base.rb, line 200
200:     def checked_out?
201:       File.exists?(@checkout_dir)
202:     end


     # File lib/rscm/base.rb, line 163
163:     def checked_out_files
164:       raise "checkout_dir not set" if @checkout_dir.nil?
166:       files = Dir["#{@checkout_dir}/**/*"]
167:       files.delete_if{|file|}
168:       ignore_paths.each do |regex|
169:         files.delete_if{|file| file =~ regex}
170:       end
171:       dir = File.expand_path(@checkout_dir)
172:       files.collect{|file| File.expand_path(file)[dir.length+1..-1]}
173:     end

Checks out or updates contents from a central SCM to checkout_dir - a local working copy. If this is a distributed SCM, this method should create a ‘working copy’ repository if one doesn’t already exist. Then the contents of the central SCM should be pulled into the working copy.

The to_identifier parameter may be optionally specified to obtain files up to a particular time or label. to_identifier should either be a Time (in UTC - according to the clock on the SCM machine) or a String - reprsenting a label or revision.

This method will yield the relative file name of each checked out file, and also return them in an array. Only files, not directories, should be yielded/returned.

This method should be overridden for SCMs that are able to yield checkouts as they happen. For some SCMs this is not possible, or at least very hard. In that case, just override the checkout_silent method instead of this method (should be protected).


     # File lib/rscm/base.rb, line 152
152:     def checkout(to_identifier=Time.infinity, options={}) # :yield: file

153:       to_identifier = Time.infinity if to_identifier.nil?
155:       before = checked_out_files
156:       # We expect subclasses to implement this as a protected method (unless this whole method is overridden).

157:       checkout_silent(to_identifier, options)
158:       after = checked_out_files
160:       (after - before).sort!
161:     end

The command line to run in order to check out a fresh working copy.


     # File lib/rscm/base.rb, line 242
242:     def checkout_commandline(to_identifier=Time.infinity)
243:       raise NotImplementedError
244:     end

Gets the working copy directory.


    # File lib/rscm/base.rb, line 56
56:     def checkout_dir
57:       @checkout_dir
58:     end

Sets the checkout dir (working copy). Should be set prior to most other method invocations (depending on the implementation).


    # File lib/rscm/base.rb, line 51
51:     def checkout_dir=(dir)
52:       @checkout_dir = PathConverter.filepath_to_nativepath(dir, false)
53:     end

Commit (check in) modified files.


     # File lib/rscm/base.rb, line 132
132:     def commit(message, options={})
133:       raise NotImplementedError
134:     end

Creates a new ‘central’ repository. This is intended only for creation of ‘central’ repositories (not for working copies). You shouldn’t have to call this method if a central repository already exists. This method is used primarily for testing of RSCM, but can also be used if you really want to use RSCM to create a central repository.

This method should throw an exception if the repository cannot be created (for example if the repository is ‘remote’ or if it already exists).


    # File lib/rscm/base.rb, line 93
93:     def create_central(options={})
94:       raise NotImplementedError
95:     end


    # File lib/rscm/base.rb, line 35
35:     def default_options
36:       @default_options ||= {}
37:     end

Destroys the central repository. Shuts down any server processes and deletes the repository. WARNING: calling this may result in loss of data. Only call this if you really want to wipe it out for good!


     # File lib/rscm/base.rb, line 100
100:     def destroy_central
101:       raise NotImplementedError
102:     end

Destroys the working copy


    # File lib/rscm/base.rb, line 68
68:     def destroy_working_copy(options={})
69:       FileUtils.rm_rf(checkout_dir) unless checkout_dir.nil?
70:     end

Yields an IO containing the unified diff of the change. Also see RevisionFile#diff


     # File lib/rscm/base.rb, line 254
254:     def diff(path, from, to, options={}, &block)
255:       raise NotImplementedError
256:     end

Open a file for edit - required by scms that check out files in read-only mode e.g. perforce


     # File lib/rscm/base.rb, line 128
128:     def edit(file, options={})
129:     end

Recursively imports files from :dir into the central scm, using commit message :message


     # File lib/rscm/base.rb, line 123
123:     def import_central(options)
124:       raise NotImplementedError
125:     end

Installs trigger_command in the SCM. The install_dir parameter should be an empty local directory that the SCM can use for temporary files if necessary (CVS needs this to check out its administrative files). Most implementations will ignore this parameter.


     # File lib/rscm/base.rb, line 224
224:     def install_trigger(trigger_command, install_dir)
225:       raise NotImplementedError
226:     end

Schedules a move of relative_src to relative_dest Should not take effect in the central repository until commit is invoked.


     # File lib/rscm/base.rb, line 117
117:     def move(relative_src, relative_dest, options={})
118:       raise NotImplementedError
119:     end

Opens a readonly IO to a file at path


     # File lib/rscm/base.rb, line 185
185:     def open(path, native_revision_identifier, options={}, &block) #:yield: io

186:       raise NotImplementedError
187:     end

Returns a Revisions object for the interval specified by from_identifier (exclusive, i.e. after) and optionally +:to_identifier+ (exclusive too). If relative_path is specified, the result will only contain revisions pertaining to that path.

For example, revisions(223, 229) should return revisions 224..228


     # File lib/rscm/base.rb, line 180
180:     def revisions(from_identifier, options={})
181:       raise NotImplementedError
182:     end

Whether or not to store the revision command in the Revisions instance returned by revisions


     # File lib/rscm/base.rb, line 267
267:     def store_revisions_command?; @store_revisions_command.nil? ? true : @store_revisions_command; end

Whether triggers are supported by this SCM. A trigger is a command that can be executed upon a completed commit to the SCM.


     # File lib/rscm/base.rb, line 206
206:     def supports_trigger?
207:       # The default implementation assumes no - override if it can be

208:       # determined programmatically.

209:       false
210:     end

Transforms raw_identifier into the native rype used for revisions.


    # File lib/rscm/base.rb, line 45
45:     def to_identifier(raw_identifier)
46:       raw_identifier.to_s
47:     end

Whether or not this SCM is transactional (atomic).


    # File lib/rscm/base.rb, line 80
80:     def transactional?
81:       false
82:     end

Whether the command denoted by trigger_command is installed in the SCM.


     # File lib/rscm/base.rb, line 236
236:     def trigger_installed?(trigger_command, install_dir)
237:       raise NotImplementedError
238:     end

Descriptive name of the trigger mechanism


     # File lib/rscm/base.rb, line 214
214:     def trigger_mechanism
215:       raise NotImplementedError
216:     end

Uninstalls trigger_command from the SCM.


     # File lib/rscm/base.rb, line 230
230:     def uninstall_trigger(trigger_command, install_dir)
231:       raise NotImplementedError
232:     end

The command line to run in order to update a working copy.


     # File lib/rscm/base.rb, line 248
248:     def update_commandline(to_identifier=Time.infinity)
249:       raise NotImplementedError
250:     end

Whether the working copy is in synch with the central repository’s revision/time identified by identifier. If identifier is nil, ‘HEAD’ of repository should be assumed.


     # File lib/rscm/base.rb, line 193
193:     def uptodate?(identifier)
194:       raise NotImplementedError
195:     end

Protected Instance methods

Directory where commands must be run


     # File lib/rscm/base.rb, line 272
272:     def cmd_dir
273:       nil
274:     end

Wrapper for CommandLine.execute that provides default values for dir plus any options set in default_options (typically stdout and stderr).


     # File lib/rscm/base.rb, line 278
278:     def execute(cmd, options={}, &proc)
279:       options = {:dir => cmd_dir}.merge(default_options).merge(options)
280:       begin
281:         CommandLine.execute(cmd, options, &proc)
282:       rescue CommandLine::OptionError => e
283:         e.message += "\nEither specify default_options on the scm object, or pass the required options to the method"
284:         raise e
285:       end
286:     end