Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

Ovid (2709)

Ovid
  (email not shown publicly)
http://publius-ovidius.livejournal.com/
AOL IM: ovidperl (Add Buddy, Send Message)

Stuff with the Perl Foundation. A couple of patches in the Perl core. A few CPAN modules. That about sums it up.

Journal of Ovid (2709)

Friday November 28, 2008
10:51 AM

Vim: source control diffs

[ #37966 ]

Quite often I want to get a diff of the file I'm working on, but as usual, I hate leaving my editor for something I script. So I first wrote this simple Perl program (adjust to taste):

#!/usr/bin/env perl

use strict;
use warnings;

my $file = shift || die "You must supply a filename to $0";

unless ( -f $file ) {
    die "File ($file) does not exist";
}

my @log = qx(svn log "$file" --stop-on-copy);
my $branch_name = branch_name();

my $pipe = qr/[[:space:]]+\|[[:space:]]+/;

splice @log, 0, 3;   # discard first revision
while (local $_ = shift @log) {
    next unless /\Ar([[:digit:]]+)$pipe([[:word:]]+)$pipe(\S+)\s+\S+/;
    my ( $revision, $user, $datetime ) = ( $1, $2, $3 );
    print "$revision - $user - $datetime - ";
    shift @log;
    my $message = shift @log;

    # we often prefix commit messages with "$branch_name: "
    $message =~ s/^\s*$branch_name(?::\s*)?//;  # trim it if it's there
    print $message;
}

sub branch_name {
    chomp(my @svn_info = qx(svn info .));
    my ($branch_name) = $svn_info[1] =~ m{/([^/]+)\z};
    return $branch_name;
}

That produces a summarized output of the subversion log history:

13015 - ovid - 2008-11-28 - Made changes to the fixture and test file
13014 - jplindstom - 2008-11-28 - Made a change to the Assert Result Test
13012 - danquayle - 2008-11-28 - Fixed misspeeling

And this vim function:

function! SourceDiff()
    let filename = bufname("%")
    let command  = 'perl script/svn_revisions.pl "'.filename.'"'
    let result   = split( system(command), "\n" )

    if empty(result)
        echomsg("No past revisions for " . filename)
        return
    endif

    " get the list of files
    let revision = PickFromList('revision', result)

    if strlen(revision)
        let items = split(revision, " ")
        execute '!svn diff -r' . items[0] . ' "' . filename .'" | less'
    endif
endfunction

(Note that this relies on my PickFromList function)

When I bind that to a key (or keystroke), it gives me output like this:

Choose a revision:
1: 13015 - ovid - 2008-11-28 - Made changes to the fixture and test file
2: 13014 - jplindstom - 2008-11-28 - Made a change to the Assert Result Test
3: 13012 - danquayle - 2008-11-28 - Fixed misspeeling

I hit the appropriate number of the revision I want to diff against, and voila, a quick subversion diff in my vim session.

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
 Full
 Abbreviated
 Hidden
More | Login | Reply
Loading... please wait.
  • Hello, Ovid.

    The fact that your script only works if the cwd is file's directory kind of frustate me, as I normally work on the root dir of the project.

    Here is a patch to make it work wherever the cwd is.

    --- svn_revisions.pl.ovid    2008-12-22 10:59:09.000000000 -0400
    +++ svn_revisions.pl    2008-12-22 11:12:55.000000000 -0400
    @@ -2,6 +2,7 @@

    use strict;
    use warnings;
    +use File::Basename qw(dirname);

    my $file = shift || die "You must supply a filename to $0";

    @@ -28,7 +29,8 @@
    }

    sub branch_na