This file is indexed.

/usr/share/pyshared/pybitclient/debianclient.py is in pybit-client 1.0.0-2.

This file is owned by root:root, with mode 0o664.

The actual contents of the file can be viewed below.

  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
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
#       debian.py
#
#       Copyright 2012, 2013 Neil Williams <codehelp@debian.org>
#
#       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 2 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, write to the Free Software
#       Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
#       MA 02110-1301, USA.

# If using with the git vcs handler, see also http://wiki.debian.org/GitSrc

# There could also be merit in renaming this as DebianSbuild and
# then supporting DebianSVN and DebianGit which would use
# svn-buildpackage & git-buildpackage respectively, instead of sbuild.

import os
import logging
import pybitclient
from pybitclient.buildclient import PackageHandler
from pybit.models import BuildRequest, checkValue

class DebianBuildClient(PackageHandler):
    dput_cfg = "" #FIXME
    dput_dest = ""
    def _overall_success(self, message, conn_data):
        error = 1
        #If we have a message set we send back the message and failure
        if message :
            pybitclient.send_message (conn_data, message)
        else:
            pybitclient.send_message (conn_data, "success")
            error = 0
        return error

    def update_environment(self,name,pkg, conn_data):
        retval = None
        command = "schroot --directory / -u root -c %s -- apt-get update > /dev/null 2>&1" % (name)
        if pybitclient.run_cmd (command, self.settings["dry_run"], None) :
            retval = "build_update"
        return retval

    def build_command_handler (self, buildreq, conn_data) :
        retval = None
        logfile = self.get_buildlog (self.settings["buildroot"], buildreq)
        # expect fakeroot debian/rules rules-target
        package_dir = os.path.join (self.settings["buildroot"],
                buildreq.get_suite(), buildreq.transport.method, buildreq.get_package())
        parts = buildreq.commands.split(' ')
        if len(parts) != 3 :
            retval = "failed-custom-command-len"
        if retval :
            return retval
        # only allow debian/rules targets, specified in full
        if parts[0] != "fakeroot" or parts[1] != "debian/rules" or parts[2] is None :
            retval = "failed-custom-command-parts"
        if retval :
            return retval
        # debian/rules targets must be run in the package_dir and
        # a command passed to schroot needs to be accessible inside the
        # chroot and therefore copied to ${HOME} so that schroot copies it again,
        # into the chroot itself.
        orig_sh = "/usr/share/pybitclient/sbuild-orig.sh"
        command = "(cp %s %s/sbuild-orig.sh ; schroot --directory / -n -u root -c %s -- %s/sbuild-orig.sh %s %s ; rm %s/sbuild-orig.sh)" % (orig_sh,
            self.settings["buildroot"], buildreq.get_suite(), self.settings["buildroot"], package_dir, parts[2], self.settings["buildroot"])
        if pybitclient.run_cmd (command, self.settings["dry_run"], logfile):
            retval = "custom-command-error"
        return retval

    def orig_source_handler (self, buildreq, conn_data) :
        retval = None
        logfile = self.get_buildlog (self.settings["buildroot"], buildreq)
        srcdir = os.path.join (self.settings["buildroot"],
                buildreq.get_suite(), buildreq.transport.method)
        version = buildreq.get_version()
        if '-' not in version :
            # native package, nothing to do for the orig source.
            return retval
        if self.settings["dry_run"] :
            logging.debug("I: %s (%s) is not a native package - need original source" % (buildreq.get_package(), version))
        offset = version.find('-')
        # strip the debian packaging part of the version string
        origversion = version[0:offset]
        origtar = os.path.join (srcdir, "%s_%s.orig.tar.gz" % (buildreq.get_package(), origversion))
        if os.path.isfile (origtar) :
            # have .gz
            return retval
        # check for .tar.bz2
        origtar = os.path.join (srcdir, "%s_%s.orig.tar.bz2" % (buildreq.get_package(), origversion))
        if os.path.isfile (origtar) :
            # have .bz2
            return retval
        # use a debian/watch file and uscan
        package_dir = "%s/%s" % (srcdir, buildreq.get_package())
        watch = os.path.join (srcdir, package_dir, "debian", "watch")
        logging.debug ("I: Looking for '%s' as watch file." % watch)
        if os.path.isfile (watch) or self.settings["dry_run"] :
            logging.debug ("I: Using '%s' as watch file." % watch)
            command = "(cd %s ; uscan --destdir ../ --repack --force-download --download-version %s)" % (os.path.join(srcdir,
                buildreq.get_package()), origversion)
            if pybitclient.run_cmd (command, self.settings["dry_run"], logfile):
                retval = "watch-failed"
                return retval
        # fall back to apt-get source
        else :
            command = "(cd ../ ; apt-get -d source %s/%s)" % (buildreq.get_package(), buildreq.get_suite())
            if pybitclient.run_cmd (command, self.settings["dry_run"], logfile):
                logging.debug("I: apt-get source failed, proceeding anyway incase its an update of a debian package.")
        return retval

    def build_master (self, buildreq, conn_data):
        retval = None
        logfile = self.get_buildlog (self.settings["buildroot"], buildreq)
        if (not isinstance(buildreq, BuildRequest)):
            logging.warn ("E: not able to identify package name.")
            retval = "misconfigured"
            return self._overall_success(retval, conn_data)
        srcdir = os.path.join (self.settings["buildroot"],
                buildreq.get_suite(), buildreq.transport.method)
        package_dir = "%s/%s" % (srcdir, buildreq.get_package())
        # To check the build-dependencies in advance, we need to ensure the
        # chroot has an update apt-cache, so can't use apt-update option of
        # sbuild. The alternative is to update the apt-cache twice per build,
        # once for the dep check and once before the build. The choice depends
        # on whether two network trips are more efficient than rewriting the
        # lvm snapshot before even trying to do any build.
        chroot_name = buildreq.get_suite()
        if (buildreq.get_buildenv() is not None):
            chroot_name = "%s-%s" % (buildreq.get_buildenv(), buildreq.get_suite())
        if self.settings["use_lvm"] :
            update_name = "%s-source" % chroot_name
        else :
            update_name = chroot_name
        retval = self.update_environment (update_name, buildreq, conn_data)
        # need an extra uscan stage to deal with non-native packages
        # this requires the upstream release to be accessible to the client.
        # i.e. unreleased versions of non-native packages cannot be built this way.
        # See #18 for the unreleased build support issue.
        if not retval:
            if hasattr (buildreq, 'commands') and buildreq.commands :
                retval = self.build_command_handler (buildreq, conn_data)
            else : #61 - avoid dependency check if not using lvm
                if self.settings["use_lvm"] and (os.path.isdir(package_dir) or self.settings["dry_run"]) :
                    control = os.path.join (package_dir, 'debian', 'control')
                    dep_check = "/usr/lib/pbuilder/pbuilder-satisfydepends-classic --control"
                    command = "schroot --directory / -u root -c %s -- %s %s" % (chroot_name, dep_check, os.path.realpath(control))
                    if pybitclient.run_cmd (command, self.settings["dry_run"], logfile):
                        retval = "build-dep-wait"
                if not retval :
                    retval = self.orig_source_handler (buildreq, conn_data)
                if not retval :
                    dsc_file = "%s/%s_%s.dsc" % (srcdir, buildreq.get_package(), buildreq.get_version())
                    if not os.path.exists (dsc_file) :
                        command = "(cd %s && dpkg-buildpackage -nc -S -d -uc -us)" % (package_dir)
                        if pybitclient.run_cmd (command, self.settings["dry_run"], logfile):
                            retval = "build_dsc"
        if not retval :
            command = "sbuild -A -n -s -d %s %s/%s_%s.dsc" % (chroot_name,
                srcdir, buildreq.get_package(), buildreq.get_version())
            ret = pybitclient.run_cmd (command, self.settings["dry_run"], logfile)
            if (ret == 3 or ret == 1):
                retval = "build-dep-wait"
            elif (ret):
                retval = "build_binary"
        if not retval :
            changes = "%s/%s_%s_%s.changes" % (self.settings["buildroot"], buildreq.get_package(),
                buildreq.get_version(), buildreq.get_arch())
            if not self.settings["dry_run"] and not os.path.isfile (changes) :
                logging.warn("E: build_master: Failed to find %s file." % (changes))
                retval = "build_changes"
            if not retval and checkValue ('debsignkey', self.settings) :
                command = "debsign -k%s %s" % (self.settings['debsignkey'], changes)
                if pybitclient.run_cmd (command, self.settings["dry_run"], logfile):
                    retval = "build_sign"
        return self._overall_success(retval, conn_data)


    def upload (self, buildreq, conn_data):
        retval = None
        logfile = self.get_buildlog (self.settings["buildroot"], buildreq)
        changes = "%s/%s_%s_%s.changes" % (self.settings["buildroot"], buildreq.get_package(),
            buildreq.get_version(), buildreq.get_arch())
        if not os.path.isfile (changes) and not self.settings["dry_run"]:
            logging.warn("E: upload: Failed to find %s file." % (changes))
            retval = "upload_changes"
        if not retval :
            if (buildreq.get_buildenv() is not None):
                upload_target = buildreq.get_buildenv()
            else :
                upload_target = self.settings["dput"]
            command = "dput -c %s %s %s %s" % (self.dput_cfg,
                upload_target, self.settings["dput_dest"], changes)
            if pybitclient.run_cmd (command, self.settings["dry_run"], logfile):
                retval = "upload_fail"
        if not retval :
            command = "dcmd rm %s" % (changes)
            if pybitclient.run_cmd (command, self.settings["dry_run"], logfile):
                retval = "post-upload-clean-fail"

        return self._overall_success(retval, conn_data)

    def build_slave (self, buildreq, conn_data):
        retval = None
        logfile = self.get_buildlog (self.settings["buildroot"], buildreq)
        srcdir = os.path.join (self.settings["buildroot"],
                buildreq.get_suite(), buildreq.transport.method)
        package_dir = "%s/%s" % (srcdir, buildreq.get_package())
        if os.path.isdir(package_dir) or self.settings["dry_run"]:
            # need an extra uscan stage to deal with non-native packages
            # this requires the upstream release to be accessible to the client.
            # i.e. unreleased versions of non-native packages cannot be built this way.
            # See #18 for the unreleased build support issue.
            if hasattr (buildreq, 'commands') and buildreq.commands :
                retval = self.build_command_handler (buildreq, conn_data)
            else :
                retval = self.orig_source_handler (buildreq, conn_data)
            command = "(cd %s ; dpkg-buildpackage -nc -S -d -uc -us)" % (package_dir)
            if pybitclient.run_cmd (command, self.settings["dry_run"], logfile):
                retval = "build_dsc"
            chroot_name = buildreq.get_suite()
            if (buildreq.get_buildenv() is not None):
                chroot_name = "%s-%s" % (buildreq.get_buildenv(), buildreq.get_suite())
            if not retval :
                command = "sbuild -n --apt-update -d %s %s/%s_%s.dsc" % (chroot_name, srcdir,
                    buildreq.get_package(), buildreq.get_version())
                ret = pybitclient.run_cmd (command, self.settings["dry_run"], logfile)
                if (ret == 3 or ret == 768):
                    retval = "build-dep-wait"
                elif (ret):
                    retval = "build_binary"
            if not retval :
                changes = "%s/%s_%s_%s.changes" % (self.settings["buildroot"],
                    buildreq.get_package(), buildreq.get_version(),
                    buildreq.get_arch())
                if not self.settings["dry_run"] and not os.path.isfile (changes) :
                    logging.warn ("E: build_slave: Failed to find %s file." % (changes))
                    retval = "build_changes"
                if not retval and checkValue ('debsignkey', self.settings) :
                    command = "debsign -k%s %s" % (self.settings['debsignkey'], changes)
                    if pybitclient.run_cmd (command, self.settings["dry_run"], logfile):
                        retval = "build_sign"
        else:
            retval = "Can't find build dir."
                #If we have a message set we send back the message and failure

        return self._overall_success(retval, conn_data)

    def get_distribution (self) :
        return 'Debian'

    def __init__(self, settings):
        PackageHandler.__init__(self, settings)
        # Specific buildd options
        # FIXME: decide how this is managed and packaged
        # variables to retrieve from the job object later
        self.dput_cfg = "/etc/pybit/client/dput.cf"
        if not settings["dry_run"] :
            os.chdir (settings["buildroot"])

def createPlugin (settings) :
    return DebianBuildClient (settings)