X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=Debian%2FDgit.pm;h=5c43f0257b82860f0e6cff3e7d85040c144cd8df;hb=e31362aa5853ada39b14be5bbdc46cbda58e20a6;hp=a453f352718b33a5567e040cdd9302973c40b279;hpb=05532651f81d706de1fab66e8ebe97b9f646b1f9;p=dgit.git
diff --git a/Debian/Dgit.pm b/Debian/Dgit.pm
index a453f352..5c43f025 100644
--- a/Debian/Dgit.pm
+++ b/Debian/Dgit.pm
@@ -1,13 +1,33 @@
# -*- perl -*-
+# dgit
+# Debian::Dgit: functions common to dgit and its helpers and servers
+#
+# Copyright (C) 2015-2016 Ian Jackson
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
package Debian::Dgit;
use strict;
use warnings;
+use Carp;
use POSIX;
use IO::Handle;
use Config;
+use Digest::SHA;
+use Data::Dumper;
BEGIN {
use Exporter ();
@@ -16,8 +36,12 @@ BEGIN {
$VERSION = 1.00;
@ISA = qw(Exporter);
@EXPORT = qw(setup_sigwarn
- debiantag server_branch server_ref
- stat_exists fail ensuredir waitstatusmsg failedcmd
+ debiantags debiantag_old debiantag_new
+ server_branch server_ref
+ stat_exists link_ltarget
+ hashfile
+ fail ensuredir executable_on_path
+ waitstatusmsg failedcmd
cmdoutput cmdoutput_errok
git_rev_parse git_get_ref git_for_each_ref
git_for_each_tag_referring is_fast_fwd
@@ -119,12 +143,23 @@ sub debugcmd {
printcmd(\*DEBUG,$debugprefix.$extraprefix,@_) if $debuglevel>0;
}
-sub debiantag ($$) {
+sub debiantag_old ($$) {
my ($v,$distro) = @_;
$v =~ y/~:/_%/;
return "$distro/$v";
}
+sub debiantag_new ($$) {
+ my ($v,$distro) = @_;
+ $v =~ y/~:/_%/;
+ return "archive/$distro/$v";
+}
+
+sub debiantags ($$) {
+ my ($version,$distro) = @_;
+ map { $_->($version, $distro) } (\&debiantag_new, \&debiantag_old);
+}
+
sub server_branch ($) { return "$branchprefix/$_[0]"; }
sub server_ref ($) { return "refs/".server_branch($_[0]); }
@@ -141,6 +176,7 @@ sub _us () {
sub fail {
my $s = "@_\n";
+ $s =~ s/\n\n$/\n/;
my $prefix = _us().": ";
$s =~ s/^/$prefix/gm;
die $s;
@@ -153,6 +189,17 @@ sub ensuredir ($) {
die "mkdir $dir: $!";
}
+sub executable_on_path ($) {
+ my ($program) = @_;
+ return 1 if $program =~ m{/};
+ my @path = split /:/, ($ENV{PATH} // "/usr/local/bin:/bin:/usr/bin");
+ foreach my $pe (@path) {
+ my $here = "$pe/$program";
+ return $here if stat_exists $here && -x _;
+ }
+ return undef;
+}
+
our @signames = split / /, $Config{sig_name};
sub waitstatusmsg () {
@@ -171,8 +218,19 @@ sub waitstatusmsg () {
}
sub failedcmd {
+ # Expects $!,$? as set by close - see below.
+ # To use with system(), set $?=-1 first.
+ #
+ # Actual behaviour of perl operations:
+ # success $!==0 $?==0 close of piped open
+ # program failed $!==0 $? >0 close of piped open
+ # syscall failure $! >0 $?=-1 close of piped open
+ # failure $! >0 unchanged close of something else
+ # success trashed $?==0 system
+ # program failed trashed $? >0 system
+ # syscall failure $! >0 unchanged system
{ local ($!); printcmd \*STDERR, _us().": failed command:", @_ or die $!; };
- if ($!) {
+ if ($? < 0) {
fail "failed to fork/exec: $!";
} elsif ($?) {
fail "subprocess ".waitstatusmsg();
@@ -182,9 +240,9 @@ sub failedcmd {
}
sub cmdoutput_errok {
- die Dumper(\@_)." ?" if grep { !defined } @_;
+ confess Dumper(\@_)." ?" if grep { !defined } @_;
debugcmd "|",@_;
- open P, "-|", @_ or die $!;
+ open P, "-|", @_ or die "$_[0] $!";
my $d;
$!=0; $?=0;
{ local $/ = undef; $d =
; }
@@ -207,6 +265,22 @@ sub cmdoutput {
return $d;
}
+sub link_ltarget ($$) {
+ my ($old,$new) = @_;
+ lstat $old or return undef;
+ if (-l _) {
+ $old = cmdoutput qw(realpath --), $old;
+ }
+ link $old, $new or die "link $old $new: $!";
+}
+
+sub hashfile ($) {
+ my ($fn) = @_;
+ my $h = Digest::SHA->new(256);
+ $h->addfile($fn);
+ return $h->hexdigest();
+}
+
sub git_rev_parse ($) {
return cmdoutput qw(git rev-parse), "$_[0]~0";
}
@@ -216,7 +290,9 @@ sub git_for_each_ref ($$;$) {
# calls $func->($objid,$objtype,$fullrefname,$reftail);
# $reftail is RHS of ref after refs/[^/]+/
# breaks if $pattern matches any ref `refs/blah' where blah has no `/'
- my @cmd = (qw(git for-each-ref), $pattern);
+ # $pattern may be an array ref to mean multiple patterns
+ $pattern = [ $pattern ] unless ref $pattern;
+ my @cmd = (qw(git for-each-ref), @$pattern);
if (defined $gitdir) {
@cmd = ('sh','-ec','cd "$1"; shift; exec "$@"','x', $gitdir, @cmd);
}