summaryrefslogtreecommitdiff
path: root/git-findtags.perl
blob: 745affe3a68471823492f37568b8daab2966a8ab (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#!/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);
}