git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Chris Mason <mason@suse.com>
To: git@vger.kernel.org
Subject: Finding file revisions
Date: Wed, 27 Apr 2005 12:50:59 -0400	[thread overview]
Message-ID: <200504271251.00635.mason@suse.com> (raw)

Hello everyone,

I haven't seen a tool yet to find which changeset modified a given file, so 
I whipped up something.  The basic idea is to:

for each changeset in rev-list
	for each file in diff-tree -r parent changeset
		match against desired files

Is there a faster way?  This will scale pretty badly as the tree grows, but 
I usually only want to search back a few months in the history.  So, it 
might make sense to limit the results by date or commit/tag.

Usage:
file-changes [-c commit id] file1 ...

The file names can be perl regular expressions, and it will match any file 
starting with the expression listed.  So "file-changes fs/ext" will show 
everything in ext2 and ext3.

Example output:

diff-tree -r 56022b4d00cae3ff816d3ff05d9f8a80e1517c60 9bd104d712d710d53c35166e40bd5fe24caf893e
8a796b48e757e56b50802c28abf28e0199c45ad9->2db368df614de4799be2d1baffb6563dbe1b8926 fs/ext2/inode.c
dbc8fd9bab639b84b8cc94fdbbf850b1e4bf1b2b->a4cd819734ba2eea9d5d21039deca62057f72d44 fs/ext3/inode.c
cat-file commit 9bd104d712d710d53c35166e40bd5fe24caf893e
    tree cd4e40eae003e29c0d3be2aa769c3b572ab1b488
    parent 56022b4d00cae3ff816d3ff05d9f8a80e1517c60
    author mason <mason@coffee> 1114617717 -0400
    committer mason <mason@coffee> 1114617717 -0400

    comments go here

This is meant for cut n' paste.  If you find a changeset comment you like, 
run the diff-tree -r command on the first line to see a diff of the 
changeset (maybe I should add | diff-tree-helper here?)

-chris


#!/usr/bin/perl

use strict;

my $last;
my $ret;
my $i;
my @wanted = ();
my $matched;
my $argc = scalar(@ARGV);
my $commit;

sub print_usage() {
    print STDERR "usage: file-changes [-c commit] file_list\n";
    exit(1);
}

if ($argc < 1) {
    print_usage();
}

for ($i = 0 ; $i < $argc ; $i++)  {
    if ($ARGV[$i] eq "-c") {
    	if ($i == $argc - 1) {
	    print_usage();
	}
	$commit = $ARGV[++$i];
    } else {
	push @wanted, $ARGV[$i];
    }
}

if (!defined($commit)) {
    $commit = `commit-id`;
    if ($?) {
    	print STDERR "commit-id failed, try using -c to specify a commit\n";
	exit(1);
    }
    chomp $commit;
}

$last = $commit;

open(RL, "rev-list $commit|") || die "rev-list failed";
while(<RL>) {
    chomp;
    my $cur = $_;
    $matched = 0;
    if ($cur eq $last) {
        next;
    }
    # rev-list gives us the commits from newest to oldest
    open(DT, "diff-tree -r $cur $last|") || die "diff-tree failed";
    while(<DT>) {
        chomp;
	my @words = split;
	my $file = $words[3];
	# if the filename has whitespace, suck it in
	if (scalar(@words) > 4) {
	    if (m/$file(.*)/) {
	        $file .= $1;
	    }
	}
	foreach my $m (@wanted) {
	    if ($file =~ m/^$m/) {
		if (!$matched) {
		    print "diff-tree -r $cur $last\n";
		}
		print "$words[2] $file\n";
		$matched = 1;
	    }
	}
    }
    close(DT);
    if ($?) {
	$ret = $? >> 8;
	die "diff-tree failed with $ret";
    }
    if ($matched) {
	print "cat-file commit $last\n";
	open(COMMIT, "cat-file commit $last|") || die "cat-file $last failed";
	while(<COMMIT>) {
	    print "    $_";
	}
	close(COMMIT);
	if ($?) {
	    $ret = $? >> 8;
	    die "cat-file failed with $ret";
	}
	print "\n";
    }
    $last = $cur;
}

close(RL);
if ($?) {
    $ret = $? >> 8;
    die "rev-list failed with $ret";
}

             reply	other threads:[~2005-04-27 16:46 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-04-27 16:50 Chris Mason [this message]
2005-04-27 17:34 ` Finding file revisions Linus Torvalds
2005-04-27 18:23   ` Chris Mason
2005-04-27 22:19     ` Linus Torvalds
2005-04-27 22:31       ` Chris Mason
2005-04-28  8:41         ` Simon Fowler
2005-04-28 11:56           ` Chris Mason
2005-04-28 13:13             ` Simon Fowler
2005-04-28 11:45       ` Chris Mason
2005-04-28 16:34         ` Kay Sievers
2005-04-28 17:10           ` Tony Luck
2005-04-28 17:22             ` Thomas Glanzmann
2005-04-28 19:11         ` Kay Sievers
2005-04-28 20:58           ` Chris Mason
2005-04-28 21:32             ` Linus Torvalds
2005-04-28 21:33             ` Kay Sievers
2005-04-28 21:50               ` Linus Torvalds
2005-04-28 22:27               ` Chris Mason
2005-04-28 13:09       ` David Woodhouse
2005-04-28 13:01     ` David Woodhouse
2005-04-27 18:41   ` Thomas Gleixner
2005-04-28 15:24     ` Linus Torvalds
2005-04-28 16:47       ` Thomas Gleixner
2005-04-28 16:08 ` Daniel Barkalow
2005-04-28 17:05   ` Chris Mason

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=200504271251.00635.mason@suse.com \
    --to=mason@suse.com \
    --cc=git@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).