Skip to content

Commit 679f222

Browse files
authored
Merge pull request #635 from jkloetzke/fix-delete-extract
Fix extraction of archives if workspace was deleted
2 parents 127832d + 5175417 commit 679f222

File tree

15 files changed

+74
-43
lines changed

15 files changed

+74
-43
lines changed

pym/bob/archive.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
import concurrent.futures
3131
import concurrent.futures.process
3232
import gzip
33-
import http.client
3433
import io
3534
import os
3635
import os.path

pym/bob/builder.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -718,7 +718,7 @@ def linkTo(dest, linkName):
718718
"{:02}-{}".format(i, a.getPackage().getName())))
719719
i += 1
720720

721-
async def _runShell(self, step, scriptName, logger, cleanWorkspace=None,
721+
async def _runShell(self, step, scriptName, logger, workspaceCreated, cleanWorkspace=None,
722722
mode=InvocationMode.CALL):
723723
workspacePath = step.getWorkspacePath()
724724
if not os.path.isdir(workspacePath): os.makedirs(workspacePath)
@@ -771,7 +771,7 @@ async def _runShell(self, step, scriptName, logger, cleanWorkspace=None,
771771
executor=self.__executor)
772772
if step.jobServer() and self.__jobServer:
773773
invoker.setMakeParameters(self.__jobServer.getMakeFd(), self.__jobs)
774-
ret = await invoker.executeStep(mode, cleanWorkspace)
774+
ret = await invoker.executeStep(mode, workspaceCreated, cleanWorkspace)
775775
if not self.__bufferedStdIO: ttyReinit() # work around MSYS2 messing up the console
776776
if ret == -int(signal.SIGINT):
777777
raise BuildError("User aborted while running {}".format(absRunFile),
@@ -1110,7 +1110,7 @@ async def _cookCheckoutStep(self, checkoutStep, depth):
11101110
if checkoutBuildOnlyStateCompatible(checkoutState, oldCheckoutState):
11111111
with stepExec(checkoutStep, "UPDATE",
11121112
"{} {}".format(prettySrcPath, overridesString)) as a:
1113-
await self._runShell(checkoutStep, "checkout", a, mode=InvocationMode.UPDATE)
1113+
await self._runShell(checkoutStep, "checkout", a, created, mode=InvocationMode.UPDATE)
11141114
newCheckoutState = oldCheckoutState.copy()
11151115
newCheckoutState[CHECKOUT_STATE_BUILD_ONLY] = checkoutState[CHECKOUT_STATE_BUILD_ONLY]
11161116
BobState().setDirectoryState(prettySrcPath, newCheckoutState)
@@ -1235,7 +1235,7 @@ async def _cookCheckoutStep(self, checkoutStep, depth):
12351235

12361236
with stepExec(checkoutStep, "CHECKOUT",
12371237
"{} ({}) {}".format(prettySrcPath, checkoutReason, overridesString)) as a:
1238-
await self._runShell(checkoutStep, "checkout", a)
1238+
await self._runShell(checkoutStep, "checkout", a, created)
12391239
self.__statistic.checkouts += 1
12401240
checkoutExecuted = True
12411241
currentResultHash.invalidate() # force recalculation
@@ -1302,6 +1302,7 @@ async def _cookBuildStep(self, buildStep, depth, buildBuildId):
13021302
stepMessage(buildStep, "PRUNE", "{} (recipe changed)".format(prettyBuildPath),
13031303
WARNING)
13041304
emptyDirectory(prettyBuildPath)
1305+
created = True
13051306
# invalidate build step
13061307
BobState().resetWorkspaceState(prettyBuildPath, buildDigest)
13071308

@@ -1327,7 +1328,7 @@ async def _cookBuildStep(self, buildStep, depth, buildBuildId):
13271328
# build it
13281329
with stepExec(buildStep, "BUILD", prettyBuildPath, INFO) as buildAction:
13291330
visibleAction = fullAction if fullAction.visible else buildAction
1330-
await self._runShell(buildStep, "build", visibleAction, self.__cleanBuild)
1331+
await self._runShell(buildStep, "build", visibleAction, created, self.__cleanBuild)
13311332
buildHash = hashWorkspace(buildStep)
13321333
await self._generateAudit(buildStep, depth, buildHash, buildBuildId)
13331334
BobState().setResultHash(prettyBuildPath, buildHash)
@@ -1577,7 +1578,7 @@ async def _cookPackageStep(self, packageStep, depth, packageBuildId):
15771578
BobState().setResultHash(prettyPackagePath, datetime.datetime.now())
15781579
with stepExec(packageStep, "PACKAGE", prettyPackagePath, INFO) as packageAction:
15791580
visibleAction = fullAction if fullAction.visible else packageAction
1580-
await self._runShell(packageStep, "package", visibleAction)
1581+
await self._runShell(packageStep, "package", visibleAction, True)
15811582
packageHash = hashWorkspace(packageStep)
15821583
packageDigest = await self.__getIncrementalVariantId(packageStep)
15831584
workspaceChanged = True

pym/bob/cmds/invoke.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,14 +50,14 @@ def doInvoke(argv, bobRoot):
5050
invoker = Invoker(spec, args.preserve_env, True, True, True, False,
5151
False, executor=executor)
5252
ret = loop.run_until_complete(invoker.executeStep(InvocationMode.SHELL,
53-
args.clean, args.keep_sandbox))
53+
False, args.clean, args.keep_sandbox))
5454
elif args.mode in ('run', 'update'):
5555
invoker = Invoker(spec, args.preserve_env, args.no_logfiles,
5656
verbosity >= 2, verbosity >= 1, verbosity >= 3, False,
5757
executor=executor)
5858
ret = loop.run_until_complete(invoker.executeStep(
5959
InvocationMode.CALL if args.mode == 'run' else InvocationMode.UPDATE,
60-
args.clean, args.keep_sandbox))
60+
False, args.clean, args.keep_sandbox))
6161
elif args.mode == 'fingerprint':
6262
invoker = Invoker(spec, args.preserve_env, True, True, True,
6363
verbosity >= 3, False, executor=executor)

pym/bob/invoker.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ def __getSlimSandboxCmds(self, tmpDir):
334334

335335
return cmdArgs
336336

337-
async def executeStep(self, mode, clean=False, keepSandbox=False):
337+
async def executeStep(self, mode, workspaceCreated, clean=False, keepSandbox=False):
338338
# make permissions predictable
339339
os.umask(0o022)
340340

@@ -352,8 +352,10 @@ async def executeStep(self, mode, clean=False, keepSandbox=False):
352352
clean = self.__spec.clean if self.__spec.clean is not None else clean
353353
if not os.path.isdir(self.__spec.workspaceWorkspacePath):
354354
os.makedirs(self.__spec.workspaceWorkspacePath, exist_ok=True)
355+
workspaceCreated = True
355356
elif clean and mode != InvocationMode.SHELL:
356357
emptyDirectory(self.__spec.workspaceWorkspacePath)
358+
workspaceCreated = True
357359

358360
if len(self.__makeFds) == 2:
359361
makeFlags = self.__spec.env.get("MAKEFLAGS")
@@ -426,7 +428,7 @@ async def executeStep(self, mode, clean=False, keepSandbox=False):
426428
if mode == InvocationMode.UPDATE and not scm.isLocal():
427429
continue # Skip non-local SCMs on update-only
428430
try:
429-
await scm.invoke(self)
431+
await scm.invoke(self, workspaceCreated)
430432
except CmdFailedError as e:
431433
self.error(scm.getSource(), "failed")
432434
self.error(e.what)

pym/bob/layers.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ async def __checkoutTask(self, verbose, attic):
155155
os.makedirs(self.__layerDir)
156156
self.__created = True
157157

158-
await self.__scm.invoke(invoker)
158+
await self.__scm.invoke(invoker, self.__created)
159159
log("CHECKOUT: Layer " +
160160
"'{}' .. ok".format(self.getName()), EXECUTED, NORMAL)
161161
BobState().setLayerState(self.__layerDir, newState)

pym/bob/scm/cvs.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ def getProperties(self, isJenkins, pretty=False):
6161

6262
return ret
6363

64-
async def invoke(self, invoker):
64+
async def invoke(self, invoker, workspaceCreated):
6565
# If given a ":ssh:" cvsroot, translate that to CVS_RSH using ssh, and ":ext:"
6666
# (some versions of CVS do that internally)
6767
m = re.match('^:ssh:(.*)', self.__cvsroot)

pym/bob/scm/git.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ def _getGitConfigOptions(self):
206206
config += [ "-c", "protocol.file.allow=always" ]
207207
return config
208208

209-
async def invoke(self, invoker, switch=False):
209+
async def invoke(self, invoker, workspaceCreated, switch=False):
210210
alternatesFile = invoker.joinPath(self.__dir, ".git/objects/info/alternates")
211211

212212
# make sure the git directory exists
@@ -709,7 +709,7 @@ async def switch(self, invoker, oldScm):
709709

710710
# Try to checkout new state in old workspace. If something fails the
711711
# old attic logic will take over.
712-
await self.invoke(invoker, True)
712+
await self.invoke(invoker, False, True)
713713
return True
714714

715715
def asDigestScript(self):

pym/bob/scm/imp.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ def getProperties(self, isJenkins, pretty=False):
166166

167167
return ret
168168

169-
async def invoke(self, invoker):
169+
async def invoke(self, invoker, workspaceCreated):
170170
dest = invoker.joinPath(self.__dir)
171171
os.makedirs(dest, exist_ok=True)
172172
if self.__prune: emptyDirectory(dest)

pym/bob/scm/svn.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ def getProperties(self, isJenkins, pretty=False):
7272

7373
return ret
7474

75-
async def invoke(self, invoker):
75+
async def invoke(self, invoker, workspaceCreated):
7676
options = [ "--non-interactive" ]
7777
if not self.__sslVerify:
7878
options += [ "--trust-server-cert-failures=unknown-ca,cn-mismatch,expired,not-yet-valid,other" ]

pym/bob/scm/url.py

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -168,11 +168,11 @@ def __init__(self, dir, file, strip, separateDownload):
168168
self.strip = strip
169169
self.separateDownload = separateDownload
170170

171-
async def _extract(self, cmds, invoker, stdout=None):
171+
async def _extract(self, cmds, invoker, dirCreated, stdout=None):
172172
destination = self.getCompressedFilePath(invoker)
173173
(destDir, destFile) = os.path.split(destination)
174174
canary = os.path.join(destDir, "."+destFile+".extracted")
175-
if isYounger(destination, canary):
175+
if dirCreated or isYounger(destination, canary):
176176
for cmd in cmds:
177177
if shutil.which(cmd[0]) is None: continue
178178
await invoker.checkCommand(cmd, cwd=self.dir, stdout=stdout)
@@ -189,7 +189,7 @@ def getCompressedFilePath(self, invoker):
189189
return os.path.abspath(invoker.joinPath(downloadFolder, self.dir, self.file)) \
190190

191191
@abstractmethod
192-
async def extract(self, invoker, destination, cwd):
192+
async def extract(self, invoker, dirCreated):
193193
return False
194194

195195
# Use the Python tar/zip extraction only on Windows. They are slower and in
@@ -198,7 +198,7 @@ async def extract(self, invoker, destination, cwd):
198198
class TarExtractor(Extractor):
199199
SUPPORT_STRIP = True
200200

201-
async def extract(self, invoker):
201+
async def extract(self, invoker, dirCreated):
202202
cmds = []
203203
compressedFilePath = self.getCompressedFilePath(invoker)
204204
if isWin32 and self.strip == 0:
@@ -210,25 +210,25 @@ async def extract(self, invoker):
210210
cmd.append("--strip-components={}".format(self.strip))
211211
cmds.append(cmd)
212212

213-
await self._extract(cmds, invoker)
213+
await self._extract(cmds, invoker, dirCreated)
214214

215215

216216
class ZipExtractor(Extractor):
217217

218-
async def extract(self, invoker):
218+
async def extract(self, invoker, dirCreated):
219219
cmds = []
220220
compressedFilePath = self.getCompressedFilePath(invoker)
221221
if isWin32:
222222
cmds.append(["python", "-m", "zipfile",
223223
"-e", compressedFilePath, "."])
224224

225225
cmds.append(["unzip", "-o", compressedFilePath])
226-
await self._extract(cmds, invoker)
226+
await self._extract(cmds, invoker, dirCreated)
227227

228228

229229
class SingleFileExtractor(Extractor):
230230

231-
async def extract(self, invoker):
231+
async def extract(self, invoker, dirCreated):
232232
# The gunzip and unxz tools extracts the file at the location of the
233233
# input file. In case the separateDownload policy is active, the
234234
# destination might be in a separete folder.
@@ -248,7 +248,7 @@ async def extract(self, invoker):
248248

249249
with open(dst, 'wb') as f:
250250
cmd = [self.CMD, "-c", src]
251-
await self._extract([cmd], invoker, f)
251+
await self._extract([cmd], invoker, dirCreated, f)
252252

253253
shutil.copystat(src, dst)
254254

@@ -281,9 +281,9 @@ class XZExtractor(SingleFileExtractor):
281281

282282
class SevenZipExtractor(Extractor):
283283

284-
async def extract(self, invoker):
284+
async def extract(self, invoker, dirCreated):
285285
cmds = [["7z", "x", "-y", self.getCompressedFilePath(invoker)]]
286-
await self._extract(cmds, invoker)
286+
await self._extract(cmds, invoker, dirCreated)
287287

288288

289289
class UrlScm(Scm):
@@ -685,8 +685,10 @@ async def switch(self, invoker, oldScm):
685685
# does not match.
686686
return True
687687

688-
async def invoke(self, invoker):
689-
os.makedirs(invoker.joinPath(self.__dir), exist_ok=True)
688+
async def invoke(self, invoker, workspaceCreated):
689+
if not os.path.isdir(invoker.joinPath(self.__dir)):
690+
os.makedirs(invoker.joinPath(self.__dir), exist_ok=True)
691+
workspaceCreated = True
690692
workspaceFile = os.path.join(self.__dir, self.__fn)
691693
extractor = self.__getExtractor()
692694

@@ -747,7 +749,7 @@ async def invoke(self, invoker):
747749

748750
# Run optional extractors
749751
if extractor is not None:
750-
await extractor.extract(invoker)
752+
await extractor.extract(invoker, workspaceCreated)
751753

752754
def asDigestScript(self):
753755
"""Return forward compatible stable string describing this url.

0 commit comments

Comments
 (0)