1#!/usr/bin/perl 2# vim: set ai shiftwidth=4 tabstop=4 expandtab: 3 4# dget - Download Debian source and binary packages 5# Copyright (C) 2005-2013 Christoph Berg <myon@debian.org> 6# Modifications Copyright (C) 2005-06 Julian Gilbey <jdg@debian.org> 7# 8# This program is free software; you can redistribute it and/or modify 9# it under the terms of the GNU General Public License as published by 10# the Free Software Foundation; either version 2 of the License, or 11# (at your option) any later version. 12# 13# This program is distributed in the hope that it will be useful, 14# but WITHOUT ANY WARRANTY; without even the implied warranty of 15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16# GNU General Public License for more details. 17# 18# You should have received a copy of the GNU General Public License 19# along with this program; if not, write to the Free Software 20# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 21 22# 2005-10-04 cb: initial release 23# 2005-12-11 cb: -x option, update documentation 24# 2005-12-31 cb: -b, -q options, use getopt 25# 2006-01-10 cb: support new binnmu version scheme 26# 2006-11-12 cb: also look in other places in the local filesystem (e.g. pbuilder result dir) 27# Later modifications: see debian/changelog 28 29use strict; 30use warnings; 31use Cwd qw(abs_path); 32use IO::Dir; 33use IO::File; 34use Digest::MD5; 35use Devscripts::Compression; 36use Dpkg::Control; 37use Getopt::Long qw(:config bundling permute no_getopt_compat); 38use File::Basename; 39 40# global variables 41 42my $progname = basename($0, '.pl'); # the '.pl' is for when we're debugging 43my $found_dsc; 44my $wget; 45my $opt; 46my $backup_dir = "backup"; 47my @dget_path = ("/var/cache/apt/archives"); 48my $modified_conf_msg; 49 50my $compression_re = compression_get_file_extension_regex(); 51 52# use curl if installed, wget otherwise 53if (system("command -v curl >/dev/null 2>&1") == 0) { 54 $wget = "curl"; 55} elsif (system("command -v wget >/dev/null 2>&1") == 0) { 56 $wget = "wget"; 57} else { 58 die 59"$progname: can't find either curl or wget; you need at least one of these\ninstalled to run me!\n"; 60} 61 62# functions 63 64sub usage { 65 print <<"EOT"; 66Usage: $progname [options] URL ... 67 $progname [options] [--all] package[=version] ... 68 69Downloads Debian packages (source and binary) from the specified URLs (first form), 70or using the mirror configured in /etc/apt/sources.list(.d) (second form). 71It is capable of downloading several packages at once. 72 73 -a, --all Package is a source package; download all binary packages 74 -b, --backup Move files that would be overwritten to ./backup 75 -q, --quiet Suppress wget/curl output 76 -d, --download-only 77 Do not extract downloaded source 78 -x, --extract Unpack downloaded source (default) 79 -u, --allow-unauthenticated 80 Do not attempt to verify source package signature 81 --build Build package with dpkg-buildpackage after download 82 --path DIR Check these directories in addition to the apt archive; 83 if DIR='' then clear current list (may be used multiple 84 times) 85 --insecure Do not check SSL certificates when downloading 86 --no-cache Disable server-side HTTP cache 87 --no-conf Don\'t read devscripts config files; 88 must be the first option given 89 -h, --help This message 90 -V, --version Version information 91 92Default settings modified by devscripts configuration files: 93$modified_conf_msg 94EOT 95} 96 97sub version { 98 print <<"EOF"; 99This is $progname, from the Debian devscripts package, version ###VERSION### 100This code is copyright 2005-08 by Christoph Berg <myon\@debian.org>. 101Modifications copyright 2005-06 by Julian Gilbey <jdg\@debian.org>. 102All rights reserved. 103This program comes with ABSOLUTELY NO WARRANTY. 104You are free to redistribute this code under the terms of the 105GNU General Public License, version 2 or later. 106EOF 107} 108 109sub wget { 110 my ($file, $url) = @_; 111 112 # schemes not supported by all backends 113 if ($url =~ m!^(file|copy):(.+)!) { 114 my $path = abs_path($2); 115 unless ($path) { 116 warn "$progname: unable to resolve full path for $2: $!\n"; 117 return 1; 118 } 119 if ($1 eq "copy" or not link($path, $file)) { 120 system 'cp', '-aL', $path, $file; 121 return $? >> 8; 122 } 123 return; 124 } 125 126 my @cmd = ($wget); 127 # curl does not follow document moved headers, and does not exit 128 # with a non-zero error code by default if a document is not found 129 push @cmd, "-f", "-L" if $wget eq "curl"; 130 push @cmd, ($wget eq "wget" ? "-nv" : ("-s", "-S")) if $opt->{'quiet'}; 131 push @cmd, ($wget eq "wget" ? "--no-check-certificate" : "--insecure") 132 if $opt->{'insecure'}; 133 push @cmd, 134 ($wget eq "wget" ? "--no-cache" : ("--header", "Pragma: no-cache")) 135 if $opt->{'no-cache'}; 136 push @cmd, ($wget eq "wget" ? "-O" : "-o"); 137 system @cmd, $file, $url; 138 return $? >> 8; 139} 140 141sub backup_or_unlink { 142 my $file = shift; 143 return unless -e $file; 144 if ($opt->{'backup'}) { 145 unless (-d $backup_dir) { 146 mkdir $backup_dir or die "mkdir $backup_dir: $!"; 147 } 148 rename $file, "$backup_dir/$file" 149 or die "rename $file $backup_dir/$file: $!"; 150 } else { 151 unlink $file or die "unlink $file: $!"; 152 } 153} 154 155# some files both are in .dsc and .changes, download only once 156my %seen; 157 158sub get_file { 159 my ($dir, $file, $md5sum) = @_; 160 return 1 if $seen{$file}; 161 162 if ($md5sum eq "unlink") { 163 backup_or_unlink($file); 164 } 165 166 # check the existing file's md5sum 167 if (-e $file) { 168 my $md5 = Digest::MD5->new; 169 my $fh5 = new IO::File($file) or die "$file: $!"; 170 my $md5sum_new = Digest::MD5->new->addfile($fh5)->hexdigest(); 171 close $fh5; 172 if (not $md5sum or ($md5sum_new eq $md5sum)) { 173 print "$progname: using existing $file\n" unless $opt->{'quiet'}; 174 } else { 175 print "$progname: removing $file (md5sum does not match)\n" 176 unless $opt->{'quiet'}; 177 backup_or_unlink($file); 178 } 179 } 180 181 # look for the file in other local directories 182 unless (-e $file) { 183 foreach my $path (@dget_path) { 184 next unless -e "$path/$file"; 185 186 my $fh5 = new IO::File("$path/$file") or next; 187 my $md5 = Digest::MD5->new; 188 my $md5sum_new = Digest::MD5->new->addfile($fh5)->hexdigest(); 189 close $fh5; 190 191 if ($md5sum_new eq $md5sum) { 192 if (link "$path/$file", $file) { 193 print "$progname: using $path/$file (hardlink)\n" 194 unless $opt->{'quiet'}; 195 } else { 196 print "$progname: using $path/$file (copy)\n" 197 unless $opt->{'quiet'}; 198 system 'cp', '-aL', "$path/$file", $file; 199 } 200 last; 201 } 202 } 203 } 204 205 # finally get it from the web 206 unless (-e $file) { 207 print "$progname: retrieving $dir/$file\n" unless $opt->{'quiet'}; 208 if (wget($file, "$dir/$file")) { 209 warn "$progname: $wget $file $dir/$file failed\n"; 210 unlink $file; 211 } 212 } 213 214 # try apt-get if it is still not there 215 my $ext = $compression_re; 216 if (not -e $file 217 and $file =~ m!^([a-z0-9][a-z0-9.+-]+)_[^/]+\.(?:diff|tar)\.$ext$!) { 218 my @cmd = ('apt-get', 'source', '--print-uris', $1); 219 my $cmd = join ' ', @cmd; 220 open(my $apt, '-|', @cmd) or die "$cmd: $!"; 221 while (<$apt>) { 222 if (/'(\S+)'\s+\S+\s+\d+\s+([\da-f]+)/i and $2 eq $md5sum) { 223 if (wget($file, $1)) { 224 warn "$progname: $wget $file $1 failed\n"; 225 unlink $file; 226 } 227 } 228 } 229 close $apt; 230 } 231 232 # still not there, return 233 unless (-e $file) { 234 return 0; 235 } 236 237 $seen{$file} = 1; 238 239 if ($file =~ /\.(?:changes|dsc)$/) { 240 parse_file($dir, $file); 241 } 242 if ($file =~ /\.dsc$/) { 243 $found_dsc = $file; 244 } 245 246 return 1; 247} 248 249sub parse_file { 250 my ($dir, $file) = @_; 251 252 my $fh = new IO::File($file); 253 open $fh, $file or die "$file: $!"; 254 while (<$fh>) { 255 if (/^ ([0-9a-f]{32}) (?:\S+ )*(\S+)$/) { 256 my ($_sum, $_file) = ($1, $2); 257 $_file !~ m,[/\x00], 258 or die "File name contains invalid characters: $_file"; 259 get_file($dir, $_file, $_sum) or return; 260 } 261 } 262 close $fh; 263} 264 265sub quote_version { 266 my $version = shift; 267 $version = quotemeta($version); 268 $version =~ s/^([^:]+:)/(?:$1)?/; # Epochs are not part of the filename 269 $version 270 =~ s/-([^.-]+)$/-$1(?:\\+b\\d+|\.0\.\\d+)?/; # BinNMU: -x -> -x.0.1 -x+by 271 $version =~ s/-([^.-]+\.[^.-]+)$/-$1(?:\\+b\\d+|\.\\d+)?/ 272 ; # -x.y -> -x.y.1 -x.y+bz 273 return $version; 274} 275 276# we reinvent "apt-get -d install" here, without requiring root 277# (and we do not download dependencies) 278sub apt_get { 279 my ($package, $version) = @_; 280 281 my ($archpackage, $arch) = $package; 282 ($package, $arch) = split(/:/, $package, 2); 283 284 my $qpackage = quotemeta($package); 285 my $qversion = quote_version($version) if $version; 286 my @hosts; 287 288 my $apt = IO::File->new("LC_ALL=C apt-cache policy $archpackage |") 289 or die "$!"; 290 OUTER: while (<$apt>) { 291 if (not $version and /^ Candidate: (.+)/) { 292 $version = $1; 293 $qversion = quote_version($version); 294 } 295 if ($qversion and /^ [ *]{3} ($qversion) \d/) { 296 while (<$apt>) { 297 last OUTER unless /^ *(?:\d+) (\S+)/; 298 (my $host = $1) =~ s@/$@@; 299 next if $host eq '/var/lib/dpkg/status'; 300 push @hosts, $host; 301 } 302 } 303 } 304 close $apt; 305 unless ($version) { 306 die "$progname: $archpackage has no installation candidate\n"; 307 } 308 unless (@hosts) { 309 die 310"$progname: no hostnames in apt-cache policy $archpackage for version $version found\n"; 311 } 312 313 $apt = IO::File->new("LC_ALL=C apt-cache show $archpackage=$version |") 314 or die "$!"; 315 my ($v, $p, $filename, $md5sum); 316 while (<$apt>) { 317 if (/^Package: $qpackage$/) { 318 $p = $package; 319 } 320 if (/^Version: $qversion$/) { 321 $v = $version; 322 } 323 if (/^Filename: (.*)/) { 324 $filename = $1; 325 } 326 if (/^MD5sum: (.*)/) { 327 $md5sum = $1; 328 } 329 if (/^Description:/) { # we assume this is the last field 330 if ($p and $v and $filename) { 331 last; 332 } 333 undef $p; 334 undef $v; 335 undef $filename; 336 undef $md5sum; 337 } 338 } 339 close $apt; 340 341 unless ($filename) { 342 die "$progname: no filename for $archpackage ($version) found\n"; 343 } 344 345 # find deb lines matching the hosts in the policy output 346 my %repositories; 347# the regexp within the map below can be removed and replaced with only the quotemeta statement once bug #154868 is fixed 348 my $host_re = '(?:' . ( 349 join '|', 350 map { 351 my $host = quotemeta; 352 $host =~ s@^(\w+\\:\\/\\/[^:/]+)\\/@$1(?::[0-9]+)?\\/@; 353 $host; 354 } @hosts 355 ) . ')'; 356 357 my @sources; 358 if (-f "/etc/apt/sources.list") { 359 push @sources, "/etc/apt/sources.list"; 360 } 361 my %dir; 362 tie %dir, "IO::Dir", "/etc/apt/sources.list.d"; 363 foreach (keys %dir) { 364 next unless /\.list$/; 365 push @sources, "/etc/apt/sources.list.d/$_"; 366 } 367 368 foreach my $source (@sources) { 369 $apt = IO::File->new($source) or die "$source: $!"; 370 while (<$apt>) { 371 if (/^\s*deb\s*(?:\[[^]]*\]\s*)?($host_re\b)/) { 372 $repositories{$1} = 1; 373 } 374 } 375 close $apt; 376 } 377 unless (%repositories) { 378 die "no repository found in /etc/apt/sources.list or sources.list.d"; 379 } 380 381 # try each repository in turn 382 foreach my $repository (keys %repositories) { 383 my ($dir, $file) = ($repository, $filename); 384 if ($filename =~ /(.*)\/([^\/]*)$/) { 385 ($dir, $file) = ("$repository/$1", $2); 386 } 387 388 get_file($dir, $file, $md5sum) and return; 389 } 390 exit 1; 391} 392 393# main program 394 395# Now start by reading configuration files and then command line 396# The next stuff is boilerplate 397 398my ($dget_path, $dget_unpack, $dget_verify); 399 400if (@ARGV and $ARGV[0] =~ /^--no-?conf$/) { 401 $modified_conf_msg = " (no configuration files read)"; 402 shift; 403} else { 404 my @config_files = ('/etc/devscripts.conf', '~/.devscripts'); 405 my %config_vars = ( 406 'DGET_PATH' => '', 407 'DGET_UNPACK' => 'yes', 408 'DGET_VERIFY' => 'yes', 409 ); 410 my %config_default = %config_vars; 411 412 my $shell_cmd; 413 # Set defaults 414 foreach my $var (keys %config_vars) { 415 $shell_cmd .= "$var='$config_vars{$var}';\n"; 416 } 417 $shell_cmd .= 'for file in ' . join(" ", @config_files) . "; do\n"; 418 $shell_cmd .= '[ -f $file ] && . $file; done;' . "\n"; 419 # Read back values 420 foreach my $var (keys %config_vars) { $shell_cmd .= "echo \$$var;\n" } 421 my $shell_out = `/bin/bash -c '$shell_cmd'`; 422 @config_vars{ keys %config_vars } = split /\n/, $shell_out, -1; 423 424 foreach my $var (sort keys %config_vars) { 425 if ($config_vars{$var} ne $config_default{$var}) { 426 $modified_conf_msg .= " $var=$config_vars{$var}\n"; 427 } 428 } 429 $modified_conf_msg ||= " (none)\n"; 430 chomp $modified_conf_msg; 431 432 $dget_path = $config_vars{'DGET_PATH'}; 433 $dget_unpack = $config_vars{'DGET_UNPACK'} =~ /^y/i; 434 $dget_verify = $config_vars{'DGET_VERIFY'} =~ /^y/i; 435} 436 437# handle options 438Getopt::Long::Configure('bundling'); 439GetOptions( 440 "a|all" => \$opt->{'all'}, 441 "b|backup" => \$opt->{'backup'}, 442 "q|quiet" => \$opt->{'quiet'}, 443 "build" => \$opt->{'build'}, 444 "d|download-only" => sub { $dget_unpack = 0 }, 445 "x|extract" => sub { $dget_unpack = 1 }, 446 "u|allow-unauthenticated" => sub { $dget_verify = 0 }, 447 "insecure" => \$opt->{'insecure'}, 448 "no-cache" => \$opt->{'no-cache'}, 449 "noconf|no-conf" => \$opt->{'no-conf'}, 450 "path=s" => sub { 451 if ($_[1] eq '') { $dget_path = ''; } 452 else { $dget_path .= ":$_[1]"; } 453 }, 454 "h|help" => \$opt->{'help'}, 455 "V|version" => \$opt->{'version'}, 456 ) 457 or die 458 "$progname: unrecognised option. Run $progname --help for more details.\n"; 459 460if ($opt->{'help'}) { usage(); exit 0; } 461if ($opt->{'version'}) { version(); exit 0; } 462if ($opt->{'no-conf'}) { 463 die 464"$progname: --no-conf is only acceptable as the first command-line option!\n"; 465} 466 467if ($dget_path) { 468 foreach my $p (split /:/, $dget_path) { 469 push @dget_path, $p if -d $p; 470 } 471} 472 473if (!@ARGV) { 474 die 475"Usage: $progname [options] URL|package[=version]\nRun $progname --help for more details.\n"; 476} 477 478# handle arguments 479for my $arg (@ARGV) { 480 $found_dsc = ""; 481 482 # case 1: URL 483 if ($arg 484 =~ /^((?:copy|file|ftp|gopher|http|rsh|rsync|scp|sftp|ssh|www).*)\/([^\/]+\.\w+)$/ 485 ) { 486 get_file($1, $2, "unlink") or exit 1; 487 if ($found_dsc) { 488 if ($dget_verify) { # We are duplicating work here a bit as 489 # dpkg-source -x will also verify signatures. Still, we 490 # also want to barf with -d, and on unsigned packages. 491 system 'dscverify', $found_dsc; 492 exit $? >> 8 if $? >> 8 != 0; 493 } 494 my @cmd = qw(dpkg-source -x); 495 push @cmd, '--no-check' unless $dget_verify; 496 if ($opt->{'build'}) { 497 my @output = `LC_ALL=C @cmd $found_dsc`; 498 my $rc = $?; 499 print @output unless $opt->{'quiet'}; 500 exit $rc >> 8 if $rc >> 8 != 0; 501 foreach (@output) { 502 if (/^dpkg-source: (?:info: )?extracting .* in (.*)/) { 503 chdir $1; 504 exec 'dpkg-buildpackage', '-b', '-uc'; 505 die "Unable to run dpkg-buildpackage: $!"; 506 } 507 } 508 } elsif ($dget_unpack) { 509 system @cmd, $found_dsc; 510 exit $? >> 8 if $? >> 8 != 0; 511 } 512 } 513 514 # case 2a: --all srcpackage[=version] 515 } elsif ($opt->{'all'} 516 and $arg =~ /^([a-z0-9.+-:]{2,})(?:=([a-zA-Z0-9.:~+-]+))?$/) { 517 my ($source, $version, $arch) = ($1, $2); 518 ($source, $arch) = split(/:/, $source, 2); 519 my $cmd = "apt-cache showsrc $source"; 520 # unfortunately =version doesn't work here, and even if it did, was the 521 # user referring to the source version or the binary version? The code 522 # assumes binary version. 523 #$cmd .= "=$version" if ($version); 524 open my $showsrc, '-|', $cmd; 525 my $c = Dpkg::Control->new(type => CTRL_INDEX_SRC); 526 while ($c->parse($showsrc, $cmd)) { 527 if ($arch) { 528 my @packages = grep { $_ } split /\n/, $c->{'Package-List'}; 529 # Find all packages whose architecture is either 'all', 'any', 530 # or the given architecture. The Package-List lines are 531 # $pkg $debtype $section $priority arch=$archlist 532 foreach my $package (@packages) { 533 $package =~ s/^\s*//; 534 my ($binary, $debtype, $section, $priority, $archs) 535 = split(/\s+/, $package, 5); 536 if ($archs =~ m/all/) { 537 eval { apt_get($binary, $version) } or print "$@"; 538 } elsif ($archs =~ m/any|[=,]$arch/) { 539 eval { apt_get("$binary:$arch", $version) } 540 or print "$@"; 541 } 542 } 543 } else { 544 my @packages = split /, /, $c->{Binary}; 545 foreach my $package (@packages) { 546 eval { apt_get($package, $version) } or print "$@"; 547 } 548 } 549 last; 550 } 551 close $showsrc; 552 553 # case 2b: package[=version] 554 } elsif ($arg =~ /^([a-z0-9.+-:]{2,})(?:=([a-zA-Z0-9.:~+-]+))?$/) { 555 apt_get($1, $2); 556 557 } else { 558 usage(); 559 } 560} 561 562=head1 NAME 563 564dget - Download Debian source and binary packages 565 566=head1 SYNOPSIS 567 568=over 569 570=item B<dget> [I<options>] I<URL> ... 571 572=item B<dget> [I<options>] [B<--all>] I<package>[B<=>I<version>] ... 573 574=back 575 576=head1 DESCRIPTION 577 578B<dget> downloads Debian packages. In the first form, B<dget> fetches 579the requested URLs. If this is a .dsc or .changes file, then B<dget> 580acts as a source-package aware form of B<wget>: it also fetches any 581files referenced in the .dsc/.changes file. The downloaded source is 582then checked with B<dscverify> and, if successful, unpacked by 583B<dpkg-source>. 584 585In the second form, B<dget> downloads a I<binary> package (i.e., a 586I<.deb> file) from the Debian mirror configured in 587/etc/apt/sources.list(.d). Unlike B<apt-get install -d>, it does not 588require root privileges, writes to the current directory, and does not 589download dependencies. If a version number is specified, this version 590of the package is requested. With B<--all>, the list of all binaries for the 591source package I<package> is extracted from the output of 592C<apt-cache showsrc package>. 593 594In both cases dget is capable of getting several packages and/or URLs 595at once. 596 597(Note that I<.udeb> packages used by debian-installer are located in separate 598packages files from I<.deb> packages. In order to use I<.udebs> with B<dget>, 599you will need to have configured B<apt> to use a packages file for 600I<component>/I<debian-installer>). 601 602Before downloading files listed in .dsc and .changes files, and before 603downloading binary packages, B<dget> checks to see whether any of 604these files already exist. If they do, then their md5sums are 605compared to avoid downloading them again unnecessarily. B<dget> also 606looks for matching files in I</var/cache/apt/archives> and directories 607given by the B<--path> option or specified in the configuration files 608(see below). Finally, if downloading (.orig).tar.gz or .diff.gz files 609fails, dget consults B<apt-get source --print-uris>. Download backends 610used are B<curl> and B<wget>, looked for in that order. 611 612B<dget> was written to make it easier to retrieve source packages from 613the web for sponsor uploads. For checking the package with 614B<debdiff>, the last binary version is available via B<dget> 615I<package>, the last source version via B<apt-get source> I<package>. 616 617=head1 OPTIONS 618 619=over 4 620 621=item B<-a>, B<--all> 622 623Interpret I<package> as a source package name, and download all binaries as 624found in the output of "apt-cache showsrc I<package>". If I<package> is 625arch-qualified, then only binary packages which are "Arch: all", "Arch: any", 626or "Arch: $arch" will be downloaded. 627 628=item B<-b>, B<--backup> 629 630Move files that would be overwritten to I<./backup>. 631 632=item B<-q>, B<--quiet> 633 634Suppress B<wget>/B<curl> non-error output. 635 636=item B<-d>, B<--download-only> 637 638Do not run B<dpkg-source -x> on the downloaded source package. This can 639only be used with the first method of calling B<dget>. 640 641=item B<-x>, B<--extract> 642 643Run B<dpkg-source -x> on the downloaded source package to unpack it. 644This option is the default and can only be used with the first method of 645calling B<dget>. 646 647=item B<-u>, B<--allow-unauthenticated> 648 649Do not attempt to verify the integrity of downloaded source packages 650using B<dscverify>. 651 652=item B<--build> 653 654Run B<dpkg-buildpackage -b -uc> on the downloaded source package. 655 656=item B<--path> I<DIR>[B<:>I<DIR> ...] 657 658In addition to I</var/cache/apt/archives>, B<dget> uses the 659colon-separated list given as argument to B<--path> to find files with 660a matching md5sum. For example: "--path 661/srv/pbuilder/result:/home/cb/UploadQueue". If DIR is empty (i.e., 662"--path ''" is specified), then any previously listed directories 663or directories specified in the configuration files will be ignored. 664This option may be specified multiple times, and all of the 665directories listed will be searched; hence, the above example could 666have been written as: "--path /srv/pbuilder/result --path 667/home/cb/UploadQueue". 668 669=item B<--insecure> 670 671Allow SSL connections to untrusted hosts. 672 673=item B<--no-cache> 674 675Bypass server-side HTTP caches by sending a B<Pragma: no-cache> header. 676 677=item B<-h>, B<--help> 678 679Show a help message. 680 681=item B<-V>, B<--version> 682 683Show version information. 684 685=back 686 687=head1 CONFIGURATION VARIABLES 688 689The two configuration files F</etc/devscripts.conf> and 690F<~/.devscripts> are sourced by a shell in that order to set 691configuration variables. Command line options can be used to override 692configuration file settings. Environment variable settings are 693ignored for this purpose. The currently recognised variable is: 694 695=over 4 696 697=item B<DGET_PATH> 698 699This can be set to a colon-separated list of directories in which to 700search for files in addition to the default 701I</var/cache/apt/archives>. It has the same effect as the B<--path> 702command line option. It is not set by default. 703 704=item B<DGET_UNPACK> 705 706Set to 'no' to disable extracting downloaded source packages. Default 707is 'yes'. 708 709=item B<DGET_VERIFY> 710 711Set to 'no' to disable checking signatures of downloaded source 712packages. Default is 'yes'. 713 714=back 715 716=head1 EXAMPLES 717 718Download all I<.deb> files for the previous version of a package and run B<debdiff> 719on them: 720 721 dget --all mypackage=1.2-1 722 debdiff --from *_1.2-1_*.deb --to *_1.2-2_*.deb 723 724=head1 BUGS AND COMPATIBILITY 725 726B<dget> I<package> should be implemented in B<apt-get install -d>. 727 728Before devscripts version 2.10.17, the default was not to extract the 729downloaded source. Set DGET_UNPACK=no to revert to the old behaviour. 730 731=head1 AUTHOR 732 733This program is Copyright (C) 2005-2013 by Christoph Berg <myon@debian.org>. 734Modifications are Copyright (C) 2005-06 by Julian Gilbey <jdg@debian.org>. 735 736This program is licensed under the terms of the GPL, either version 2 737of the License, or (at your option) any later version. 738 739=head1 SEE ALSO 740 741B<apt-get>(1), B<curl>(1), B<debcheckout>(1), B<debdiff>(1), B<dpkg-source>(1), 742B<wget>(1) 743