chiark / gitweb /
5c079a68d3abfa8e4ce89b969027337244d4c53b
[dgit.git] / Debian / Dgit.pm
1 # -*- perl -*-
2
3 package Debian::Dgit;
4
5 use strict;
6 use warnings;
7
8 use POSIX;
9 use IO::Handle;
10
11 BEGIN {
12     use Exporter   ();
13     our ($VERSION, @ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS);
14
15     $VERSION     = 1.00;
16     @ISA         = qw(Exporter);
17     @EXPORT      = qw(debiantag server_branch server_ref
18                       stat_exists git_for_each_ref
19                       $package_re $component_re $branchprefix
20                       initdebug enabledebug printdebug $debugprefix $debug
21                       shellquote printcmd);
22     %EXPORT_TAGS = ( policyflags => [qw(NOFFCHECK FRESHREPO)] );
23     @EXPORT_OK   = @{ $EXPORT_TAGS{policyflags} };
24 }
25
26 our @EXPORT_OK;
27
28 our $package_re = '[0-9a-z][-+.0-9a-z]*';
29 our $component_re = '[0-9a-zA-Z][-+.0-9a-zA-Z]*';
30 our $branchprefix = 'dgit';
31
32 # policy hook exit status bits
33 # see dgit-repos-server head comment for documentation
34 # 1 is reserved in case something fails with `exit 1'
35 sub NOFFCHECK () { return 0x2; }
36 sub FRESHREPO () { return 0x4; }
37 # 0x80 is reserved
38
39 sub debiantag ($) { 
40     my ($v) = @_;
41     $v =~ y/~:/_%/;
42     return "debian/$v";
43 }
44
45 sub server_branch ($) { return "$branchprefix/$_[0]"; }
46 sub server_ref ($) { return "refs/".server_branch($_[0]); }
47
48 sub stat_exists ($) {
49     my ($f) = @_;
50     return 1 if stat $f;
51     return 0 if $!==&ENOENT;
52     die "stat $f: $!";
53 }
54
55 sub git_for_each_ref ($$) {
56     my ($pattern,$func) = @_;
57     # calls $func->($objid,$objtype,$fullrefname,$reftail);
58     # $reftail is RHS of ref after refs/\w+/
59     # breaks if $pattern matches any ref `refs/blah' where blah has no `/'
60     my $fh = new IO::File "-|", qw(git for-each-ref), $pattern or die $!;
61     while (<$fh>) {
62         m#^(\w+)\s+(\w+)\s+(refs/\w+/(\S+))\s# or die "$_ ?";
63         $func->($1,$2,$3,$4);
64     }
65     $!=0; $?=0; close $fh or die "$pattern $? $!";
66 }
67
68 sub git_for_each_tag_referring ($$) {
69     my ($objreferring, $func) = @_;
70     # calls $func->($objid,$fullrefname,$tagname);
71     git_for_each_ref('refs/tags', sub {
72         my ($objid,$objtype,$fullrefname,$tagname) = @_;
73         next unless $objtype eq 'tag';
74         next if defined $objreferring and $objid ne $objreferring;
75         $func->($objid,$fullrefname,$tagname);
76     });
77 }
78
79 our $debugprefix;
80 our $debug = 0;
81
82 sub initdebug ($) { 
83     ($debugprefix) = @_;
84     open ::DEBUG, ">/dev/null" or die $!;
85 }
86
87 sub enabledebug () {
88     open ::DEBUG, ">&STDERR" or die $!;
89     ::DEBUG->autoflush(1);
90     $debug ||= 1;
91 }
92     
93 sub printdebug {
94     print ::DEBUG $debugprefix, @_ or die $!;
95 }
96
97 sub shellquote {
98     my @out;
99     local $_;
100     foreach my $a (@_) {
101         $_ = $a;
102         if (m{[^-=_./0-9a-z]}i) {
103             s{['\\]}{'\\$&'}g;
104             push @out, "'$_'";
105         } else {
106             push @out, $_;
107         }
108     }
109     return join ' ', @out;
110 }
111
112 sub printcmd {
113     my $fh = shift @_;
114     my $intro = shift @_;
115     print $fh $intro," " or die $!;
116     print $fh shellquote @_ or die $!;
117     print $fh "\n" or die $!;
118 }
119
120 1;