git/git-findtags.perl
Martin Langhoff 8af12741ee Add findtags - reworked
A short perl script that will walk the tag refs, tag objects, and even commit
objects in its quest to figure out whether the given SHA1 (for a commit or
tree) was ever tagged.

This version is reworked incorporating sanity, feature and style fixes from
Junio.

Usage: git-findtags.perl [ -t ] <commit-or-tree-sha1>

Signed-off-by: Martin Langhoff <martin@catalyst.net.nz>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2005-10-13 10:47:42 -07:00

94 lines
2.1 KiB
Perl
Executable file

#!/usr/bin/perl -w
#
# Copyright (c) 2005 Martin Langhoff
#
# Walk the tags and find if they match a commit
# expects a SHA1 of a commit. Option -t enables
# searching trees too.
#
use strict;
use File::Basename;
use File::Find;
use Getopt::Std;
my $git_dir = $ENV{GIT_DIR} || '.git';
$git_dir =~ s|/$||; # chomp trailing slash
# options
our $opt_t;
getopts("t") || usage();
my @tagfiles = `find $git_dir/refs/tags -follow -type f`; # haystack
my $target = shift @ARGV; # needle
unless ($target) {
usage();
}
# drive the processing from the find hook
# slower, safer (?) than the find utility
find( { wanted => \&process,
no_chdir => 1,
follow => 1,
}, "$git_dir/refs/tags");
sub process {
my ($dev,$ino,$mode,$nlink,$uid,$gid);
# process only regular files
unless ((($dev,$ino,$mode,$nlink,$uid,$gid) = lstat($_)) && -f _) {
return 1; # ignored anyway
}
my $tagfile = $_;
chomp $tagfile;
my $tagname = substr($tagfile, length($git_dir.'/refs/tags/'));
my $tagid = quickread($tagfile);
chomp $tagid;
# is it just a soft tag?
if ($tagid eq $target) {
print "$tagname\n";
return 1; # done with this tag
}
# grab the first 2 lines (the whole tag could be large)
my $tagobj = `git-cat-file tag $tagid | head -n2 `;
if ($tagobj =~ m/^type commit$/m) { # only deal with commits
if ($tagobj =~ m/^object $target$/m) { # match on the commit
print "$tagname\n";
} elsif ( $opt_t && # follow the commit
$tagobj =~ m/^object (\S+)$/m) { # and try to match trees
my $commitid = $1;
my $commitobj = `git-cat-file commit $commitid | head -n1`;
chomp $commitobj;
$commitobj =~ m/^tree (\S+)$/;
my $treeid = $1;
if ($target eq $treeid) {
print "$tagname\n";
}
}
}
}
sub quickread {
my $file = shift;
local $/; # undef: slurp mode
open FILE, "<$file"
or die "Cannot open $file : $!";
my $content = <FILE>;
close FILE;
return $content;
}
sub usage {
print STDERR <<END;
Usage: ${\basename $0} # find tags for a commit or tree
[ -t ] <commit-or-tree-sha1>
END
exit(1);
}