From 11f6f1e04d23e0a0ad29292996177b3b52ce784e Mon Sep 17 00:00:00 2001 From: joey Date: Mon, 4 Oct 1999 01:56:51 +0000 Subject: [PATCH] r290: * Dh_Lib.pm: fixed bug in xargs() that made boundry words be skipped. --- Dh_Lib.pm | 251 +++++++++++++++++++++++++++++++++++------------ debian/changelog | 6 ++ 2 files changed, 193 insertions(+), 64 deletions(-) diff --git a/Dh_Lib.pm b/Dh_Lib.pm index c9b964c..4c3841c 100644 --- a/Dh_Lib.pm +++ b/Dh_Lib.pm @@ -5,19 +5,29 @@ # Joey Hess, GPL copyright 1997, 1998. package Dh_Lib; +use strict; use Exporter; -use vars qw(%dh); +use vars qw(@ISA @EXPORT %dh); @ISA=qw(Exporter); @EXPORT=qw(&init &doit &complex_doit &verbose_print &error &warning &tmpdir &pkgfile &pkgext &isnative &autoscript &filearray &GetPackages + &xargs %dh); +my $max_compat=2; + sub init { + # If DH_OPTIONS is set, prepend it @ARGV. + if (defined($ENV{DH_OPTIONS})) { + unshift @ARGV,split(/\s+/,$ENV{DH_OPTIONS}); + } + # Check to see if an argument on the command line starts with a dash. - # if so, we need to pass this off to the resource intensive Getopt::Long, - # which I'd prefer to avoid loading at all if possible. + # if so, we need to pass this off to the resource intensive + # Getopt::Long, which I'd prefer to avoid loading at all if possible. my $parseopt=undef; + my $arg; foreach $arg (@ARGV) { if ($arg=~m/^-/) { $parseopt=1; @@ -30,30 +40,58 @@ sub init { %dh=Dh_Getopt::parseopts(); } + # Check to see if DH_VERBOSE environment variable was set, if so, + # make sure verbose is on. + if (defined $ENV{DH_VERBOSE} && $ENV{DH_VERBOSE} ne "") { + $dh{VERBOSE}=1; + } + + # Check to see if DH_NO_ACT environment variable was set, if so, + # make sure no act mode is on. + if (defined $ENV{DH_NO_ACT} && $ENV{DH_NO_ACT} ne "") { + $dh{NO_ACT}=1; + } + # Get the name of the main binary package (first one listed in # debian/control). my @allpackages=GetPackages(); $dh{MAINPACKAGE}=$allpackages[0]; - # Check if packages to build have been specified, if not, fall back to + # Check if packages to build have been specified, if not, fall back to # the default, doing them all. - if (! @{$dh{DOPACKAGES}}) { - if ($dh{DH_DOINDEP} || $dh{DH_DOARCH}) { - error("I have no package to build."); + if (! defined $dh{DOPACKAGES} || ! @{$dh{DOPACKAGES}}) { + if ($dh{DOINDEP} || $dh{DOARCH} || $dh{DOSAME}) { + # User specified that all arch (in)dep package be + # built, and there are none of that type. + error("I have no package to act on"); } push @{$dh{DOPACKAGES}},@allpackages; } # Check to see if -P was specified. If so, we can only act on a single # package. - if ($dh{TMPDIR} || $#{$dh{DOPACKAGES}} > 0) { - error("-P was specified, but multiple packages would be acted on."); + if ($dh{TMPDIR} && $#{$dh{DOPACKAGES}} > 0) { + error("-P was specified, but multiple packages would be acted on (".join(",",@{$dh{DOPACKAGES}}).")."); } # Figure out which package is the first one we were instructed to build. # This package gets special treatement: files and directories specified on # the command line may affect it. $dh{FIRSTPACKAGE}=${$dh{DOPACKAGES}}[0]; + + # Split the U_PARAMS up into an array. + my $u=$dh{U_PARAMS}; + undef $dh{U_PARAMS}; + if (defined $u) { + push @{$dh{U_PARAMS}}, split(/\s+/,$u); + } +} + +# Escapes out shell metacharacters in a word of shell script. +sub escape_shell { my $word=shift; + # This list is from _Unix in a Nutshell_. (except '#') + $word=~s/([\s!"\$()*+#;<>?@\[\]\\`|~])/\\$1/g; + return $word; } # Run a command, and display the command to stdout if verbose mode is on. @@ -63,7 +101,7 @@ sub init { # Note that this cannot handle complex commands, especially anything # involving redirection. Use complex_doit instead. sub doit { - verbose_print(join(" ",,@_)); + verbose_print(join(" ",map { escape_shell($_) } @_)); if (! $dh{NO_ACT}) { system(@_) == 0 @@ -72,10 +110,53 @@ sub doit { } } -# This is an identical command to doit, except the parameters passed to it -# can include complex shell stull like redirection and compound commands. +# Run a command and display the command to stdout if verbose mode is on. +# Use doit() if you can, instead of this function, because this function +# forks a shell. However, this function can handle more complicated stuff +# like redirection. sub complex_doit { - error("complex_doit() not yet supported"); + verbose_print(join(" ",@_)); + + if (! $dh{NO_ACT}) { + # The join makes system get a scalar so it forks off a shell. + system(join(" ",@_)) == 0 + || error("command returned error code"); + } +} + +# Run a command that may have a huge number of arguments, like xargs does. +# Pass in a reference to an array containing the arguments, and then other +# parameters that are the command and any parameters that should be passed to +# it each time. +sub xargs { + my $args=shift; + + # The kernel can accept command lines up to 20k worth of characters. + my $command_max=20000; + + # Figure out length of static portion of command. + my $static_length=0; + foreach (@_) { + $static_length+=length($_)+1; + } + + my @collect=(); + my $length=$static_length; + foreach (@$args) { + if (length($_) + 1 + $static_length > $command_max) { + error("This command is greater than the maximum command size allowed by the kernel, and cannot be split up further. What on earth are you doing? \"@_ $_\""); + } + $length+=length($_) + 1; + if ($length < $command_max) { + push @collect, $_; + } + else { + doit(@_,@collect) if $#collect > -1; + @collect=($_); + $length=$static_length + length($_) + 1; + } + } + doit(@_,@collect) if $#collect > -1; } # Print something if the verbose flag is on. @@ -93,19 +174,46 @@ sub error { my $message=shift; # Output a warning. sub warning { my $message=shift; - my $fn=$0; - $fn=~s:.*/(.*?):$1:; - print STDERR "$fn: $message\n"; + print STDERR basename($0).": $message\n"; +} + +# Returns the basename of the argument passed to it. +sub basename { my $fn=shift; + $fn=~s:^.*/(.*?)$:$1:; + return $fn; +} + +# Returns the directory name of the argument passed to it. +sub dirname { my $fn=shift; + $fn=~s:^(.*)/.*?$:$1:; + return $fn; +} + +# Pass in a number, will return true iff the current compatability level +# is equal to that number. +sub compat { + my $num=shift; + + my $c=1; + if (defined $ENV{DH_COMPAT}) { + $c=$ENV{DH_COMPAT}; + } + + if ($c > $max_compat) { + error("Sorry, but $max_compat is the highest compatability level of debhelper currently supported."); + } + + return ($c == $num); } # Pass it a name of a binary package, it returns the name of the tmp dir to # use, for that package. -# This is for back-compatability with the debian/tmp tradition. sub tmpdir { my $package=shift; if ($dh{TMPDIR}) { return $dh{TMPDIR}; } - elsif ($package eq $dh{MAINPACKAGE}) { + elsif (compat(1) && $package eq $dh{MAINPACKAGE}) { + # This is for back-compatability with the debian/tmp tradition. return "debian/tmp"; } else { @@ -120,10 +228,10 @@ sub tmpdir { my $package=shift; # the main package, it will look for debian/foo, and if found, return that. # Failing that, it will return nothing. sub pkgfile { my $package=shift; my $filename=shift; - if (-e "debian/$package.$filename") { + if (-f "debian/$package.$filename") { return "debian/$package.$filename"; } - elsif ($package eq $dh{MAINPACKAGE} && -e "debian/$filename") { + elsif ($package eq $dh{MAINPACKAGE} && -f "debian/$filename") { return "debian/$filename"; } return ""; @@ -132,7 +240,7 @@ sub pkgfile { my $package=shift; my $filename=shift; # Pass it a name of a binary package, it returns the name to prefix to files # in debian for this package. sub pkgext { my $package=shift; - if ($package ne $MAINPACKAGE) { + if ($package ne $dh{MAINPACKAGE}) { return "$package."; } return ""; @@ -142,30 +250,30 @@ sub pkgext { my $package=shift; # As a side effect, sets $dh{VERSION} to the version of this package. { # Caches return code so it only needs to run dpkg-parsechangelog once. - my $isnative_cache; + my %isnative_cache; sub isnative { my $package=shift; - if ($isnative_cache eq undef) { + if (! defined $isnative_cache{$package}) { # Make sure we look at the correct changelog. my $isnative_changelog=pkgfile($package,"changelog"); if (! $isnative_changelog) { $isnative_changelog="debian/changelog"; } - + # Get the package version. my $version=`dpkg-parsechangelog -l$isnative_changelog`; - ($dh{VERSION})=$version=~s/[^|\n]Version: \(.*\)\n//m; - + ($dh{VERSION})=$version=~m/Version: (.*)/m; + # Is this a native Debian package? if ($dh{VERSION}=~m/.*-/) { - $isnative_cache=1; + $isnative_cache{$package}=0; } else { - $isnative_cache=0; + $isnative_cache{$package}=1; } } - return $isnative_cache; + return $isnative_cache{$package}; } } @@ -173,52 +281,66 @@ sub pkgext { my $package=shift; # Only works if the script has #DEBHELPER# in it. # # Parameters: -# 1: script to add to -# 2: filename of snippet -# 3: sed commands to run on the snippet. Ie, s/#PACKAGE#/$PACKAGE/ -sub autoscript { - error "autoscript() not yet implemented (lazy, lazy!)"; -# autoscript_script=$1 -# autoscript_filename=$2 -# autoscript_sed=$3 -# autoscript_debscript=debian/`pkgext $PACKAGE`$autoscript_script.debhelper -# -# if [ -e "$DH_AUTOSCRIPTDIR/$autoscript_filename" ]; then -# autoscript_filename="$DH_AUTOSCRIPTDIR/$autoscript_filename" -# else -# if [ -e "/usr/lib/debhelper/autoscripts/$autoscript_filename" ]; then -# autoscript_filename="/usr/lib/debhelper/autoscripts/$autoscript_filename" -# else -# error "/usr/lib/debhelper/autoscripts/$autoscript_filename does not exist" -# fi -# fi -# -# complex_doit "echo \"# Automatically added by `basename $0`\" >> $autoscript_debscript" -# complex_doit "sed \"$autoscript_sed\" $autoscript_filename >> $autoscript_debscript" -# complex_doit "echo '# End automatically added section' >> $autoscript_debscript" +# 1: package +# 2: script to add to +# 3: filename of snippet +# 4: sed to run on the snippet. Ie, s/#PACKAGE#/$PACKAGE/ +sub autoscript { my $package=shift; my $script=shift; my $filename=shift; my $sed=shift || ""; + # This is the file we will append to. + my $outfile="debian/".pkgext($package)."$script.debhelper"; + + # Figure out what shell script snippet to use. + my $infile; + if (defined($ENV{DH_AUTOSCRIPTDIR}) && + -e "$ENV{DH_AUTOSCRIPTDIR}/$filename") { + $infile="$ENV{DH_AUTOSCRIPTDIR}/$filename"; + } + else { + if (-e "/usr/share/debhelper/autoscripts/$filename") { + $infile="/usr/share/debhelper/autoscripts/$filename"; + } + else { + error("/usr/share/debhelper/autoscripts/$filename does not exist"); + } + } + + # TODO: do this in perl, perhaps? + complex_doit("echo \"# Automatically added by ".basename($0)."\">> $outfile"); + complex_doit("sed \"$sed\" $infile >> $outfile"); + complex_doit("echo '# End automatically added section' >> $outfile"); } # Reads in the specified file, one word at a time, and returns an array of # the result. -sub filearray { $file=shift; +sub filearray { my $file=shift; my @ret; open (DH_FARRAY_IN,"<$file") || error("cannot read $file: $1"); while () { - push @ret,split(/\s/,$_); + push @ret,split(' ',$_); } - close DH_ARRAY; + close DH_FARRAY_IN; return @ret; } # Returns a list of packages in the control file. -# Must pass "arch" or "indep" to specify arch-dependant or -independant -# packages. If nothing is specified, returns all packages. -sub GetPackages { $type=shift; - my $package; - my $arch; - my @list; - open (CONTROL,") { chomp; @@ -233,10 +355,11 @@ sub GetPackages { $type=shift; if ($package && (($type eq 'indep' && $arch eq 'all') || ($type eq 'arch' && $arch ne 'all') || + ($type eq 'same' && ($arch eq 'any' || $arch =~ /\b$buildarch\b/)) || ! $type)) { push @list, $package; - undef $package; - undef $arch; + $package=""; + $arch=""; } } } diff --git a/debian/changelog b/debian/changelog index 2dd8d7f..a1dbb0f 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +debhelper (2.0.58) unstable; urgency=low + + * Dh_Lib.pm: fixed bug in xargs() that made boundry words be skipped. + + -- Joey Hess Sun, 3 Oct 1999 18:55:29 -0700 + debhelper (2.0.57) unstable; urgency=low * Added note to man pages of commands that use autoscript to note they are -- 2.39.5