svn_update.pl

来自「subversion-1.4.3-1.tar.gz 配置svn的源码」· PL 代码 · 共 341 行

PL
341
字号
#!/usr/bin/perl -w# ====================================================================## svn_update.pl## Put this in your path somewhere and make sure it has exec perms.# Do your thing w/subversion but when you would use 'svn update'# call this script instead.## ====================================================================# Copyright (c) 2000-2004 CollabNet.  All rights reserved.## This software is licensed as described in the file COPYING, which# you should have received as part of this distribution.  The terms# are also available at http://subversion.tigris.org/license-1.html.# If newer versions of this license are posted there, you may use a# newer version instead, at your option.## This software consists of voluntary contributions made by many# individuals.  For exact contribution history, see the revision# history and logs, available at http://subversion.tigris.org/.# ====================================================================# WHY THE NEED FOR THIS SCRIPT?## Currently, the subversion server will attempt to stream all file# data to the client at once for _each_ merge candidate.  For cases# that have >1 file and/or the complexity of the merge for any# given file(s) that would require >n minutes, where n is the# server's magic timeout (5 min.??), the server will timeout.  This# leaves the client/user in an unswell state.  See issue #2048 for# details http://subversion.tigris.org/issues/show_bug.cgi?id=2048.## One solution is to wrap the 'svn update' command in a script that# will perform the update one file at a time.  The problem with# this solution is that it defeats the beneficial atomic nature of# subversion for this type of action.  If commits are still coming# in to the repository, the value of "HEAD" might change between each# of these update operations.## Another solution, the one that this script utilizes, passes the# --diff3-cmd directive to 'svn update' using a command which forces# a failed contextual merge ('/bin/false', for example).  These faux# merge failures cause subversion to leave all of the accounting files# involved in a merge behind and puts them into the 'conflict'# state.  Since all the data required for all the merges took place# at that exact moment atomicity is preserved and life is swell.######################################################################## This is required for copy() command.  I believe it's a standard# module.  If there's a doubt run this from a shell:#	perl -e 'use File::Copy;'# If you don't get any complaint from perl you're good.  Otherwise# comment this line out and change the $backup_mine_files to 0.use File::Copy;# This forces backing up of the .mine files for reference even # after the resolved command.  The backups will be stored as# <filename.username>$backup_mine_files=1;# Choose your favorite graphical diff app.  If it's not here, just add# the full path to it and the style of the options to the# %DIFF3CMD_hash below.$DIFF3CMD="xcleardiff";# Override the diff3-cmd in the config file here.# If this is an empty string it'll use the config file's# setting.#$d3cmdoverride="";$d3cmdoverride="/bin/false";# Add more diff programs here.  # For the internal, discovered, file parameters:#	+A+ ==> mine#	+B+ ==> older#	+C+ ==> latest#	+D+ ==> Destination (The output of your merged code would go here.#                            This would, generally, be whatever #                            $(basename <+A+> .mine) would evaluate to.# But you can feel free to do something like these:# 	"+B+ +C+ +A+ -out +D+.bob"# 	"+B+ +A+ +C+ -out /tmp/bob"# Just note that the '+' (plus) are to limit the false positives in the# search and replace sub.## HAVING THE CORRECT PATH, AND ARGS FOR YOUR DIFF PROGRAM, IS CRITICAL!!%DIFF3CMD_hash=(# Ahh...hallowed be thy name.                "/opt/atria/bin/xcleardiff" => "+A+ +B+ +C+ -out +D+",                  # This one is slow.                "/usr/bin/kdiff3"           => "+A+ +B+ +C+ -o +D+",                    # This one's slow and it sucks!(BUGGY)                "/usr/bin/xxdiff"           => "-M +D+ +A+ +B+ +C+",                    # This one's even worse (no output filename).                "/usr/bin/meld"             => "+A+ +B+ +C+",                );sub exec_cmd{  my @args=@_;  my $CMD=$args[0];    my @retData;  my $i=0;  open (FH,$CMD) || die("Can't '$CMD': $!\n");  while($_=<FH>)  {    chomp($_);    $retData[$i]=$_;     $i++;  }  close(FH);  return \@retData;} # exec_cmdsub diff_it{  my @args=@_;  my $A=$args[0]; # mine  my $B=$args[1]; # older  my $C=$args[2]; # latest  my $D=$args[3]; # output of merge (Destination)  my @rdat;  # What's is the diff of choice?  if( $CHOSENDIFF eq "" )  {    # Glean our choice.    diff_of_choice();  }  # $CHOSENDIFF has data.  We deal with the args.  ($diffcmd,$diff_format)=(split /:/,$CHOSENDIFF);  # This works.  $diff_format=~s/\+A\+/$A/g;  $diff_format=~s/\+B\+/$B/g;  $diff_format=~s/\+C\+/$C/g;  $diff_format=~s/\+D\+/$D/g;  @rdat=@{exec_cmd("$diffcmd $diff_format 2>/dev/null |")};  return @rdat;} #diff_itsub diff_of_choice{  foreach $diff_app (sort(keys(%DIFF3CMD_hash)))  {    if( ${diff_app}=~m/${DIFF3CMD}/o )    {      $CHOSENDIFF="$diff_app:$DIFF3CMD_hash{$diff_app}";    }  }  if( $CHOSENDIFF eq "" )  {    # Big problem.  Some kind of disconnect w/the choice and the hash.    # Most likely a typo.    print "It would seem that the '${DIFF3CMD}' was not found in\n";    print "the hash of diff applications I know about.  Please\n";    print "investigate and correct.\n";    exit(1);  }} #diff_of_choicesub svn_update_info{  my @data;  my @file_array;  my $j;  # Check to see if the d3cmdoverride is set so  # we don't fail here if it wasn't.  if( ${d3cmdoverride} eq "" )  {    $d3cmdoverride_final="";  }  else  {    $d3cmdoverride_final="--diff3-cmd=${d3cmdoverride}";  }  @data=@{exec_cmd("svn update ${d3cmdoverride_final} | grep ^C | awk '{print \$2}' |")};  for($j=0;$j<(scalar(@data));$j++)  {    push( @file_array, exec_cmd("svn info $data[$j] |") );  }  return @file_array;} # svn_update_infosub parse_it{  my @file_array=@_;  my @file;  my $fname;  my $fpath_tmp;  my $fpath;  my $file_ref;  my $sbox_repo_base;  my $sbox_repo_changed;  my $sbox_repo_latest;  my @cleanup_array;  my @commit_array;  my $rdat;  my $retline;  my $i;  foreach $file_ref (@file_array)  {    @file=@{$file_ref};    for($i=0; $i < (scalar(@file)-1);$i++)    {      if( $file[$i]=~m/Name:/o )      {        # Key off of "Name:" and then back up one to get "Path:".        # This way the calculations will be correct when chopping off        # the name portion on the path bit.        $fname=(split /Name: /,$file[$i])[1];        $fpath_tmp=(split /Path: /,$file[$i-1])[1];        $fpath=(substr($fpath_tmp,0,(length($fpath_tmp)-(length($fname)+1))));      }      elsif( $file[$i]=~m/Conflict Previous Base File:/o )      {        $sbox_repo_base=(split /Conflict Previous Base File: /,$file[$i])[1];      }      elsif( $file[$i]=~m/Conflict Previous Working File:/o )      {        $sbox_repo_changed=(split /Conflict Previous Working File: /,                            $file[$i])[1];      }      elsif( $file[$i]=~m/Conflict Current Base File:/o )      {        $sbox_repo_latest=(split /Conflict Current Base File: /,$file[$i])[1];      }    }#   print "\n----------------------------------------------\n";#   print "                      \$fpath: '$fpath'\n";#   print "                      \$fname: '$fname'\n";#   print "[A](mine) \$sbox_repo_changed: '$sbox_repo_changed'\n";#   print "[B](older)   \$sbox_repo_base: '$sbox_repo_base'\n";#   print "[C](latest)\$sbox_repo_latest: '$sbox_repo_latest'\n";#   print "\n----------------------------------------------\n";    # Send them in standard, ABCD, order.    @rdat=diff_it("${fpath}/${sbox_repo_changed}",                  "${fpath}/${sbox_repo_base}",                  "${fpath}/${sbox_repo_latest}",                  "${fpath}/${fname}");    # Print out any return data.  Shouldn't be much of anything due to    # the redirection to /dev/null in the invocation of whatever diff    # command is used.    print "\nOutput from diff3 command.\n";    print "-----------------------\n";    foreach $retline (@rdat)    {      print "$retline\n";    }    print "---------END-----------\n";    # Add the files we may wish to remove to an array.  Keep *.mine    # files in case something bad happened.    push(@cleanup_array,         "${fpath}/${sbox_repo_base}",          "${fpath}/${sbox_repo_latest}",          "${fpath}/${fname}.orig");    # Make copies of *.mine for ctya purposes.    if ( ${backup_mine_files} > 0 )    {      copy("${fpath}/${sbox_repo_changed}",           "${fpath}/${fname}.${ENV{USERNAME}}");    }    # Return an array that contains all the files we might wish to    # commit.    push(@commit_array,"${fpath}/${fname}");  }  return \@cleanup_array, \@commit_array;} #parse_itsub clean_up{  my @args=@_;  my @rdat;  foreach $file (@{$args[0]})  {    unlink($file);  }  # Need to tell subversion we have resolved the conflicts.  @rdat=@{exec_cmd("svn -R resolved . |")};  print "\nOutput from subversion 'resolved' command.\n";  print "-----------------------\n";  foreach $line (@rdat)  {    print "$line\n";  }  print "---------END-----------\n";} #clean_upsub main{  my @args=@_;  my $cleanup_aref;  my $commit_aref;  my $file;  ($cleanup_aref,$commit_aref)=parse_it(svn_update_info());  clean_up($cleanup_aref);  print "\nDon't forget to commit these files:\n";  print "-----------------------\n";  foreach $file (@{$commit_aref})  {    print "$file\n";  }  print "---------END-----------\n";} #main# Special global.$CHOSENDIFF="";# Get the ball rolling.main(@ARGV);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?