# deepimport.pl -- import history from a remote depot. # # Usage: # deepimport.pl srcPath... tgtPath... # # This script will do a changelist-by-changelist integration from # a remote depot so that the full version history is reflected in # the local depot. The changelist descriptions and pertinent # information about the original changes will be copied into the # changelist descriptions in the local depot. # # The srcPath should be in a remote depot that maps to a Perforce # server that you can access directly. You will only need "list" # access on the remote server, but you will need the usual "read" # and "write" access to the source and target on the local server. # # If you don't set the configuration variables, they'll be read from your # environment. If you don't specify authentication info # for the remote server, the local user/password will be used. $p4 = "p4"; $P4PORT = ""; $P4USER = ""; $P4PASSWD = ""; $P4CLIENT = ""; $P4USER_remote = ""; $P4PASSWD_remote = ""; #####end configuration section########### if ( !$P4USER_remote ) { $P4USER_remote = $P4USER; } if ( !$P4PASSWD_remote ) { $P4PASSWD_remote = $P4PASSWD; } $p4_local = $p4; $p4_remote = $p4; if ( $P4PORT ) { $p4_local .= " -p $P4PORT"; } if ( $P4USER ) { $p4_local .= " -u $P4USER"; } if ( $P4PASSWD ) { $p4_local .= " -P $P4PASSWD"; } if ( $P4CLIENT ) { $p4_local .= " -c $P4CLIENT"; } $source_local = $ARGV[0]; $target_local = $ARGV[1]; if ( !$source_local or !$target_local ) { die "Please provide a source and target path."; } # Resolve $source_local to a depot path. open WHERE, "$p4_local -Ztag where \"$source_local\" 2>&1|" or die "$!"; while () { chomp; if ( /\.\.\. depotFile (.*)/ ) { $source_local = $1; last; } } close WHERE; $_ = $source_local; if ( /^\/\/([^\/]+)/ ) { $depot = $1; } else { die "Unable to resolve $_ to a depot path." } # Get remote server information. $P4PORT_remote = $P4PORT; $map_remote = "//$depot/..."; open DEPOT, "$p4_local -Ztag depot -o \"$depot\"|" or die "$!"; while () { chomp; if ( /\.\.\. Type (.*)/ and $1 ne "remote" ) { last; } # I was going to throw an error here if Type wasn't remote, # but maybe somebody will really want to do an import from # a local depot? Not too hard to allow that; we just bail # out here and use the local connection settings instead. if ( /\.\.\. Address (.*)/ ) { $P4PORT_remote = $1; } if ( /\.\.\. Map (.*)/ ) { $map_remote = $1; } } close DEPOT; if ( $P4PORT_remote ) { $p4_remote .= " -p $P4PORT_remote"; } if ( $P4USER_remote ) { $p4_remote .= " -u $P4USER_remote"; } if ( $P4PASSWD_remote ) { $p4_remote .= " -P $P4PASSWD_remote"; } #Use Map to translate $source_local into $source_remote. $_ = $map_remote; if ( !/\.\.\.$/ ) { die "Map field doesn't end in ..."; } s/\.\.\.$//; $map_remote = $_; $map_local = "//$depot/"; $_ = $source_local; s/$map_local/$map_remote/; $source_remote = $_; # Now the fun begins! We're going to connect to the remote server, get # the list of changes for this path, and start importing. @changes = (); open CHANGES, "$p4_remote changes \"$source_remote\"|" or die "$!"; while () { if ( !/^(Change \d+ on [^a-z]+ by [^\s]+)/ ) { last; } # Changes come in reverse order. unshift @changes, $1; } close CHANGES; $count = 0; foreach ( @changes ) { if ( !/^Change (\d+) (on.*)/ ) { next; } else { $change = $1; $desc = $2; } #Import the change. print "Importing change $change...\n"; `$p4_local integ "$source_local\@$change" "$target_local"`; `$p4_local resolve -as "$target_local" 2>&1`; # Submit, copying the remote description. open REMOTE, "$p4_remote change -o $change|" or die "$!"; open LOCAL, "$p4_local change -o|" or die "$!"; open SUBMIT, "|$p4_local submit -i" or die "$!"; while ( ) { print SUBMIT $_; if ( /^Description:/ ) { last; } } while ( ) { if ( /^Description:/ ) { last; } } while ( ) { if ( /^Files:/ ) { last; } print SUBMIT $_; } if ( !$P4PORT_remote ) { $P4PORT_remote = "this server"; } print SUBMIT "\tImported from change $change at $P4PORT_remote.\n"; print SUBMIT "\tOriginally submitted $desc.\n"; while ( ) { if ( /^Files:/ ) { print SUBMIT $_; last; } } while ( ) { print SUBMIT $_; } close REMOTE; close LOCAL; close SUBMIT; $count++; } print "$count changes imported.\n";