Class SpecMgr
In: specsaver.rb
Parent: Object

Virtual base class for handling all types of spec. For each spec you want to manage, derive a class which must implement at least the following methods:

      list_specs    - list specs ("p4 clients"/"p4 labels" etc.)
      spec_file     - Locate spec file in workspace

Optionally, you may also want to override the changed? method used to determine whether or not a spec has changed since the last time it was archived. The default method uses the "Update" timestamp in the spec, but not all specs have this. If in doubt, changed? should just evaluate to true anyway, and let the "p4 revert -a" sort it out.

Methods
add_edit_file    changed?    new    revert_unchanged    save_spec    submit    type2name    update    write_ws_file   
Public Class methods
new( root, p4tagged, p4untagged )

Constructor: Supply the client root, and two P4 instances, one with tagged mode enabled, and one without.

# File specsaver.rb, line 127
    def initialize( root, p4tagged, p4untagged )
	@root = root
	@p4t = p4tagged
	@p4u = p4untagged
	@modlist = Hash.new
    end
Public Instance methods
update( type, since )

Updates the archives for all specs of the specified type. This is the main public interface method for this class

# File specsaver.rb, line 138
    def update( type, since )
	list_specs.each do
	    |spec|
	    save_spec( type, spec ) if ( changed?( spec, since ) )
	end
	submit( description() )
    end
Protected Instance methods
changed?( spec, stamp )

Method to determine whether or not a spec has changed since the specified timestamp. The default implementation uses the "Update" field of the spec, but this is not available in all types of spec so this method should be overridden for those specs. Where there is no easy way to decide whether or not a spec has changed, override implementations of this method should just return true and let the "p4 revert -a" sort it all out.

# File specsaver.rb, line 157
    def changed?( spec, stamp )
	spec[ "Update" ].to_i > stamp 
    end
add_edit_file( path, name )

Opens the specified file for add or edit as appropriate

# File specsaver.rb, line 164
    def add_edit_file( path, name )
	fs = @p4t.run_fstat( path ).shift
	if ( fs )
	    @p4t.run_edit( path )
	else
	    @p4t.run_add( "-t", "text", path )
	    fs = @p4t.run_fstat( path ).shift
	end
	@modlist[ fs[ "depotFile" ] ] = name
    end
type2name( type, spec )

Compute the name of a spec from its type. Necessary because the field for jobs is "Job" whilst for clients it's "client" ...

# File specsaver.rb, line 179
    def type2name( type, spec )
	return spec[ type ] if spec.has_key?( type )
	return spec[ type.capitalize ] if spec.has_key?( type.capitalize )
	raise( RuntimeError, "Can't determine object name from type" )
    end
save_spec( type, spec )

Save the named spec into its text file version. As we don't want the spec in parsed form for this we use the non-tagged P4 instance here to run the "p4 xxxx -o" and the output of that command is written to the workspace file.

# File specsaver.rb, line 191
    def save_spec( type, spec )
	path = spec_file( spec )
	name = type2name( type, spec )
	add_edit_file( path, name )

	form = eval( }@p4u.fetch_#{type}( "#{name}" )} )
	write_ws_file( path, form )
    end
write_ws_file( path, form )

Method to write form data into the workspace file

# File specsaver.rb, line 203
    def write_ws_file( path, form )
	File.open( path, "w+" ) do
	    |file|
	    file.write( form )
	end
    end
revert_unchanged()

Revert all unchanged files and remove them from the modlist.

# File specsaver.rb, line 213
    def revert_unchanged()
	@p4t.run_revert( "-a" ).each do
	    |r|
	    r = r.sub( /\#\d+.*/, "" )
	    @modlist.delete( r ) if @modlist.has_key?( r )
	end
    end
submit( desc )

Submit the changelist and write out a message including the list of objects being updated.

# File specsaver.rb, line 225
    def submit( desc )
	revert_unchanged()
	change = @p4t.fetch_change
	if ( change.has_key?( "Files" ) )
	    change[ "Description" ] = desc
	    @p4t.submit_spec( change )
	    puts( desc + "\n\t" + @modlist.values.sort.join( "\n\t" ) )
	end
	@modlist = Hash.new
    end