Merge lp:~cjwatson/launchpad/buildmaster-getFile-rename into lp:launchpad

Proposed by Colin Watson
Status: Merged
Merged at revision: 18543
Proposed branch: lp:~cjwatson/launchpad/buildmaster-getFile-rename
Merge into: lp:launchpad
Diff against target: 32 lines (+7/-1)
1 file modified
lib/lp/buildmaster/interactor.py (+7/-1)
To merge this branch: bzr merge lp:~cjwatson/launchpad/buildmaster-getFile-rename
Reviewer Review Type Date Requested Status
William Grant code Approve
Review via email: mp+336709@code.launchpad.net

Commit message

Write files fetched from builders to a temporary name, and only rename them into place on success.

Description of the change

This is a slightly speculative attempt to fix odd checksum mismatches on files fetched from builders for gcc-7-cross-ports builds: my theory is that a Deferred might be left over from a previous retry iteration and try to write to the same file. At any rate, it should be pretty safe to follow the rename-into-place protocol here.

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
=== modified file 'lib/lp/buildmaster/interactor.py'
--- lib/lp/buildmaster/interactor.py 2017-04-27 15:54:54 +0000
+++ lib/lp/buildmaster/interactor.py 2018-01-26 16:33:33 +0000
@@ -10,6 +10,8 @@
1010
11from collections import namedtuple11from collections import namedtuple
12import logging12import logging
13import os.path
14import tempfile
13from urlparse import urlparse15from urlparse import urlparse
1416
15import transaction17import transaction
@@ -67,7 +69,9 @@
6769
68 def dataReceived(self, data):70 def dataReceived(self, data):
69 if self.file is None:71 if self.file is None:
70 self.file = open(self.filename, "wb")72 self.file = tempfile.NamedTemporaryFile(
73 mode="wb", prefix=os.path.basename(self.filename) + "_",
74 dir=os.path.dirname(self.filename), delete=False)
71 try:75 try:
72 self.file.write(data)76 self.file.write(data)
73 except IOError:77 except IOError:
@@ -82,6 +86,8 @@
82 try:86 try:
83 if self.file is not None:87 if self.file is not None:
84 self.file.close()88 self.file.close()
89 if self.filename is not None and reason.check(ResponseDone):
90 os.rename(self.file.name, self.filename)
85 except IOError:91 except IOError:
86 self.finished.errback()92 self.finished.errback()
87 else:93 else: