# # File:: lib/pipeline/scm/perforce_util.rb # Description:: High-level Perforce utility classes and functions. # # Author:: David Muir # Date:: 2 December 2009 # # For monkey-patching functions into the SCM::Perforce class use the # perforce_helper.rb instead. # #---------------------------------------------------------------------------- # Uses #---------------------------------------------------------------------------- require 'pipeline/log/log' require 'pipeline/os/path' #---------------------------------------------------------------------------- # Monkey-Patching #---------------------------------------------------------------------------- # Monkey patch the P4::Revision class to allow public access to the # attributes member. This class varies from our documentation quite a bit. # Ah well. Thank the Ruby stars for Monkey-Patching goodness. class P4 class Revision attr_reader :attributes end end #---------------------------------------------------------------------------- # Implementation #---------------------------------------------------------------------------- module Pipeline module SCM # # == Description # High-level Perforce utility classes and functions. # module PerforceUtil # # Fetch a Perforce file revision at a temporary location. The # temporary location filename is returned. # # === Example # See %TOOLSLIB%/util/perforce/p4_get_revision.rb for an example of # this function's usage. # def PerforceUtil::get_file_revision_temp( log, p4, depotfile, rev ) throw ArgumentError.new( "Invalid P4 object (#{p4.class})." ) \ unless ( p4.is_a?( P4 ) ) throw ArgumentError.new( "Invalid P4::DepotFile object (#{depotfile.class})." ) \ unless ( depotfile.is_a?( P4::DepotFile ) ) throw ArgumentError.new( "Invalid P4::Revision object (#{rev.class})." ) \ unless ( rev.is_a?( P4::Revision ) ) p4.connect() unless ( p4.connected?() ) filename = depotfile.depot_file tempclient = "#{p4.user}_get_revision_temp" where = p4.run_where( filename ).shift() target = OS::Path::get_directory( where['clientFile'].gsub( p4.client, tempclient ) ) target = OS::Path::combine( target, '_Get', OS::Path::get_filename( filename ) ) localnewfilename = nil p4new = P4::new() begin PerforceUtil_Private::create_single_file_workspace( log, p4, p4.client, tempclient, filename, target ) # Sync the file into the new client. p4new.port = p4.port p4new.client = tempclient p4new.user = p4.user p4new.connect( ) unless ( p4new.connected?() ) puts "REV: #{rev.inspect}" revision = rev.attributes['rev'].to_s newfilenamewithrev = "#{filename}##{revision}" log.info( "Syncing: #{newfilenamewithrev}." ) p4new.run_sync( '-f', newfilenamewithrev ) localfilename = p4new.run_where( filename ).shift()['path'] localnewfilename = OS::Path::combine( OS::Path::get_directory( localfilename ), OS::Path::get_basename( localfilename ) ) + "##{revision}.#{OS::Path::get_extension(localfilename)}" log.info( "Synced. Moving file to: #{localnewfilename}." ) FileUtils::move( localfilename, localnewfilename ) ensure p4new.disconnect( ) PerforceUtil_Private::destroy_workspace( log, p4, tempclient ) end localnewfilename end #-------------------------------------------------------------------- # Private #-------------------------------------------------------------------- private # Private Module. module PerforceUtil_Private # Create a new user workspace that maps a single source file/dir # to a single target file/dir. def PerforceUtil_Private::create_single_file_workspace( log, p4, template, name, source, target ) log.info( "Creating Perforce client: #{name}." ) curr_client = p4.fetch_client( template ) new_client = p4.fetch_client( name ) new_client['Root'] = curr_client['Root'] new_client['Description'] = "Created by #{OS::Path::get_basename(__FILE__)}." new_client_view = P4::Map::new( new_client._view ) new_client_view.clear( ) new_client_view.insert( source, target ) new_client['View'] = new_client_view.to_a p4.save_client( new_client ) curr_client end # Destroy a user workspace. This will fail if the user has files # checked-out. def PerforceUtil_Private::destroy_workspace( log, p4, name ) log.info( "Destroying Perforce client: #{name}." ) p4.delete_client( name ) end end end # PerforceUtil module end # SCM module end # Pipeline module # lib/pipeline/scm/perforce_util.rb