# # File:: %RS_TOOLSLIB%/util/perforce/p4_revert_files.rb # Description:: Mass-revert files for a particular user. # # Author:: David Muir # Date:: 5 March 2012 # #----------------------------------------------------------------------------- # Uses #----------------------------------------------------------------------------- require 'pipeline/config/projects' require 'pipeline/os/getopt' require 'pipeline/os/path' require 'pipeline/scm/perforce' include Pipeline #----------------------------------------------------------------------------- # Constants #----------------------------------------------------------------------------- OPTIONS = [ [ '--user', '-u', OS::Getopt::REQUIRED, 'user changelists to revert.' ], [ '--help', '-h', OS::Getopt::BOOLEAN, 'display usage information.' ] ] TRAILING = { 'paths' => 'paths to revert changelists for.' } #----------------------------------------------------------------------------- # Functions #----------------------------------------------------------------------------- # The meat function that handles the revert. def revert_changelists_for_user( p4, log, username, path ) files_with_rev = [] files = [] count = 0 flog_records = p4.run_filelog( path ) flog_records.each do |flog_file| log.info( "Processing: #{flog_file.depot_file}..." ) # Most recent version is first. next unless ( 0 == username.casecmp( flog_file.revisions.first.user ) ) # User touched #head revision; we need to revert it. log.info( "\tUser #{username} has touched \#head revision!" ) # Find revision to revert to; i.e. latest one that user didn't commit. rev_revert = nil flog_file.revisions.each do |revision| next unless ( 0 != username.casecmp( revision.user ) ) rev_revert = revision.rev break end if ( rev_revert.nil? ) then log.warn( "\tNo known file revision to revert to." ) else count += 1 log.info( "\tRevert #{flog_file.depot_file} to revision #{rev_revert}/#{flog_file.revisions.size}." ) files_with_rev << "#{flog_file.depot_file}\##{rev_revert}" files << flog_file.depot_file end end # Handle batching of sync, edit and resolve for more efficient Perforce # usage. changelist = p4.create_changelist( "p4_revert_files: #{count} files for user #{username}." ) p4.run_sync( *files_with_rev ) p4.run_edit( '-c', changelist, *files ) p4.run_sync( *files ) p4.run_resolve( '-ay', *files ) count end #----------------------------------------------------------------------------- # Implementation #----------------------------------------------------------------------------- if ( __FILE__ == $0 ) then g_AppName = OS::Path::get_filename( __FILE__ ) g_Config = Pipeline::Config::instance( ) g_Opts, g_Trailing = OS::Getopt::getopts( OPTIONS ) g_Log = Log.new( g_AppName ) if ( g_Opts['help'] ) then puts OS::Getopt::usage( OPTIONS, TRAILING ) exit( 1 ) end if ( not g_Opts.has_key?( 'user' ) ) then g_Log.error( "--user option required." ) puts OS::Getopt::usage( OPTIONS, TRAILING ) exit( 1 ) end begin user = g_Opts['user'] project = Pipeline::Config::instance().project project.load_config( ) p4 = project.scm( ) p4.connect( ) count = 0 g_Trailing.each do |path| count += revert_changelists_for_user( p4, g_Log, user, path ) end g_Log.info( "User #{user} touched #{count} files that are reverted." ) p4.disconnect( ) rescue SystemExit => ex exit( ex.exitstatus ) rescue Exception => ex g_Log.exception( ex, 'Unhandled exception' ) puts "Press any key to continue..." $stdin.gets end end # %RS_TOOLSLIB%/util/perforce/p4_revert_files.rb