summaryrefslogtreecommitdiffstats
path: root/dh_debputy
blob: 1fe6dd1552a5b0686a900b1c983b11f518241314 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
#!/usr/bin/perl

=encoding UTF-8

=head1 NAME

dh_debputy - build Debian binary packages using debputy

=cut

use strict;
use warnings;
use Debian::Debhelper::Dh_Lib;

our $VERSION = DH_BUILTIN_VERSION;

=head1 SYNOPSIS

B<dh_debputy> [S<I<debhelper options>>] [B<--destdir=>I<directory>] [S<B<--> I<params>>]

=head1 DESCRIPTION

B<dh_debputy> is a tool for integrating B<debputy> with debhelper as an interim solution
until B<debputy> covers enough features to be a standalone packaging tool.

The B<debputy> toolstack can built I<any> deb without requiring root or fakeroot.  It is
always possible to use B<Rules-Requires-Root: no> with B<dh_debputy>/B<debputy> (given no
non-debputy parts of F<debian/rules> or the upstream build system require root).

=head1 OPTIONS

=over 4

=item B<--destdir=>I<directory>

Use this if you want the generated F<.deb> files to be put in a directory
other than the default of "F<..>".

=item B<--plugin=>I<name>

Have `debputy` load the given I<name>.  The I<name> can be a name, in which case
the plugin must be installed into the proper plugin path (and in that case, you can
I<often> just have a build dependency on B<< debputy-plugin-I<name> >> ).

Alternatively, the I<name> can be a path (must contain B</> and should end with
B<.json> or B<.json.in>).  In this case, that file is loaded as a plugin.  This
case is useful for plugin providers to use their own plugin.

=item B<--> I<params>

Pass I<params> to L<dpkg-deb(1)> when it is used to build the
package.

Restrict I<params> to compression options as the B<dpkg-deb> options may be
emulated and not all of the B<dpkg-deb> parameters are supported.

=back

=head1 FILES

=over 4

=item F<debian/debputy.manifest>

Please see F</usr/share/doc/dh-debputy/MANIFEST-FORMAT.md.gz>.

If you are converting your first package, you may want to read
F</usr/share/doc/dh-debputy/GETTING-STARTED-WITH-dh-debputy.md.gz> first.

Unlike most debhelper like tools, this file is per source package rather than
per binary package.  Therefore, you I<cannot> use F<< debian/I<package>.debputy.manifest >>
to provide a specialized manifest for I<package>.  Instead, all the needed parts
should be written into the manifest itself.

=back

=cut

my (@plugins, $integration_mode);

init(options => {
	"destdir=s"          => \$dh{DESTDIR},
	"plugin=s"           => \@plugins,
	"integration-mode=s" => \$integration_mode,
});

# Set the default destination directory.
if (! defined $dh{DESTDIR}) {
	$dh{DESTDIR}='..';
}

my $debputy_cmd = $ENV{'DEBPUTY_CMD'} // 'debputy';
# `debputy` does not know about any -v/--verbose passed directly.
# But it does listen to `DH_VERBOSE` in these integration modes, so we just
# use that for now. At some point, this might be replaced by a proper
# command line option.
$ENV{'DH_VERBOSE'} = '1' if $dh{VERBOSE};

my @debputy_cmdline = ($debputy_cmd);
for my $plugin (@plugins) {
	push(@debputy_cmdline, '--plugin', $plugin);
}
push(@debputy_cmdline,
	'internal-command',
	'dh-integration-generate-debs',
);
push(@debputy_cmdline, "--integration-mode=${integration_mode}")
	if defined($integration_mode);
for my $package (@{$dh{DOPACKAGES}}) {
	push(@debputy_cmdline, '-p', $package);
}
push(@debputy_cmdline, $dh{DESTDIR});
if (@{$dh{U_PARAMS}}) {
	push(@debputy_cmdline, '--', @{$dh{U_PARAMS}});
}
doit(@debputy_cmdline);

=head1 ON DEB ASSEMBLY

The B<dh_debputy> will often use B<dpkg-deb> for assembling the output. However, there are a few cases
where B<dpkg-deb> does not have the required features for 100% rootless assembly and B<debputy> will
use a different assembly method when needed.  Generally, this special-case only triggers with
B<Rules-Requires-Root: no> I<and> when using a feature that requires root with B<dpkg-deb> (such as
static file ownership).

If you experience, that a B<dh_debputy> produced binary via its internal assembly method that
is B<not> 100% bit-for-bit reproducible with the equivalent B<root> + B<dpkg-deb> built deb
and that is not caused by an inaccurate manifest in your end, please file a bug.  See the
subsection L</How to ensure the dpkg-deb assembly method is being used> for how you
control which assembly method is being used.

By producing exactly the same deb as B<dpkg-deb> would have with B<fakeroot>, we reduce the risk of bugs
or bad behaviour during installation.

Note that 100% bit-for-bit reproducible is not compared to debhelper.  Packages generated by debputy may
differ from those built by debhelper. As an example, auto-generated shell snippets for maintainer scripts
identifies the tool that generated them and it would be wrong for debputy to identify itself as debhelper
in this case. This in turn creates a minor difference between packages generated by the two tools.
Consider using B<diffoscope> to compare your B<debhelper> generated deb to your B<debputy> generated debs.

=head2 How to ensure the dpkg-deb assembly method is being used

The B<debputy> tool stack has two assembly methods: B<dpkg-deb> and the internal B<debputy> method.

By default, the B<dpkg-deb> is used. The B<debputy> tool will only switch to its internal method when:

=over 4

=item -

The package uses a feature that requires (fake)root when assembly via B<dpkg-deb>. At the time of
writing, this is only triggered by having static ownership in the deb (paths where ownership such as
B<root:tty> is recorded directly in the F<data.tar>), AND

=item -

The package does not run nor permit B<debputy> to use (fake)root.  This part comes down to
B<Rules-Requires-Root>. When set to B<no>, B<debputy> will automatically fallback to the
internal method as necessary.

If you would like to avoid using root during package assembly but also do not want a custom
assembly method, then you can set B<Rules-Requires-Root: debputy/deb-assembly> and B<debputy>
will always use B<dpkg-deb> for the assembly.  However, depending on your version of B<dpkg-dev>
you may run into L<#1036865|https://bugs.debian.org/1036865>.  In that case, you will have to
choose between using classic root (B<Rules-Requires-Root: binary-targets>) or the internal
rootless assembly method.

=back

=head1 SEE ALSO

L<debhelper(7)>

This program integrates into the debhelper suite.

=head1 AUTHOR

Niels Thykier <niels@thykier.net>

=cut