# deepimport.pl -- import history from a remote depot. # # Usage: # deepimport.pl srcPath... tgtPath... # # 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 "admin" access on # the local server to copy the changelists over. # # 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+)/ ) { last; } # Changes come in reverse order. unshift @changes, $1; } close CHANGES; $count = 0; foreach $change ( @changes ) { #Import the change. print "Importing change $change..."; `$p4_local integ "$source_local\@$change" "$target_local"`; `$p4_local resolve -as "$target_local" 2>&1`; $_ = `$p4_local submit -d "Import $change from $source_local."`; if ( !/Change (\d+) submitted.$/ ) { last; } $import = $1; print " local change $import submitted.\n"; #Try to copy the change description over. open REMOTE, "$p4_remote change -o $change|" or die "$!"; open LOCAL, "$p4_local change -o $import|" or die "$!"; open EDIT, "|$p4_local change -if" or die "$!"; # Everything before the User: field should remain unchanged. # Everything after that is either identical or can be # overwritten. (Note that there is no Files: field.) while ( ) { print EDIT $_; if ( /^Client:/ ) { last; } } while ( ) { if ( /^Client:/ ) { last; } } while ( ) { print EDIT $_; } close REMOTE; close LOCAL; close EDIT; $count++; } print "$count changes imported.\n";