Merge lp:~cjwatson/launchpad-buildd/backend-run-cwd into lp:launchpad-buildd

Proposed by Colin Watson
Status: Merged
Merged at revision: 308
Proposed branch: lp:~cjwatson/launchpad-buildd/backend-run-cwd
Merge into: lp:launchpad-buildd
Diff against target: 688 lines (+168/-166)
9 files modified
debian/changelog (+3/-0)
lpbuildd/target/backend.py (+2/-1)
lpbuildd/target/build_livefs.py (+3/-16)
lpbuildd/target/build_snap.py (+6/-21)
lpbuildd/target/chroot.py (+11/-1)
lpbuildd/target/lxd.py (+11/-1)
lpbuildd/target/tests/test_build_livefs.py (+48/-38)
lpbuildd/target/tests/test_build_snap.py (+80/-85)
lpbuildd/tests/fakeslave.py (+4/-3)
To merge this branch: bzr merge lp:~cjwatson/launchpad-buildd/backend-run-cwd
Reviewer Review Type Date Requested Status
William Grant code Approve
Review via email: mp+333569@code.launchpad.net

Commit message

Make Backend.run(cwd=) work, and refactor BuildLiveFS and BuildSnap to
use it. This fixes translation templates builds, which were assuming
that this worked.

To post a comment you must log in.
Revision history for this message
William Grant (wgrant) :
review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'debian/changelog'
2--- debian/changelog 2017-11-09 14:55:22 +0000
3+++ debian/changelog 2017-11-10 20:56:18 +0000
4@@ -5,6 +5,9 @@
5 * Replace shell_escape function with shlex.quote (Python 3) or pipes.quote
6 (Python 2).
7 * Fix handling of null/empty-domain case in generate_pots.
8+ * Make Backend.run(cwd=) work, and refactor BuildLiveFS and BuildSnap to
9+ use it. This fixes translation templates builds, which were assuming
10+ that this worked.
11
12 -- Colin Watson <cjwatson@ubuntu.com> Thu, 09 Nov 2017 12:08:42 +0000
13
14
15=== modified file 'lpbuildd/target/backend.py'
16--- lpbuildd/target/backend.py 2017-11-01 23:08:22 +0000
17+++ lpbuildd/target/backend.py 2017-11-10 20:56:18 +0000
18@@ -36,11 +36,12 @@
19 """
20 raise NotImplementedError
21
22- def run(self, args, env=None, input_text=None, get_output=False,
23+ def run(self, args, cwd=None, env=None, input_text=None, get_output=False,
24 echo=False, **kwargs):
25 """Run a command in the target environment.
26
27 :param args: the command and arguments to run.
28+ :param cwd: run the command in this working directory in the target.
29 :param env: additional environment variables to set.
30 :param input_text: input text to pass on the command's stdin.
31 :param get_output: if True, return the output from the command.
32
33=== modified file 'lpbuildd/target/build_livefs.py'
34--- lpbuildd/target/build_livefs.py 2017-09-13 09:32:19 +0000
35+++ lpbuildd/target/build_livefs.py 2017-11-10 20:56:18 +0000
36@@ -10,7 +10,6 @@
37 import os
38
39 from lpbuildd.target.operation import Operation
40-from lpbuildd.util import shell_escape
41
42
43 RETCODE_FAILURE_INSTALL = 200
44@@ -62,25 +61,13 @@
45 "--debug", default=False, action="store_true",
46 help="enable detailed live-build debugging")
47
48- def run_build_command(self, args, env=None, echo=False):
49+ def run_build_command(self, args, **kwargs):
50 """Run a build command in the chroot.
51
52- This is unpleasant because we need to run it in /build under sudo
53- chroot, and there's no way to do this without either a helper
54- program in the chroot or unpleasant quoting. We go for the
55- unpleasant quoting.
56-
57 :param args: the command and arguments to run.
58- :param env: dictionary of additional environment variables to set.
59- :param echo: if True, print the command before executing it.
60+ :param kwargs: any other keyword arguments to pass to Backend.run.
61 """
62- args = [shell_escape(arg) for arg in args]
63- if env:
64- args = ["env"] + [
65- "%s=%s" % (key, shell_escape(value))
66- for key, value in env.items()] + args
67- command = "cd /build && %s" % " ".join(args)
68- self.backend.run(["/bin/sh", "-c", command], echo=echo)
69+ return self.backend.run(args, cwd="/build", **kwargs)
70
71 def install(self):
72 deps = ["livecd-rootfs"]
73
74=== modified file 'lpbuildd/target/build_snap.py'
75--- lpbuildd/target/build_snap.py 2017-10-27 07:52:32 +0000
76+++ lpbuildd/target/build_snap.py 2017-11-10 20:56:18 +0000
77@@ -32,7 +32,6 @@
78 from urlparse import urlparse
79
80 from lpbuildd.target.operation import Operation
81-from lpbuildd.util import shell_escape
82
83
84 RETCODE_FAILURE_INSTALL = 200
85@@ -73,34 +72,20 @@
86 # appropriate certificate for your codehosting system.
87 self.ssl_verify = True
88
89- def run_build_command(self, args, path="/build", env=None,
90- get_output=False, echo=False):
91+ def run_build_command(self, args, cwd="/build", env=None, **kwargs):
92 """Run a build command in the target.
93
94- This is unpleasant because we need to run it with /build as the
95- working directory, and there's no way to do this without either a
96- helper program in the target or unpleasant quoting. We go for the
97- unpleasant quoting.
98-
99 :param args: the command and arguments to run.
100- :param path: the working directory to use in the target.
101+ :param cwd: run the command in this working directory in the target.
102 :param env: dictionary of additional environment variables to set.
103- :param get_output: if True, return the output from the command.
104- :param echo: if True, print the command before executing it.
105+ :param kwargs: any other keyword arguments to pass to Backend.run.
106 """
107- args = [shell_escape(arg) for arg in args]
108- path = shell_escape(path)
109 full_env = OrderedDict()
110 full_env["LANG"] = "C.UTF-8"
111 full_env["SHELL"] = "/bin/sh"
112 if env:
113 full_env.update(env)
114- args = ["env"] + [
115- "%s=%s" % (key, shell_escape(value))
116- for key, value in full_env.items()] + args
117- command = "cd %s && %s" % (path, " ".join(args))
118- return self.backend.run(
119- ["/bin/sh", "-c", command], get_output=get_output, echo=echo)
120+ return self.backend.run(args, cwd=cwd, env=full_env, **kwargs)
121
122 def save_status(self, status):
123 """Save a dictionary of status information about this build.
124@@ -190,7 +175,7 @@
125 env["GIT_PROXY_COMMAND"] = "/usr/local/bin/snap-git-proxy"
126 self.run_build_command(
127 ["snapcraft", "pull"],
128- path=os.path.join("/build", self.args.name),
129+ cwd=os.path.join("/build", self.args.name),
130 env=env)
131
132 def build(self):
133@@ -203,7 +188,7 @@
134 env["GIT_PROXY_COMMAND"] = "/usr/local/bin/snap-git-proxy"
135 self.run_build_command(
136 ["snapcraft"],
137- path=os.path.join("/build", self.args.name),
138+ cwd=os.path.join("/build", self.args.name),
139 env=env)
140
141 def revoke_token(self):
142
143=== modified file 'lpbuildd/target/chroot.py'
144--- lpbuildd/target/chroot.py 2017-11-09 12:09:12 +0000
145+++ lpbuildd/target/chroot.py 2017-11-10 20:56:18 +0000
146@@ -52,7 +52,7 @@
147 for path in ("/etc/hosts", "/etc/hostname", "/etc/resolv.conf"):
148 self.copy_in(path, path)
149
150- def run(self, args, env=None, input_text=None, get_output=False,
151+ def run(self, args, cwd=None, env=None, input_text=None, get_output=False,
152 echo=False, **kwargs):
153 """See `Backend`."""
154 if env:
155@@ -61,6 +61,16 @@
156 for key, value in env.items()] + args
157 if self.arch is not None:
158 args = set_personality(args, self.arch, series=self.series)
159+ if cwd is not None:
160+ # This requires either a helper program in the chroot or
161+ # unpleasant quoting. For now we go for the unpleasant quoting,
162+ # though once we have coreutils >= 8.28 everywhere we'll be able
163+ # to use "env --chdir".
164+ args = [
165+ "/bin/sh", "-c", "cd %s && %s" % (
166+ shell_escape(cwd),
167+ " ".join(shell_escape(arg) for arg in args)),
168+ ]
169 if echo:
170 print("Running in chroot: %s" % ' '.join(
171 shell_escape(arg) for arg in args))
172
173=== modified file 'lpbuildd/target/lxd.py'
174--- lpbuildd/target/lxd.py 2017-11-01 11:17:44 +0000
175+++ lpbuildd/target/lxd.py 2017-11-10 20:56:18 +0000
176@@ -419,7 +419,7 @@
177 no_cdn_file.name,
178 "/etc/systemd/system/snapd.service.d/no-cdn.conf")
179
180- def run(self, args, env=None, input_text=None, get_output=False,
181+ def run(self, args, cwd=None, env=None, input_text=None, get_output=False,
182 echo=False, **kwargs):
183 """See `Backend`."""
184 env_params = []
185@@ -428,6 +428,16 @@
186 env_params.extend(["--env", "%s=%s" % (key, value)])
187 if self.arch is not None:
188 args = set_personality(args, self.arch, series=self.series)
189+ if cwd is not None:
190+ # This requires either a helper program in the chroot or
191+ # unpleasant quoting. For now we go for the unpleasant quoting,
192+ # though once we have coreutils >= 8.28 everywhere we'll be able
193+ # to use "env --chdir".
194+ args = [
195+ "/bin/sh", "-c", "cd %s && %s" % (
196+ shell_escape(cwd),
197+ " ".join(shell_escape(arg) for arg in args)),
198+ ]
199 if echo:
200 print("Running in container: %s" % ' '.join(
201 shell_escape(arg) for arg in args))
202
203=== modified file 'lpbuildd/target/tests/test_build_livefs.py'
204--- lpbuildd/target/tests/test_build_livefs.py 2017-11-09 12:15:39 +0000
205+++ lpbuildd/target/tests/test_build_livefs.py 2017-11-10 20:56:18 +0000
206@@ -26,12 +26,15 @@
207
208 class RanCommand(MatchesListwise):
209
210- def __init__(self, args, echo=None, **env):
211+ def __init__(self, args, echo=None, cwd=None, **env):
212 kwargs_matcher = {}
213 if echo is not None:
214 kwargs_matcher["echo"] = Is(echo)
215+ if cwd:
216+ kwargs_matcher["cwd"] = Equals(cwd)
217 if env:
218- kwargs_matcher["env"] = MatchesDict(env)
219+ kwargs_matcher["env"] = MatchesDict(
220+ {key: Equals(value) for key, value in env.items()})
221 super(RanCommand, self).__init__(
222 [Equals((args,)), MatchesDict(kwargs_matcher)])
223
224@@ -44,9 +47,8 @@
225
226 class RanBuildCommand(RanCommand):
227
228- def __init__(self, command):
229- super(RanBuildCommand, self).__init__(
230- ["/bin/sh", "-c", "cd /build && " + command], echo=False)
231+ def __init__(self, args, **kwargs):
232+ super(RanBuildCommand, self).__init__(args, cwd="/build", **kwargs)
233
234
235 class TestBuildLiveFS(TestCase):
236@@ -59,7 +61,7 @@
237 build_livefs = parse_args(args=args).operation
238 build_livefs.run_build_command(["echo", "hello world"])
239 self.assertThat(build_livefs.backend.run.calls, MatchesListwise([
240- RanBuildCommand("echo 'hello world'"),
241+ RanBuildCommand(["echo", "hello world"]),
242 ]))
243
244 def test_run_build_command_env(self):
245@@ -71,7 +73,7 @@
246 build_livefs.run_build_command(
247 ["echo", "hello world"], env={"FOO": "bar baz"})
248 self.assertThat(build_livefs.backend.run.calls, MatchesListwise([
249- RanBuildCommand("env FOO='bar baz' echo 'hello world'"),
250+ RanBuildCommand(["echo", "hello world"], FOO="bar baz"),
251 ]))
252
253 def test_install(self):
254@@ -120,18 +122,22 @@
255 build_livefs = parse_args(args=args).operation
256 build_livefs.build()
257 self.assertThat(build_livefs.backend.run.calls, MatchesListwise([
258- RanBuildCommand("rm -rf auto local"),
259- RanBuildCommand("mkdir -p auto"),
260- RanBuildCommand(
261- "ln -s /usr/share/livecd-rootfs/live-build/auto/config auto/"),
262- RanBuildCommand(
263- "ln -s /usr/share/livecd-rootfs/live-build/auto/build auto/"),
264- RanBuildCommand(
265- "ln -s /usr/share/livecd-rootfs/live-build/auto/clean auto/"),
266- RanBuildCommand("lb clean --purge"),
267- RanBuildCommand(
268- "env PROJECT=ubuntu ARCH=amd64 SUITE=xenial lb config"),
269- RanBuildCommand("env PROJECT=ubuntu ARCH=amd64 lb build"),
270+ RanBuildCommand(["rm", "-rf", "auto", "local"]),
271+ RanBuildCommand(["mkdir", "-p", "auto"]),
272+ RanBuildCommand(
273+ ["ln", "-s",
274+ "/usr/share/livecd-rootfs/live-build/auto/config", "auto/"]),
275+ RanBuildCommand(
276+ ["ln", "-s",
277+ "/usr/share/livecd-rootfs/live-build/auto/build", "auto/"]),
278+ RanBuildCommand(
279+ ["ln", "-s",
280+ "/usr/share/livecd-rootfs/live-build/auto/clean", "auto/"]),
281+ RanBuildCommand(["lb", "clean", "--purge"]),
282+ RanBuildCommand(
283+ ["lb", "config"],
284+ PROJECT="ubuntu", ARCH="amd64", SUITE="xenial"),
285+ RanBuildCommand(["lb", "build"], PROJECT="ubuntu", ARCH="amd64"),
286 ]))
287
288 def test_build_locale(self):
289@@ -144,8 +150,8 @@
290 build_livefs.build()
291 self.assertThat(build_livefs.backend.run.calls, MatchesListwise([
292 RanBuildCommand(
293- "ubuntu-defaults-image --locale zh_CN --arch amd64 "
294- "--release xenial"),
295+ ["ubuntu-defaults-image", "--locale", "zh_CN",
296+ "--arch", "amd64", "--release", "xenial"]),
297 ]))
298
299 def test_build_debug(self):
300@@ -157,21 +163,25 @@
301 build_livefs = parse_args(args=args).operation
302 build_livefs.build()
303 self.assertThat(build_livefs.backend.run.calls, MatchesListwise([
304- RanBuildCommand("rm -rf auto local"),
305- RanBuildCommand("mkdir -p auto"),
306- RanBuildCommand(
307- "ln -s /usr/share/livecd-rootfs/live-build/auto/config auto/"),
308- RanBuildCommand(
309- "ln -s /usr/share/livecd-rootfs/live-build/auto/build auto/"),
310- RanBuildCommand(
311- "ln -s /usr/share/livecd-rootfs/live-build/auto/clean auto/"),
312- RanBuildCommand("mkdir -p local/functions"),
313- RanBuildCommand(
314- "sh -c 'echo '\"'\"'set -x'\"'\"' >local/functions/debug.sh'"),
315- RanBuildCommand("lb clean --purge"),
316- RanBuildCommand(
317- "env PROJECT=ubuntu ARCH=amd64 SUITE=xenial lb config"),
318- RanBuildCommand("env PROJECT=ubuntu ARCH=amd64 lb build"),
319+ RanBuildCommand(["rm", "-rf", "auto", "local"]),
320+ RanBuildCommand(["mkdir", "-p", "auto"]),
321+ RanBuildCommand(
322+ ["ln", "-s",
323+ "/usr/share/livecd-rootfs/live-build/auto/config", "auto/"]),
324+ RanBuildCommand(
325+ ["ln", "-s",
326+ "/usr/share/livecd-rootfs/live-build/auto/build", "auto/"]),
327+ RanBuildCommand(
328+ ["ln", "-s",
329+ "/usr/share/livecd-rootfs/live-build/auto/clean", "auto/"]),
330+ RanBuildCommand(["mkdir", "-p", "local/functions"]),
331+ RanBuildCommand(
332+ ["sh", "-c", "echo 'set -x' >local/functions/debug.sh"]),
333+ RanBuildCommand(["lb", "clean", "--purge"]),
334+ RanBuildCommand(
335+ ["lb", "config"],
336+ PROJECT="ubuntu", ARCH="amd64", SUITE="xenial"),
337+ RanBuildCommand(["lb", "build"], PROJECT="ubuntu", ARCH="amd64"),
338 ]))
339
340 def test_run_succeeds(self):
341@@ -185,7 +195,7 @@
342 self.assertThat(build_livefs.backend.run.calls, MatchesAll(
343 AnyMatch(RanAptGet("install", "livecd-rootfs")),
344 AnyMatch(RanBuildCommand(
345- "env PROJECT=ubuntu ARCH=amd64 lb build"))))
346+ ["lb", "build"], PROJECT="ubuntu", ARCH="amd64"))))
347
348 def test_run_install_fails(self):
349 class FailInstall(FakeMethod):
350@@ -208,7 +218,7 @@
351 class FailBuild(FakeMethod):
352 def __call__(self, run_args, *args, **kwargs):
353 super(FailBuild, self).__call__(run_args, *args, **kwargs)
354- if run_args[0] == "/bin/sh":
355+ if run_args[0] == "rm":
356 raise subprocess.CalledProcessError(1, run_args)
357
358 self.useFixture(FakeLogger())
359
360=== modified file 'lpbuildd/target/tests/test_build_snap.py'
361--- lpbuildd/target/tests/test_build_snap.py 2017-09-13 12:21:44 +0000
362+++ lpbuildd/target/tests/test_build_snap.py 2017-11-10 20:56:18 +0000
363@@ -33,14 +33,17 @@
364
365 class RanCommand(MatchesListwise):
366
367- def __init__(self, args, get_output=None, echo=None, **env):
368+ def __init__(self, args, get_output=None, echo=None, cwd=None, **env):
369 kwargs_matcher = {}
370 if get_output is not None:
371 kwargs_matcher["get_output"] = Is(get_output)
372 if echo is not None:
373 kwargs_matcher["echo"] = Is(echo)
374+ if cwd:
375+ kwargs_matcher["cwd"] = Equals(cwd)
376 if env:
377- kwargs_matcher["env"] = MatchesDict(env)
378+ kwargs_matcher["env"] = MatchesDict(
379+ {key: Equals(value) for key, value in env.items()})
380 super(RanCommand, self).__init__(
381 [Equals((args,)), MatchesDict(kwargs_matcher)])
382
383@@ -53,10 +56,10 @@
384
385 class RanBuildCommand(RanCommand):
386
387- def __init__(self, command, path="/build", get_output=False):
388- super(RanBuildCommand, self).__init__(
389- ["/bin/sh", "-c", "cd %s && %s" % (path, command)],
390- get_output=get_output, echo=False)
391+ def __init__(self, args, cwd="/build", **kwargs):
392+ kwargs.setdefault("LANG", "C.UTF-8")
393+ kwargs.setdefault("SHELL", "/bin/sh")
394+ super(RanBuildCommand, self).__init__(args, cwd=cwd, **kwargs)
395
396
397 class FakeRevisionID(FakeMethod):
398@@ -67,10 +70,9 @@
399
400 def __call__(self, run_args, *args, **kwargs):
401 super(FakeRevisionID, self).__call__(run_args, *args, **kwargs)
402- if run_args[0] == "/bin/sh":
403- command = run_args[2]
404- if "bzr revno" in command or "rev-parse" in command:
405- return "%s\n" % self.revision_id
406+ if (run_args[:2] == ["bzr", "revno"] or
407+ (run_args[0] == "git" and "rev-parse" in run_args)):
408+ return "%s\n" % self.revision_id
409
410
411 class TestBuildSnap(TestCase):
412@@ -84,8 +86,7 @@
413 build_snap = parse_args(args=args).operation
414 build_snap.run_build_command(["echo", "hello world"])
415 self.assertThat(build_snap.backend.run.calls, MatchesListwise([
416- RanBuildCommand(
417- "env LANG=C.UTF-8 SHELL=/bin/sh echo 'hello world'"),
418+ RanBuildCommand(["echo", "hello world"]),
419 ]))
420
421 def test_run_build_command_env(self):
422@@ -98,9 +99,7 @@
423 build_snap.run_build_command(
424 ["echo", "hello world"], env={"FOO": "bar baz"})
425 self.assertThat(build_snap.backend.run.calls, MatchesListwise([
426- RanBuildCommand(
427- "env LANG=C.UTF-8 SHELL=/bin/sh FOO='bar baz' "
428- "echo 'hello world'"),
429+ RanBuildCommand(["echo", "hello world"], FOO="bar baz"),
430 ]))
431
432 def test_install_bzr(self):
433@@ -160,11 +159,10 @@
434 build_snap.backend.build_path = self.useFixture(TempDir()).path
435 build_snap.backend.run = FakeRevisionID("42")
436 build_snap.repo()
437- env = "env LANG=C.UTF-8 SHELL=/bin/sh "
438 self.assertThat(build_snap.backend.run.calls, MatchesListwise([
439- RanBuildCommand(env + "ls /build"),
440- RanBuildCommand(env + "bzr branch lp:foo test-snap"),
441- RanBuildCommand(env + "bzr revno test-snap", get_output=True),
442+ RanBuildCommand(["ls", "/build"]),
443+ RanBuildCommand(["bzr", "branch", "lp:foo", "test-snap"]),
444+ RanBuildCommand(["bzr", "revno", "test-snap"], get_output=True),
445 ]))
446 status_path = os.path.join(build_snap.backend.build_path, "status")
447 with open(status_path) as status:
448@@ -180,13 +178,14 @@
449 build_snap.backend.build_path = self.useFixture(TempDir()).path
450 build_snap.backend.run = FakeRevisionID("0" * 40)
451 build_snap.repo()
452- env = "env LANG=C.UTF-8 SHELL=/bin/sh "
453 self.assertThat(build_snap.backend.run.calls, MatchesListwise([
454- RanBuildCommand(env + "git clone lp:foo test-snap"),
455- RanBuildCommand(
456- env + "git -C test-snap submodule update --init --recursive"),
457- RanBuildCommand(
458- env + "git -C test-snap rev-parse HEAD", get_output=True),
459+ RanBuildCommand(["git", "clone", "lp:foo", "test-snap"]),
460+ RanBuildCommand(
461+ ["git", "-C", "test-snap",
462+ "submodule", "update", "--init", "--recursive"]),
463+ RanBuildCommand(
464+ ["git", "-C", "test-snap", "rev-parse", "HEAD"],
465+ get_output=True),
466 ]))
467 status_path = os.path.join(build_snap.backend.build_path, "status")
468 with open(status_path) as status:
469@@ -202,13 +201,15 @@
470 build_snap.backend.build_path = self.useFixture(TempDir()).path
471 build_snap.backend.run = FakeRevisionID("0" * 40)
472 build_snap.repo()
473- env = "env LANG=C.UTF-8 SHELL=/bin/sh "
474 self.assertThat(build_snap.backend.run.calls, MatchesListwise([
475- RanBuildCommand(env + "git clone -b next lp:foo test-snap"),
476- RanBuildCommand(
477- env + "git -C test-snap submodule update --init --recursive"),
478- RanBuildCommand(
479- env + "git -C test-snap rev-parse next", get_output=True),
480+ RanBuildCommand(
481+ ["git", "clone", "-b", "next", "lp:foo", "test-snap"]),
482+ RanBuildCommand(
483+ ["git", "-C", "test-snap",
484+ "submodule", "update", "--init", "--recursive"]),
485+ RanBuildCommand(
486+ ["git", "-C", "test-snap", "rev-parse", "next"],
487+ get_output=True),
488 ]))
489 status_path = os.path.join(build_snap.backend.build_path, "status")
490 with open(status_path) as status:
491@@ -226,18 +227,18 @@
492 build_snap.backend.build_path = self.useFixture(TempDir()).path
493 build_snap.backend.run = FakeRevisionID("0" * 40)
494 build_snap.repo()
495- env = (
496- "env LANG=C.UTF-8 SHELL=/bin/sh "
497- "http_proxy=http://proxy.example:3128/ "
498- "https_proxy=http://proxy.example:3128/ "
499- "GIT_PROXY_COMMAND=/usr/local/bin/snap-git-proxy ")
500+ env = {
501+ "http_proxy": "http://proxy.example:3128/",
502+ "https_proxy": "http://proxy.example:3128/",
503+ "GIT_PROXY_COMMAND": "/usr/local/bin/snap-git-proxy",
504+ }
505 self.assertThat(build_snap.backend.run.calls, MatchesListwise([
506- RanBuildCommand(env + "git clone lp:foo test-snap"),
507- RanBuildCommand(
508- env + "git -C test-snap submodule update --init --recursive"),
509- RanBuildCommand(
510- "env LANG=C.UTF-8 SHELL=/bin/sh "
511- "git -C test-snap rev-parse HEAD",
512+ RanBuildCommand(["git", "clone", "lp:foo", "test-snap"], **env),
513+ RanBuildCommand(
514+ ["git", "-C", "test-snap",
515+ "submodule", "update", "--init", "--recursive"], **env),
516+ RanBuildCommand(
517+ ["git", "-C", "test-snap", "rev-parse", "HEAD"],
518 get_output=True),
519 ]))
520 status_path = os.path.join(build_snap.backend.build_path, "status")
521@@ -252,11 +253,13 @@
522 ]
523 build_snap = parse_args(args=args).operation
524 build_snap.pull()
525- env = (
526- "env LANG=C.UTF-8 SHELL=/bin/sh "
527- "SNAPCRAFT_LOCAL_SOURCES=1 SNAPCRAFT_SETUP_CORE=1 ")
528+ env = {
529+ "SNAPCRAFT_LOCAL_SOURCES": "1",
530+ "SNAPCRAFT_SETUP_CORE": "1",
531+ }
532 self.assertThat(build_snap.backend.run.calls, MatchesListwise([
533- RanBuildCommand(env + "snapcraft pull", path="/build/test-snap"),
534+ RanBuildCommand(
535+ ["snapcraft", "pull"], cwd="/build/test-snap", **env),
536 ]))
537
538 def test_pull_proxy(self):
539@@ -268,14 +271,16 @@
540 ]
541 build_snap = parse_args(args=args).operation
542 build_snap.pull()
543- env = (
544- "env LANG=C.UTF-8 SHELL=/bin/sh "
545- "SNAPCRAFT_LOCAL_SOURCES=1 SNAPCRAFT_SETUP_CORE=1 "
546- "http_proxy=http://proxy.example:3128/ "
547- "https_proxy=http://proxy.example:3128/ "
548- "GIT_PROXY_COMMAND=/usr/local/bin/snap-git-proxy ")
549+ env = {
550+ "SNAPCRAFT_LOCAL_SOURCES": "1",
551+ "SNAPCRAFT_SETUP_CORE": "1",
552+ "http_proxy": "http://proxy.example:3128/",
553+ "https_proxy": "http://proxy.example:3128/",
554+ "GIT_PROXY_COMMAND": "/usr/local/bin/snap-git-proxy",
555+ }
556 self.assertThat(build_snap.backend.run.calls, MatchesListwise([
557- RanBuildCommand(env + "snapcraft pull", path="/build/test-snap"),
558+ RanBuildCommand(
559+ ["snapcraft", "pull"], cwd="/build/test-snap", **env),
560 ]))
561
562 def test_build(self):
563@@ -286,9 +291,8 @@
564 ]
565 build_snap = parse_args(args=args).operation
566 build_snap.build()
567- env = "env LANG=C.UTF-8 SHELL=/bin/sh "
568 self.assertThat(build_snap.backend.run.calls, MatchesListwise([
569- RanBuildCommand(env + "snapcraft", path="/build/test-snap"),
570+ RanBuildCommand(["snapcraft"], cwd="/build/test-snap"),
571 ]))
572
573 def test_build_proxy(self):
574@@ -300,13 +304,13 @@
575 ]
576 build_snap = parse_args(args=args).operation
577 build_snap.build()
578- env = (
579- "env LANG=C.UTF-8 SHELL=/bin/sh "
580- "http_proxy=http://proxy.example:3128/ "
581- "https_proxy=http://proxy.example:3128/ "
582- "GIT_PROXY_COMMAND=/usr/local/bin/snap-git-proxy ")
583+ env = {
584+ "http_proxy": "http://proxy.example:3128/",
585+ "https_proxy": "http://proxy.example:3128/",
586+ "GIT_PROXY_COMMAND": "/usr/local/bin/snap-git-proxy",
587+ }
588 self.assertThat(build_snap.backend.run.calls, MatchesListwise([
589- RanBuildCommand(env + "snapcraft", path="/build/test-snap"),
590+ RanBuildCommand(["snapcraft"], cwd="/build/test-snap", **env),
591 ]))
592
593 # XXX cjwatson 2017-08-07: Test revoke_token. It may be easiest to
594@@ -325,14 +329,11 @@
595 self.assertThat(build_snap.backend.run.calls, MatchesAll(
596 AnyMatch(RanAptGet("install", "snapcraft", "bzr")),
597 AnyMatch(RanBuildCommand(
598- "env LANG=C.UTF-8 SHELL=/bin/sh bzr branch lp:foo test-snap")),
599- AnyMatch(RanBuildCommand(
600- "env LANG=C.UTF-8 SHELL=/bin/sh "
601- "SNAPCRAFT_LOCAL_SOURCES=1 SNAPCRAFT_SETUP_CORE=1 "
602- "snapcraft pull", path="/build/test-snap")),
603- AnyMatch(RanBuildCommand(
604- "env LANG=C.UTF-8 SHELL=/bin/sh snapcraft",
605- path="/build/test-snap")),
606+ ["bzr", "branch", "lp:foo", "test-snap"])),
607+ AnyMatch(RanBuildCommand(
608+ ["snapcraft", "pull"], cwd="/build/test-snap",
609+ SNAPCRAFT_LOCAL_SOURCES="1", SNAPCRAFT_SETUP_CORE="1")),
610+ AnyMatch(RanBuildCommand(["snapcraft"], cwd="/build/test-snap")),
611 ))
612
613 def test_run_install_fails(self):
614@@ -356,10 +357,8 @@
615 class FailRepo(FakeMethod):
616 def __call__(self, run_args, *args, **kwargs):
617 super(FailRepo, self).__call__(run_args, *args, **kwargs)
618- if run_args[0] == "/bin/sh":
619- command = run_args[2]
620- if "bzr branch" in command:
621- raise subprocess.CalledProcessError(1, run_args)
622+ if run_args[:2] == ["bzr", "branch"]:
623+ raise subprocess.CalledProcessError(1, run_args)
624
625 self.useFixture(FakeLogger())
626 args = [
627@@ -375,12 +374,10 @@
628 class FailPull(FakeMethod):
629 def __call__(self, run_args, *args, **kwargs):
630 super(FailPull, self).__call__(run_args, *args, **kwargs)
631- if run_args[0] == "/bin/sh":
632- command = run_args[2]
633- if "bzr revno" in command:
634- return "42\n"
635- elif "snapcraft pull" in command:
636- raise subprocess.CalledProcessError(1, run_args)
637+ if run_args[:2] == ["bzr", "revno"]:
638+ return "42\n"
639+ elif run_args[:2] == ["snapcraft", "pull"]:
640+ raise subprocess.CalledProcessError(1, run_args)
641
642 self.useFixture(FakeLogger())
643 args = [
644@@ -397,12 +394,10 @@
645 class FailBuild(FakeMethod):
646 def __call__(self, run_args, *args, **kwargs):
647 super(FailBuild, self).__call__(run_args, *args, **kwargs)
648- if run_args[0] == "/bin/sh":
649- command = run_args[2]
650- if "bzr revno" in command:
651- return "42\n"
652- elif command.endswith(" snapcraft"):
653- raise subprocess.CalledProcessError(1, run_args)
654+ if run_args[:2] == ["bzr", "revno"]:
655+ return "42\n"
656+ elif run_args == ["snapcraft"]:
657+ raise subprocess.CalledProcessError(1, run_args)
658
659 self.useFixture(FakeLogger())
660 args = [
661
662=== modified file 'lpbuildd/tests/fakeslave.py'
663--- lpbuildd/tests/fakeslave.py 2017-09-08 15:57:18 +0000
664+++ lpbuildd/tests/fakeslave.py 2017-11-10 20:56:18 +0000
665@@ -202,7 +202,7 @@
666 class UncontainedBackend(Backend):
667 """A partial backend implementation with no containment."""
668
669- def run(self, args, env=None, input_text=None, get_output=False,
670+ def run(self, args, cwd=None, env=None, input_text=None, get_output=False,
671 echo=False, **kwargs):
672 """See `Backend`."""
673 if env:
674@@ -212,11 +212,12 @@
675 if self.arch is not None:
676 args = set_personality(args, self.arch, series=self.series)
677 if input_text is None and not get_output:
678- subprocess.check_call(args, **kwargs)
679+ subprocess.check_call(args, cwd=cwd, **kwargs)
680 else:
681 if get_output:
682 kwargs["stdout"] = subprocess.PIPE
683- proc = subprocess.Popen(args, stdin=subprocess.PIPE, **kwargs)
684+ proc = subprocess.Popen(
685+ args, stdin=subprocess.PIPE, cwd=cwd, **kwargs)
686 output, _ = proc.communicate(input_text)
687 if proc.returncode:
688 raise subprocess.CalledProcessError(proc.returncode, args)

Subscribers

People subscribed via source and target branches

to all changes: