Colin Watson has proposed merging lp:~cjwatson/launchpad-buildd/gather-results-via-backend into lp:launchpad-buildd with lp:~cjwatson/launchpad-buildd/fake-backend as a prerequisite.
Commit message: Gather results via the backend abstraction rather than by direct filesystem access. Requested reviews: Launchpad code reviewers (launchpad-reviewers) For more details, see: https://code.launchpad.net/~cjwatson/launchpad-buildd/gather-results-via-backend/+merge/328624 Current exceptions are binarypackage (because sbuild handles its own backend access) and sourcepackagerecipe (which needs some further refactoring first). -- Your team Launchpad code reviewers is requested to review the proposed merge of lp:~cjwatson/launchpad-buildd/gather-results-via-backend into lp:launchpad-buildd.
=== modified file 'lpbuildd/livefs.py' --- lpbuildd/livefs.py 2017-07-28 13:57:47 +0000 +++ lpbuildd/livefs.py 2017-08-05 09:47:12 +0000 @@ -4,12 +4,10 @@ __metaclass__ = type import os -import shutil from lpbuildd.debian import ( DebianBuildManager, DebianBuildState, - get_build_path, ) @@ -33,11 +31,6 @@ def initiate(self, files, chroot, extra_args): """Initiate a build with a given set of files and chroot.""" - self.build_path = get_build_path( - self.home, self._buildid, "chroot-autobuild", "build") - if os.path.isdir(self.build_path): - shutil.rmtree(self.build_path) - self.subarch = extra_args.get("subarch") self.project = extra_args["project"] self.subproject = extra_args.get("subproject") @@ -100,7 +93,8 @@ def gatherResults(self): """Gather the results of the build and add them to the file cache.""" - for entry in sorted(os.listdir(self.build_path)): - path = os.path.join(self.build_path, entry) - if entry.startswith("livecd.") and not os.path.islink(path): - self._slave.addWaitingFile(path) + for entry in sorted(self.backend.listdir("/build")): + path = os.path.join("/build", entry) + if (entry.startswith("livecd.") and + not self.backend.islink(path)): + self.addWaitingFileFromBackend(path) === modified file 'lpbuildd/slave.py' --- lpbuildd/slave.py 2017-08-05 09:47:12 +0000 +++ lpbuildd/slave.py 2017-08-05 09:47:12 +0000 @@ -12,6 +12,8 @@ import hashlib import os import re +import shutil +import tempfile import urllib2 import xmlrpclib @@ -310,6 +312,15 @@ self._subprocess.ignore = True self._subprocess.transport.loseConnection() + def addWaitingFileFromBackend(self, path): + fetched_dir = tempfile.mkdtemp() + try: + fetched_path = os.path.join(fetched_dir, os.path.basename(path)) + self.backend.copy_out(path, fetched_path) + self._slave.addWaitingFile(fetched_path) + finally: + shutil.rmtree(fetched_dir) + class BuilderStatus: """Status values for the builder.""" === modified file 'lpbuildd/snap.py' --- lpbuildd/snap.py 2017-04-03 12:30:15 +0000 +++ lpbuildd/snap.py 2017-08-05 09:47:12 +0000 @@ -7,7 +7,6 @@ import json import os -import shutil import sys from lpbuildd.debian import ( @@ -41,11 +40,6 @@ def initiate(self, files, chroot, extra_args): """Initiate a build with a given set of files and chroot.""" - self.build_path = get_build_path( - self.home, self._buildid, "chroot-autobuild", "build") - if os.path.isdir(self.build_path): - shutil.rmtree(self.build_path) - self.name = extra_args["name"] self.branch = extra_args.get("branch") self.git_repository = extra_args.get("git_repository") @@ -113,12 +107,12 @@ def gatherResults(self): """Gather the results of the build and add them to the file cache.""" - output_path = os.path.join(self.build_path, self.name) - if not os.path.exists(output_path): + output_path = os.path.join("/build", self.name) + if not self.backend.path_exists(output_path): return - for entry in sorted(os.listdir(output_path)): + for entry in sorted(self.backend.listdir(output_path)): path = os.path.join(output_path, entry) - if os.path.islink(path): + if self.backend.islink(path): continue if entry.endswith(".snap") or entry.endswith(".manifest"): - self._slave.addWaitingFile(path) + self.addWaitingFileFromBackend(path) === modified file 'lpbuildd/target/backend.py' --- lpbuildd/target/backend.py 2017-08-05 09:47:12 +0000 +++ lpbuildd/target/backend.py 2017-08-05 09:47:12 +0000 @@ -49,12 +49,14 @@ """ raise NotImplementedError - def run(self, args, env=None, input_text=None, **kwargs): + def run(self, args, env=None, input_text=None, get_output=False, + **kwargs): """Run a command in the target environment. :param args: the command and arguments to run. :param env: additional environment variables to set. :param input_text: input text to pass on the command's stdin. + :param get_output: if True, return the output from the command. :param kwargs: additional keyword arguments for `subprocess.Popen`. """ raise NotImplementedError @@ -73,6 +75,57 @@ """ raise NotImplementedError + def copy_out(self, source_path, target_path): + """Copy a file out of the target environment. + + The target file will have the same permission mode as the source + file. + + :param source_path: the path to the file that should be copied, + relative to the target environment's root. + :param target_path: the path where the file should be installed in + the host system. + """ + raise NotImplementedError + + def path_exists(self, path): + """Test whether a path exists in the target environment. + + :param path: the path to the file to test, relative to the target + environment's root. + """ + try: + self.run(["test", "-e", path]) + return True + except subprocess.CalledProcessError: + return False + + def islink(self, path): + """Test whether a file is a symbolic link in the target environment. + + :param path: the path to the file to test, relative to the target + environment's root. + """ + try: + self.run(["test", "-h", path]) + return True + except subprocess.CalledProcessError: + return False + + def listdir(self, path): + """List a directory in the target environment. + + :param path: the path to the directory to list, relative to the + target environment's root. + """ + paths = self.run( + ["find", path, "-mindepth", "1", "-maxdepth", "1", + "-printf", "%P\\0"], + get_output=True).rstrip(b"\0").split(b"\0") + # XXX cjwatson 2017-08-04: Use `os.fsdecode` instead once we're on + # Python 3. + return [path.decode("UTF-8") for path in paths] + def kill_processes(self): """Kill any processes left running in the target. === modified file 'lpbuildd/target/chroot.py' --- lpbuildd/target/chroot.py 2017-08-05 09:47:12 +0000 +++ lpbuildd/target/chroot.py 2017-08-05 09:47:12 +0000 @@ -52,7 +52,8 @@ for path in ("/etc/hosts", "/etc/hostname", "/etc/resolv.conf"): self.copy_in(path, path) - def run(self, args, env=None, input_text=None, **kwargs): + def run(self, args, env=None, input_text=None, get_output=False, + **kwargs): """See `Backend`.""" if env: args = ["env"] + [ @@ -61,14 +62,17 @@ if self.arch is not None: args = set_personality(args, self.arch, series=self.series) cmd = ["sudo", "/usr/sbin/chroot", self.chroot_path] + args - if input_text is None: + if input_text is None and not get_output: subprocess.check_call(cmd, cwd=self.chroot_path, **kwargs) else: - proc = subprocess.Popen( - cmd, stdin=subprocess.PIPE, universal_newlines=True, **kwargs) - proc.communicate(input_text) + if get_output: + kwargs["stdout"] = subprocess.PIPE + proc = subprocess.Popen(cmd, stdin=subprocess.PIPE, **kwargs) + output, _ = proc.communicate(input_text) if proc.returncode: raise subprocess.CalledProcessError(proc.returncode, cmd) + if get_output: + return output def copy_in(self, source_path, target_path): """See `Backend`.""" @@ -82,6 +86,14 @@ ["sudo", "install", "-o", "root", "-g", "root", "-m", "%o" % mode, source_path, full_target_path]) + def copy_out(self, source_path, target_path): + # We can just use a plain copy here, since the file ownership in the + # host system isn't important. + full_source_path = os.path.join( + self.chroot_path, source_path.lstrip("/")) + subprocess.check_call( + ["sudo", "cp", "-p", full_source_path, target_path]) + def kill_processes(self): """See `Backend`.""" prefix = os.path.realpath(self.chroot_path) === modified file 'lpbuildd/target/override_sources_list.py' --- lpbuildd/target/override_sources_list.py 2017-08-05 09:47:12 +0000 +++ lpbuildd/target/override_sources_list.py 2017-08-05 09:47:12 +0000 @@ -6,6 +6,7 @@ __metaclass__ = type import logging +import os import tempfile from lpbuildd.target.operation import Operation @@ -31,5 +32,6 @@ for archive in self.args.archives: print(archive, file=sources_list) sources_list.flush() + os.fchmod(sources_list.fileno(), 0o644) self.backend.copy_in(sources_list.name, "/etc/apt/sources.list") return 0 === modified file 'lpbuildd/target/tests/test_chroot.py' --- lpbuildd/target/tests/test_chroot.py 2017-08-05 09:47:12 +0000 +++ lpbuildd/target/tests/test_chroot.py 2017-08-05 09:47:12 +0000 @@ -3,6 +3,7 @@ __metaclass__ = type +import io import os.path import signal from textwrap import dedent @@ -97,6 +98,25 @@ expected_args, [proc._args["args"] for proc in processes_fixture.procs]) + def test_run_get_output(self): + self.useFixture(EnvironmentVariable("HOME", "/expected/home")) + processes_fixture = self.useFixture(FakeProcesses()) + processes_fixture.add( + lambda _: {"stdout": io.BytesIO(b"hello\n")}, name="sudo") + self.assertEqual( + "hello\n", + Chroot("1", "xenial", "amd64").run( + ["echo", "hello"], get_output=True)) + + expected_args = [ + ["sudo", "/usr/sbin/chroot", + "/expected/home/build-1/chroot-autobuild", + "linux64", "echo", "hello"], + ] + self.assertEqual( + expected_args, + [proc._args["args"] for proc in processes_fixture.procs]) + def test_copy_in(self): self.useFixture(EnvironmentVariable("HOME", "/expected/home")) source_dir = self.useFixture(TempDir()).path @@ -119,6 +139,77 @@ expected_args, [proc._args["args"] for proc in processes_fixture.procs]) + def test_copy_out(self): + self.useFixture(EnvironmentVariable("HOME", "/expected/home")) + processes_fixture = self.useFixture(FakeProcesses()) + processes_fixture.add(lambda _: {}, name="sudo") + Chroot("1", "xenial", "amd64").copy_out( + "/path/to/source", "/path/to/target") + + expected_args = [ + ["sudo", "cp", "-p", + "/expected/home/build-1/chroot-autobuild/path/to/source", + "/path/to/target"], + ] + self.assertEqual( + expected_args, + [proc._args["args"] for proc in processes_fixture.procs]) + + def test_path_exists(self): + self.useFixture(EnvironmentVariable("HOME", "/expected/home")) + processes_fixture = self.useFixture(FakeProcesses()) + test_proc_infos = iter([{}, {"returncode": 1}]) + processes_fixture.add(lambda _: next(test_proc_infos), name="sudo") + self.assertTrue(Chroot("1", "xenial", "amd64").path_exists("/present")) + self.assertFalse(Chroot("1", "xenial", "amd64").path_exists("/absent")) + + expected_args = [ + ["sudo", "/usr/sbin/chroot", + "/expected/home/build-1/chroot-autobuild", + "linux64", "test", "-e", path] + for path in ("/present", "/absent") + ] + self.assertEqual( + expected_args, + [proc._args["args"] for proc in processes_fixture.procs]) + + def test_islink(self): + self.useFixture(EnvironmentVariable("HOME", "/expected/home")) + processes_fixture = self.useFixture(FakeProcesses()) + test_proc_infos = iter([{}, {"returncode": 1}]) + processes_fixture.add(lambda _: next(test_proc_infos), name="sudo") + self.assertTrue(Chroot("1", "xenial", "amd64").islink("/link")) + self.assertFalse(Chroot("1", "xenial", "amd64").islink("/file")) + + expected_args = [ + ["sudo", "/usr/sbin/chroot", + "/expected/home/build-1/chroot-autobuild", + "linux64", "test", "-h", path] + for path in ("/link", "/file") + ] + self.assertEqual( + expected_args, + [proc._args["args"] for proc in processes_fixture.procs]) + + def test_listdir(self): + self.useFixture(EnvironmentVariable("HOME", "/expected/home")) + processes_fixture = self.useFixture(FakeProcesses()) + processes_fixture.add( + lambda _: {"stdout": io.BytesIO(b"foo\0bar\0baz\0")}, name="sudo") + self.assertEqual( + ["foo", "bar", "baz"], + Chroot("1", "xenial", "amd64").listdir("/path")) + + expected_args = [ + ["sudo", "/usr/sbin/chroot", + "/expected/home/build-1/chroot-autobuild", + "linux64", "find", "/path", "-mindepth", "1", "-maxdepth", "1", + "-printf", "%P\\0"], + ] + self.assertEqual( + expected_args, + [proc._args["args"] for proc in processes_fixture.procs]) + def test_kill_processes(self): self.useFixture(EnvironmentVariable("HOME", "/expected/home")) fs_fixture = self.useFixture(FakeFilesystem()) === modified file 'lpbuildd/target/tests/test_override_sources_list.py' --- lpbuildd/target/tests/test_override_sources_list.py 2017-08-05 09:47:12 +0000 +++ lpbuildd/target/tests/test_override_sources_list.py 2017-08-05 09:47:12 +0000 @@ -3,6 +3,7 @@ __metaclass__ = type +import stat from textwrap import dedent from testtools import TestCase @@ -20,9 +21,9 @@ ] override_sources_list = OverrideSourcesList(args=args) self.assertEqual(0, override_sources_list.run()) - self.assertEqual({ - "/etc/apt/sources.list": dedent("""\ + self.assertEqual( + (dedent("""\ deb http://archive.ubuntu.com/ubuntu xenial main deb http://ppa.launchpad.net/launchpad/ppa/ubuntu xenial main - """).encode("UTF-8"), - }, override_sources_list.backend.copied_in) + """).encode("UTF-8"), stat.S_IFREG | 0o644), + override_sources_list.backend.backend_fs["/etc/apt/sources.list"]) === modified file 'lpbuildd/tests/fakeslave.py' --- lpbuildd/tests/fakeslave.py 2017-08-05 09:47:12 +0000 +++ lpbuildd/tests/fakeslave.py 2017-08-05 09:47:12 +0000 @@ -10,6 +10,7 @@ import hashlib import os import shutil +import stat from lpbuildd.target.backend import Backend @@ -117,8 +118,55 @@ ) for fake_method in fake_methods: setattr(self, fake_method, FakeMethod()) - self.copied_in = {} + self.backend_fs = {} + + def _add_inode(self, path, contents, full_mode): + path = os.path.normpath(path) + parent = os.path.dirname(path) + if parent != path and parent not in self.backend_fs: + self.add_dir(parent) + self.backend_fs[path] = (contents, full_mode) + + def add_dir(self, path, mode=0o755): + self._add_inode(path, None, stat.S_IFDIR | mode) + + def add_file(self, path, contents, mode=0o644): + self._add_inode(path, contents, stat.S_IFREG | mode) + + def add_link(self, path, target): + self._add_inode(path, target, stat.S_IFLNK | 0o777) def copy_in(self, source_path, target_path): with open(source_path, "rb") as source: - self.copied_in[target_path] = source.read() + self.add_file( + target_path, source.read(), os.fstat(source.fileno()).st_mode) + + def _get_inode(self, path): + while True: + contents, mode = self.backend_fs[path] + if not stat.S_ISLNK(mode): + return contents, mode + path = os.path.normpath( + os.path.join(os.path.dirname(path), contents)) + + def copy_out(self, source_path, target_path): + contents, mode = self._get_inode(source_path) + with open(target_path, "wb") as target: + target.write(contents) + os.fchmod(target.fileno(), stat.S_IMODE(mode)) + + def path_exists(self, path): + try: + self._get_inode(path) + return True + except KeyError: + return False + + def islink(self, path): + _, mode = self.backend_fs.get(path, (b"", 0)) + return stat.S_ISLNK(mode) + + def listdir(self, path): + return [ + os.path.basename(p) for p in self.backend_fs + if os.path.dirname(p) == path] === modified file 'lpbuildd/tests/test_livefs.py' --- lpbuildd/tests/test_livefs.py 2017-08-05 09:47:12 +0000 +++ lpbuildd/tests/test_livefs.py 2017-08-05 09:47:12 +0000 @@ -4,9 +4,11 @@ __metaclass__ = type import os -import shutil -import tempfile +from fixtures import ( + EnvironmentVariable, + TempDir, + ) from testtools import TestCase from lpbuildd.livefs import ( @@ -35,19 +37,16 @@ """Run LiveFilesystemBuildManager through its iteration steps.""" def setUp(self): super(TestLiveFilesystemBuildManagerIteration, self).setUp() - self.working_dir = tempfile.mkdtemp() - self.addCleanup(lambda: shutil.rmtree(self.working_dir)) + self.working_dir = self.useFixture(TempDir()).path slave_dir = os.path.join(self.working_dir, "slave") home_dir = os.path.join(self.working_dir, "home") for dir in (slave_dir, home_dir): os.mkdir(dir) + self.useFixture(EnvironmentVariable("HOME", home_dir)) self.slave = FakeSlave(slave_dir) self.buildid = "123" self.buildmanager = MockBuildManager(self.slave, self.buildid) - self.buildmanager.home = home_dir self.buildmanager._cachepath = self.slave._cachepath - self.build_dir = os.path.join( - home_dir, "build-%s" % self.buildid, "chroot-autobuild", "build") def getState(self): """Retrieve build manager's state.""" @@ -62,7 +61,10 @@ "pocket": "release", "arch_tag": "i386", } + original_backend_name = self.buildmanager.backend_name + self.buildmanager.backend_name = "fake" self.buildmanager.initiate({}, "chroot.tar.gz", extra_args) + self.buildmanager.backend_name = original_backend_name # Skip states that are done in DebianBuildManager to the state # directly before BUILD_LIVEFS. @@ -90,10 +92,8 @@ with open(log_path, "w") as log: log.write("I am a build log.") - os.makedirs(self.build_dir) - manifest_path = os.path.join(self.build_dir, "livecd.ubuntu.manifest") - with open(manifest_path, "w") as manifest: - manifest.write("I am a manifest file.") + self.buildmanager.backend.add_file( + "/build/livecd.ubuntu.manifest", b"I am a manifest file.") # After building the package, reap processes. self.buildmanager.iterate(0) @@ -133,13 +133,10 @@ with open(log_path, "w") as log: log.write("I am a build log.") - os.makedirs(self.build_dir) - target_path = os.path.join( - self.build_dir, "livecd.ubuntu.kernel-generic") - with open(target_path, "w") as target: - target.write("I am a kernel.") - link_path = os.path.join(self.build_dir, "livecd.ubuntu.kernel") - os.symlink("livecd.ubuntu.kernel-generic", link_path) + self.buildmanager.backend.add_file( + "/build/livecd.ubuntu.kernel-generic", b"I am a kernel.") + self.buildmanager.backend.add_link( + "/build/livecd.ubuntu.kernel", "livefs.ubuntu.kernel-generic") self.buildmanager.iterate(0) self.assertThat(self.slave, HasWaitingFiles.byEquality({ === modified file 'lpbuildd/tests/test_snap.py' --- lpbuildd/tests/test_snap.py 2017-08-05 09:47:12 +0000 +++ lpbuildd/tests/test_snap.py 2017-08-05 09:47:12 +0000 @@ -4,9 +4,11 @@ __metaclass__ = type import os -import shutil -import tempfile +from fixtures import ( + EnvironmentVariable, + TempDir, + ) from testtools import TestCase from lpbuildd.snap import ( @@ -35,19 +37,16 @@ """Run SnapBuildManager through its iteration steps.""" def setUp(self): super(TestSnapBuildManagerIteration, self).setUp() - self.working_dir = tempfile.mkdtemp() - self.addCleanup(lambda: shutil.rmtree(self.working_dir)) + self.working_dir = self.useFixture(TempDir()).path slave_dir = os.path.join(self.working_dir, "slave") home_dir = os.path.join(self.working_dir, "home") for dir in (slave_dir, home_dir): os.mkdir(dir) + self.useFixture(EnvironmentVariable("HOME", home_dir)) self.slave = FakeSlave(slave_dir) self.buildid = "123" self.buildmanager = MockBuildManager(self.slave, self.buildid) - self.buildmanager.home = home_dir self.buildmanager._cachepath = self.slave._cachepath - self.build_dir = os.path.join( - home_dir, "build-%s" % self.buildid, "chroot-autobuild", "build") def getState(self): """Retrieve build manager's state.""" @@ -63,7 +62,10 @@ "git_repository": "https://git.launchpad.dev/~example/+git/snap", "git_path": "master", } + original_backend_name = self.buildmanager.backend_name + self.buildmanager.backend_name = "fake" self.buildmanager.initiate({}, "chroot.tar.gz", extra_args) + self.buildmanager.backend_name = original_backend_name # Skip states that are done in DebianBuildManager to the state # directly before BUILD_SNAP. @@ -102,11 +104,8 @@ with open(log_path, "w") as log: log.write("I am a build log.") - output_dir = os.path.join(self.build_dir, "test-snap") - os.makedirs(output_dir) - snap_path = os.path.join(output_dir, "test-snap_0_all.snap") - with open(snap_path, "w") as snap: - snap.write("I am a snap package.") + self.buildmanager.backend.add_file( + "/build/test-snap/test-snap_0_all.snap", b"I am a snap package.") # After building the package, reap processes. self.buildmanager.iterate(0) @@ -146,14 +145,10 @@ with open(log_path, "w") as log: log.write("I am a build log.") - output_dir = os.path.join(self.build_dir, "test-snap") - os.makedirs(output_dir) - snap_path = os.path.join(output_dir, "test-snap_0_all.snap") - with open(snap_path, "w") as snap: - snap.write("I am a snap package.") - manifest_path = os.path.join(output_dir, "test-snap_0_all.manifest") - with open(manifest_path, "w") as manifest: - manifest.write("I am a manifest.") + self.buildmanager.backend.add_file( + "/build/test-snap/test-snap_0_all.snap", b"I am a snap package.") + self.buildmanager.backend.add_file( + "/build/test-snap/test-snap_0_all.manifest", b"I am a manifest.") # After building the package, reap processes. self.buildmanager.iterate(0) === modified file 'lpbuildd/tests/test_translationtemplatesbuildmanager.py' --- lpbuildd/tests/test_translationtemplatesbuildmanager.py 2017-08-05 09:47:12 +0000 +++ lpbuildd/tests/test_translationtemplatesbuildmanager.py 2017-08-05 09:47:12 +0000 @@ -4,9 +4,11 @@ __metaclass__ = type import os -import shutil -import tempfile +from fixtures import ( + EnvironmentVariable, + TempDir, + ) from testtools import TestCase from lpbuildd.tests.fakeslave import FakeSlave @@ -35,16 +37,15 @@ """Run TranslationTemplatesBuildManager through its iteration steps.""" def setUp(self): super(TestTranslationTemplatesBuildManagerIteration, self).setUp() - self.working_dir = tempfile.mkdtemp() - self.addCleanup(lambda: shutil.rmtree(self.working_dir)) + self.working_dir = self.useFixture(TempDir()).path slave_dir = os.path.join(self.working_dir, 'slave') home_dir = os.path.join(self.working_dir, 'home') for dir in (slave_dir, home_dir): os.mkdir(dir) + self.useFixture(EnvironmentVariable("HOME", home_dir)) self.slave = FakeSlave(slave_dir) self.buildid = '123' self.buildmanager = MockBuildManager(self.slave, self.buildid) - self.buildmanager.home = home_dir self.chrootdir = os.path.join( home_dir, 'build-%s' % self.buildid, 'chroot-autobuild') @@ -57,8 +58,11 @@ url = 'lp:~my/branch' # The build manager's iterate() kicks off the consecutive states # after INIT. + original_backend_name = self.buildmanager.backend_name + self.buildmanager.backend_name = "fake" self.buildmanager.initiate( {}, 'chroot.tar.gz', {'series': 'xenial', 'branch_url': url}) + self.buildmanager.backend_name = original_backend_name # Skip states that are done in DebianBuildManager to the state # directly before INSTALL. @@ -94,12 +98,9 @@ self.assertFalse(self.slave.wasCalled('chrootFail')) outfile_path = os.path.join( - self.chrootdir, self.buildmanager.home[1:], - self.buildmanager._resultname) - os.makedirs(os.path.dirname(outfile_path)) - - with open(outfile_path, 'w') as outfile: - outfile.write("I am a template tarball. Seriously.") + self.buildmanager.home, self.buildmanager._resultname) + self.buildmanager.backend.add_file( + outfile_path, b"I am a template tarball. Seriously.") # After generating templates, reap processes. self.buildmanager.iterate(0) @@ -166,7 +167,7 @@ self.buildmanager.initiate( {}, 'chroot.tar.gz', {'series': 'xenial', 'branch_url': url}) - # Skip states to the INSTALL state. + # Skip states to the GENERATE state. self.buildmanager._state = TranslationTemplatesBuildState.GENERATE # The buildmanager fails and reaps processes. === modified file 'lpbuildd/translationtemplates.py' --- lpbuildd/translationtemplates.py 2015-05-11 05:39:25 +0000 +++ lpbuildd/translationtemplates.py 2017-08-05 09:47:12 +0000 @@ -64,12 +64,9 @@ """Gather the results of the build and add them to the file cache.""" # The file is inside the chroot, in the home directory of the buildd # user. Should be safe to assume the home dirs are named identically. - assert self.home.startswith('/'), "home directory must be absolute." - - path = os.path.join( - self._chroot_path, self.home[1:], self._resultname) - if os.access(path, os.F_OK): - self._slave.addWaitingFile(path) + path = os.path.join(self.home, self._resultname) + if self.backend.path_exists(path): + self.addWaitingFileFromBackend(path) def iterate_INSTALL(self, success): """Installation was done."""
_______________________________________________ Mailing list: https://launchpad.net/~launchpad-reviewers Post to : launchpad-reviewers@lists.launchpad.net Unsubscribe : https://launchpad.net/~launchpad-reviewers More help : https://help.launchpad.net/ListHelp