[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

svn_all_diffs.pl #for windows

From: David Wilcock <david.wilcock_at_servotest.com>
Date: 2007-01-16 18:07:40 CET

I have got svn_all_diffs.pl working on perl for windows, thought it might be
useful to post it here. This script was useful to me for searching all
revisions of a file and I have added an svn cat of the original version to
help with this.

#!/usr/bin/perl -w

# svn_all_diffs.pl modified to work on windows by david wilcock. basically
ripped off solution on open(HANDLE, "-|") by Ian Brockbank at
http://svn.haxx.se/users/archive-2004-04/1280.shtml

# $HeadURL$
# $LastChangedDate$
# $LastChangedBy$
# $LastChangedRevision$

use strict;
use Carp;
use Getopt::Long 2.25;
use File::Temp 0.12 qw(tempdir tempfile);

# Process the command line options.

# Print the log message along with the modifications made in a
# particular revision.
my $opt_print_log_message;

GetOptions('log' => \$opt_print_log_message)
  or &usage;

&usage("$0: too many arguments") if @ARGV > 1;

# If there is no file or directory specified on the command line, use
# the current working directory as a default path.
my $file_or_dir = @ARGV ? shift : '.';

unless (-e $file_or_dir)
  {
    die "$0: file or directory `$file_or_dir' does not exist.\n";
  }

# Create a temporary directory for svn to work in.
my $temp_dir = $ENV{TMPDIR};
unless (defined $temp_dir and length $temp_dir) {
  # Try the Windows standard environment variable
  $temp_dir = $ENV{TEMP};
}
unless (defined $temp_dir and length $temp_dir) {
  $temp_dir = '/tmp';
}
my $temp_template = "$temp_dir/svn_load_dirs_XXXXXXXXXX";
$temp_dir = tempdir($temp_template);

# Get the entire log for this file or directory. Parse the log into
# two separate lists. The first is a list of the revision numbers
# when this file or directory was modified. The second is a hash of
# log messages for each revision.
my @revisions;
my %log_messages;
{
  my $current_revision;
  foreach my $log_line (read_from_process('svn', 'log', $file_or_dir))
    {
      # Ignore any of the lines containing only -'s.
      next if $log_line =~ /^-+$/;

      if (my ($r) = $log_line =~ /^r(\d+)/)
        {
          $current_revision = $r;
          $log_messages{$current_revision} = "";
          push(@revisions, $r);
        }

      if (defined $current_revision)
        {
          $log_messages{$current_revision} .= "$log_line\n";
        }
    }
}

# Run all the diffs.
my $first_time = 1;
while (@revisions > 1)
  {

    my $new_rev = shift @revisions;
    my $old_rev = $revisions[0];

    if ($first_time) {
        $first_time = 0;
        

    }
    
    &print_revision($new_rev);

    my @diff = read_from_process('svn', 'diff',
                                 "-r$old_rev:$new_rev", $file_or_dir);

    if ($opt_print_log_message)
      {
        print $log_messages{$new_rev};
      }
    print join("\n", @diff, "\n");
  }

# Print the log message for the last revision. There is no diff for
# this revision, because according to svn log, the file or directory
# did not exist previously.
{
  my $last_revision = shift @revisions;
  my @orig = read_from_process('svn', 'cat', "-r$last_revision",
$file_or_dir);
  print "\n\nOriginal Content:\n\n";
  print join("\n", @orig, "\n");
  if ($opt_print_log_message)
    {
      &print_revision($last_revision);
      print $log_messages{$last_revision};
    }
}

exit 0;

sub usage
{
  warn "@_\n" if @_;
  die "usage: $0 [options] [file_or_dir]\n",
      "Valid options:\n",
      " -l [--log] : also show the log messages\n";
}

sub print_revision
{
  my $revision = shift;

  print "\n\n\nRevision $revision\n";
}

# Start a child process safely without using /bin/sh.
my $openfork_available = "MSWin32" ne $^O;
sub safe_read_from_pipe
{
  unless (@_)
    {
      croak "$0: safe_read_from_pipe passed no arguments.\n";
    }
  print "Running @_\n";
  if ($openfork_available)
    {
      my $pid = open(SAFE_READ, "-|");
      unless (defined $pid)
        {
          die "$0: cannot fork: $!\n";
        }
      unless ($pid)
        {
          # child
          open(STDERR, ">&STDOUT")
            or die "$0: cannot dup STDOUT: $!\n";
          exec(@_)
            or die "$0: cannot exec '@_': $!\n";
        }
    }
  else
    {
      # Redirect the comment into a temp file and use that to work around
      # Windoze's (non-)handling of multi-line commands.
      my @commandline = ();
      my $command;
        
      while ($command = shift)
        {
          if ("-m" eq $command)
            {
              my $comment = shift;
              my ($handle, $tmpfile) = tempfile( DIR => $temp_dir);
              print $handle $comment;
              close($handle);
                
              push(@commandline, "--file");
              push(@commandline, $tmpfile);
            }
          else
            {
              if ($command =~ m"\n")
                {
                  warn "$0: carriage return detected in command - may not
work\n";
                }
              push(@commandline, $command);
            }
        }
        
      # Now do the pipe.
      open(SAFE_READ, "@commandline |")
        or die "$0: cannot pipe to command: $!\n";
    }
    
  # parent
  my @output;
  while (<SAFE_READ>)
    {
      chomp;
      push(@output, $_);
    }
  close(SAFE_READ);
  my $result = $?;
  my $exit = $result >> 8;
  my $signal = $result & 127;
  my $cd = $result & 128 ? "with core dump" : "";
  if ($signal or $cd)
    {
      warn "$0: pipe from `@_' failed $cd: exit=$exit signal=$signal\n";
    }
  if (wantarray)
    {
      return ($result, @output);
    }
  else
    {
      return $result;
    }
}

# Use safe_read_from_pipe to start a child process safely and exit the
# script if the child failed for whatever reason.
sub read_from_process
{
  unless (@_)
    {
      croak "$0: read_from_process passed no arguments.\n";
    }
  my ($status, @output) = &safe_read_from_pipe(@_);
  if ($status)
    {
      die "$0: @_ failed with this output:\n", join("\n", @output), "\n";
    }
  else
    {
      return @output;
    }
}

This email and any files transmitted with it are confidential and intended
solely for the use of the individual or entity to whom they are addressed.
If you are not the intended recipient be advised that you have received this
email in error and that any use, dissemination, forwarding, printing, or copying
of this email is strictly prohibited.

Internet communications are not secure and therefore Servotest Systems Ltd
do not accept legal responsibility for the contents of this message.
Although Servotest Systems Ltd operates anti-virus programmes it does not
accept responsibility for any damage whatsoever that is caused by viruses
being passed.

Any views or opinions presented are solely those of the author and do not
necessarily represent those of Servotest Systems Ltd.

If you have received this email in error, please notify the sender.

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@subversion.tigris.org
For additional commands, e-mail: users-help@subversion.tigris.org
Received on Tue Jan 16 18:16:23 2007

This is an archived mail posted to the Subversion Users mailing list.