our @deliberatelies;
our %previously;
our $existing_package = 'dpkg';
-our $cleanmode = 'dpkg-source';
+our $cleanmode;
our $changes_since_version;
our $quilt_mode;
our $quilt_modes_re = 'linear|smash|auto|nofix|nocheck';
our %format_ok = map { $_=>1 } ("1.0","3.0 (native)","3.0 (quilt)");
our $suite_re = '[-+.0-9a-z]+';
+our $cleanmode_re = 'dpkg-source(?:-d)?|git|git-ff|check|none';
our (@git) = qw(git);
our (@dget) = qw(dget);
'sbuild' => \@sbuild,
'ssh' => \@ssh,
'dgit' => \@dgit,
+ 'git' => \@git,
'dpkg-source' => \@dpkgsource,
'dpkg-buildpackage' => \@dpkgbuildpackage,
'dpkg-genchanges' => \@dpkggenchanges,
'ch' => \@changesopts,
'mergechanges' => \@mergechanges);
-our %opts_opt_cmdonly = ('gpg' => 1);
+our %opts_opt_cmdonly = ('gpg' => 1, 'git' => 1);
our %opts_cfg_insertpos = map {
$_,
scalar @{ $opts_opt_map{$_} }
main usages:
dgit [dgit-opts] clone [dgit-opts] package [suite] [./dir|/dir]
dgit [dgit-opts] fetch|pull [dgit-opts] [suite]
- dgit [dgit-opts] build [git-buildpackage-opts|dpkg-buildpackage-opts]
+ dgit [dgit-opts] build [dpkg-buildpackage-opts]
+ dgit [dgit-opts] sbuild [sbuild-opts]
dgit [dgit-opts] push [dgit-opts] [suite]
dgit [dgit-opts] rpush build-host:build-dir ...
important dgit options:
my $url = "$prefix/$package$suffix";
my @cmd = (qw(curl -sS -I), $url);
my $result = cmdoutput @cmd;
+ $result =~ s/^\S+ 200 .*\n\r?\n//;
+ # curl -sS -I with https_proxy prints
+ # HTTP/1.0 200 Connection established
$result =~ m/^\S+ (404|200) /s or
fail "unexpected results from git check query - ".
Dumper($prefix, $result);
return $tree;
}
-sub mktree_in_ud_from_only_subdir () {
- # changes into the subdir
- my (@dirs) = <*/.>;
- die unless @dirs==1;
- $dirs[0] =~ m#^([^/]+)/\.$# or die;
- my $dir = $1;
- changedir $dir;
-
+sub remove_stray_gits () {
my @gitscmd = qw(find -name .git -prune -print0);
debugcmd "|",@gitscmd;
open GITS, "-|", @gitscmd or failedcmd @gitscmd;
}
}
$!=0; $?=0; close GITS or failedcmd @gitscmd;
+}
+
+sub mktree_in_ud_from_only_subdir () {
+ # changes into the subdir
+ my (@dirs) = <*/.>;
+ die unless @dirs==1;
+ $dirs[0] =~ m#^([^/]+)/\.$# or die;
+ my $dir = $1;
+ changedir $dir;
+ remove_stray_gits();
mktree_in_ud_here();
my $format=get_source_format();
if (madformat($format)) {
runcmd @git, qw(config), $k, $v;
}
-sub setup_mergechangelogs () {
+sub setup_mergechangelogs (;$) {
+ my ($always) = @_;
+ return unless $always || access_cfg_bool(1, 'setup-mergechangelogs');
+
my $driver = 'dpkg-mergechangelogs';
my $cb = "merge.$driver";
my $attrs = '.git/info/attributes';
rename "$attrs.new", "$attrs" or die "$attrs: $!";
}
+sub setup_useremail (;$) {
+ my ($always) = @_;
+ return unless $always || access_cfg_bool(1, 'setup-useremail');
+
+ my $setup = sub {
+ my ($k, $envvar) = @_;
+ my $v = access_cfg("user-$k", 'RETURN-UNDEF') // $ENV{$envvar};
+ return unless defined $v;
+ set_local_git_config "user.$k", $v;
+ };
+
+ $setup->('email', 'DEBEMAIL');
+ $setup->('name', 'DEBFULLNAME');
+}
+
+sub setup_new_tree () {
+ setup_mergechangelogs();
+ setup_useremail();
+}
+
sub clone ($) {
my ($dstdir) = @_;
canonicalise_suite();
$vcsgiturl =~ s/\s+-b\s+\S+//g;
runcmd @git, qw(remote add vcs-git), $vcsgiturl;
}
- setup_mergechangelogs();
+ setup_new_tree();
runcmd @git, qw(reset --hard), lrref();
printdone "ready for work in $dstdir";
}
if (!defined $keyid) {
$keyid = access_cfg('keyid','RETURN-UNDEF');
}
+ if (!defined $keyid) {
+ $keyid = getfield $clogp, 'Maintainer';
+ }
unlink $tfn->('.tmp.asc') or $!==&ENOENT or die $!;
my @sign_cmd = (@gpg, qw(--detach-sign --armor));
push @sign_cmd, qw(-u),$keyid if defined $keyid;
# should be contained within debian/patches.
changedir '../fake';
+ remove_stray_gits();
mktree_in_ud_here();
rmtree '.pc';
runcmd @git, 'add', '.';
#----- other building -----
+our $suppress_clean;
+
sub clean_tree () {
+ return if $suppress_clean;
if ($cleanmode eq 'dpkg-source') {
runcmd_ordryrun_local @dpkgbuildpackage, qw(-T clean);
} elsif ($cleanmode eq 'dpkg-source-d') {
build_maybe_quilt_fixup();
}
-sub changesopts () {
+sub changesopts_initial () {
my @opts =@changesopts[1..$#changesopts];
+}
+
+sub changesopts_version () {
if (!defined $changes_since_version) {
my @vsns = archive_query('archive_query');
my @quirk = access_quirk();
}
}
if ($changes_since_version ne '_') {
- unshift @opts, "-v$changes_since_version";
+ return ("-v$changes_since_version");
+ } else {
+ return ();
}
- return @opts;
}
-sub massage_dbp_args ($) {
- my ($cmd) = @_;
- return unless $cleanmode =~ m/git|none/;
+sub changesopts () {
+ return (changesopts_initial(), changesopts_version());
+}
+
+sub massage_dbp_args ($;$) {
+ my ($cmd,$xargs) = @_;
+ if ($cleanmode eq 'dpkg-source') {
+ $suppress_clean = 1;
+ return;
+ }
debugcmd '#massaging#', @$cmd if $debuglevel>1;
my @newcmd = shift @$cmd;
# -nc has the side effect of specifying -b if nothing else specified
push @newcmd, '-nc';
# and some combinations of -S, -b, et al, are errors, rather than
# later simply overriding earlier
- push @newcmd, '-F' unless grep { m/^-[bBASF]$/ } @$cmd;
+ push @newcmd, '-F' unless grep { m/^-[bBASF]$/ } (@$cmd, @$xargs);
push @newcmd, @$cmd;
@$cmd = @newcmd;
}
sub cmd_build {
- build_prep();
- my @dbp = (@dpkgbuildpackage, qw(-us -uc), changesopts(), @ARGV);
+ my @dbp = (@dpkgbuildpackage, qw(-us -uc), changesopts_initial(), @ARGV);
massage_dbp_args \@dbp;
+ build_prep();
+ push @dbp, changesopts_version();
runcmd_ordryrun_local @dbp;
printdone "build successful\n";
}
-sub cmd_git_build {
- build_prep();
+sub cmd_gbp_build {
my @dbp = @dpkgbuildpackage;
- massage_dbp_args \@dbp;
- my @cmd =
- (qw(git-buildpackage -us -uc --git-no-sign-tags),
- "--git-builder=@dbp");
+ massage_dbp_args \@dbp, \@ARGV;
+
+ my @cmd;
+ if (length executable_on_path('git-buildpackage')) {
+ @cmd = qw(git-buildpackage);
+ } else {
+ @cmd = qw(gbp buildpackage);
+ }
+ push @cmd, (qw(-us -uc --git-no-sign-tags), "--git-builder=@dbp");
+
+ if ($cleanmode eq 'dpkg-source') {
+ $suppress_clean = 1;
+ } else {
+ push @cmd, '--git-cleaner=true';
+ }
+ build_prep();
unless (grep { m/^--git-debian-branch|^--git-ignore-branch/ } @ARGV) {
canonicalise_suite();
push @cmd, "--git-debian-branch=".lbranch();
runcmd_ordryrun_local @cmd, @ARGV;
printdone "build successful\n";
}
+sub cmd_git_build { cmd_gbp_build(); } # compatibility with <= 1.0
sub build_source {
+ if ($cleanmode =~ m/^dpkg-source/) {
+ # dpkg-source will clean, so we shouldn't
+ $suppress_clean = 1;
+ }
build_prep();
$sourcechanges = "${package}_".(stripepoch $version)."_source.changes";
$dscfn = dscfn($version);
sub cmd_setup_mergechangelogs {
badusage "no arguments allowed to dgit setup-mergechangelogs" if @ARGV;
- setup_mergechangelogs();
+ setup_mergechangelogs(1);
+}
+
+sub cmd_setup_useremail {
+ badusage "no arguments allowed to dgit setup-mergechangelogs" if @ARGV;
+ setup_useremail(1);
+}
+
+sub cmd_setup_new_tree {
+ badusage "no arguments allowed to dgit setup-tree" if @ARGV;
+ setup_new_tree();
}
#---------- argument parsing and main program ----------
exit 0;
}
+our (%valopts_long, %valopts_short);
+our @rvalopts;
+
+sub defvalopt ($$$$) {
+ my ($long,$short,$val_re,$how) = @_;
+ my $oi = { Long => $long, Short => $short, Re => $val_re, How => $how };
+ $valopts_long{$long} = $oi;
+ $valopts_short{$short} = $oi;
+ # $how subref should:
+ # do whatever assignemnt or thing it likes with $_[0]
+ # if the option should not be passed on to remote, @rvalopts=()
+ # or $how can be a scalar ref, meaning simply assign the value
+}
+
+defvalopt '--since-version', '-v', '[^_]+|_', \$changes_since_version;
+defvalopt '--distro', '-d', '.+', \$idistro;
+defvalopt '--existing-package','', '.*', \$existing_package;
+
sub parseopts () {
my $om;
@ssh = ($ENV{'GIT_SSH'});
}
+ my $oi;
+ my $val;
+ my $valopt = sub {
+ my ($what) = @_;
+ @rvalopts = ($_);
+ if (!defined $val) {
+ badusage "$what needs a value" unless length @ARGV;
+ $val = shift @ARGV;
+ push @rvalopts, $val;
+ }
+ badusage "bad value \`$val' for $what" unless
+ $val =~ m/^$oi->{Re}$(?!\n)/s;
+ my $how = $oi->{How};
+ if (ref($how) eq 'SCALAR') {
+ $$how = $val;
+ } else {
+ $how->($val);
+ }
+ push @ropts, @rvalopts;
+ };
+
while (@ARGV) {
last unless $ARGV[0] =~ m/^-/;
$_ = shift @ARGV;
} elsif (m/^--new$/) {
push @ropts, $_;
$new_package=1;
- } elsif (m/^--since-version=([^_]+|_)$/) {
- push @ropts, $_;
- $changes_since_version = $1;
} elsif (m/^--([-0-9a-z]+)=(.+)/s &&
($om = $opts_opt_map{$1}) &&
length $om->[0]) {
($om = $opts_opt_map{$1})) {
push @ropts, $_;
push @$om, $2;
- } elsif (m/^--existing-package=(.*)/s) {
- push @ropts, $_;
- $existing_package = $1;
} elsif (m/^--initiator-tempdir=(.*)/s) {
$initiator_tempdir = $1;
$initiator_tempdir =~ m#^/# or
badusage "--initiator-tempdir must be used specify an".
" absolute, not relative, directory."
- } elsif (m/^--distro=(.*)/s) {
- push @ropts, $_;
- $idistro = $1;
} elsif (m/^--build-products-dir=(.*)/s) {
push @ropts, $_;
$buildproductsdir = $1;
- } elsif (m/^--clean=(dpkg-source(?:-d)?|git|git-ff|check|none)$/s) {
+ } elsif (m/^--clean=($cleanmode_re)$/os) {
push @ropts, $_;
$cleanmode = $1;
} elsif (m/^--clean=(.*)$/s) {
} elsif (m/^--deliberately-($deliberately_re)$/s) {
push @ropts, $_;
push @deliberatelies, $&;
+ } elsif (m/^(--[-0-9a-z]+)(=|$)/ && ($oi = $valopts_long{$1})) {
+ $val = $2 ? $' : undef; #';
+ $valopt->($oi->{Long});
} else {
badusage "unknown long option \`$_'";
}
} elsif (s/^-N/-/) {
push @ropts, $&;
$new_package=1;
- } elsif (s/^-v([^_]+|_)$//s) {
- push @ropts, $&;
- $changes_since_version = $1;
} elsif (m/^-m/) {
push @ropts, $&;
push @changesopts, $_;
} elsif (s/^-c(.*=.*)//s) {
push @ropts, $&;
push @git, '-c', $1;
- } elsif (s/^-d(.+)//s) {
- push @ropts, $&;
- $idistro = $1;
} elsif (s/^-C(.+)//s) {
push @ropts, $&;
$changesfile = $1;
}
} elsif (s/^-k(.+)//s) {
$keyid=$1;
- } elsif (m/^-[vdCk]$/) {
+ } elsif (m/^-[dCk]$/) {
badusage
"option \`$_' requires an argument (and no space before the argument)";
} elsif (s/^-wn$//s) {
} elsif (s/^-wc$//s) {
push @ropts, $&;
$cleanmode = 'check';
+ } elsif (m/^-[a-zA-Z]/ && ($oi = $valopts_short{$&})) {
+ $val = $'; #';
+ $val = undef unless length $val;
+ $valopt->($oi->{Short});
+ $_ = '';
} else {
badusage "unknown short option \`$_'";
}
$quilt_mode = $1;
}
+if (!defined $cleanmode) {
+ local $access_forpush;
+ $cleanmode = access_cfg('clean-mode', 'RETURN-UNDEF');
+ $cleanmode //= 'dpkg-source';
+
+ badcfg "unknown clean-mode \`$cleanmode'" unless
+ $cleanmode =~ m/^($cleanmode_re)$(?!\n)/s;
+}
+
my $fn = ${*::}{"cmd_$cmd"};
$fn or badusage "unknown operation $cmd";
$fn->();