| #!/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); |
| } |