def removeSingleDir(self, dirname): # TODO: remove the old tree in the background self.dir = os.path.join(self.builder.basedir, dirname) if runtime.platformType != "posix": # if we're running on w32, use rmtree instead. It will block, # but hopefully it won't take too long. utils.rmdirRecursive(self.dir) d = defer.succeed(0) else: d = self._clobber(None) return d
def _purgeAndUpdate2(self, res): for filename in self.getUnversionedFiles(self.command.stdout, self.keep_on_purge): filepath = os.path.join(self.builder.basedir, self.workdir, filename) self.sendStatus({'stdout': "%s\n" % filepath}) if os.path.isfile(filepath): os.chmod(filepath, 0700) os.remove(filepath) else: utils.rmdirRecursive(filepath) # Now safe to update. revision = self.args['revision'] or 'HEAD' return self._dovccmd('update', ['--revision', str(revision)], keepStdout=True)
def doClobber(self, dummy, dirname, chmodDone=False): # TODO: remove the old tree in the background ## workdir = os.path.join(self.builder.basedir, self.workdir) ## deaddir = self.workdir + ".deleting" ## if os.path.isdir(workdir): ## try: ## os.rename(workdir, deaddir) ## # might fail if deaddir already exists: previous deletion ## # hasn't finished yet ## # start the deletion in the background ## # TODO: there was a solaris/NetApp/NFS problem where a ## # process that was still running out of the directory we're ## # trying to delete could prevent the rm-rf from working. I ## # think it stalled the rm, but maybe it just died with ## # permission issues. Try to detect this. ## os.commands("rm -rf %s &" % deaddir) ## except: ## # fall back to sequential delete-then-checkout ## pass d = os.path.join(self.builder.basedir, dirname) if runtime.platformType != "posix": # if we're running on w32, use rmtree instead. It will block, # but hopefully it won't take too long. utils.rmdirRecursive(d) return defer.succeed(0) command = ["rm", "-rf", d] c = runprocess.RunProcess( self.builder, command, self.builder.basedir, sendRC=0, timeout=self.timeout, maxTime=self.maxTime, usePTY=False, ) self.command = c # sendRC=0 means the rm command will send stdout/stderr to the # master, but not the rc=0 when it finishes. That job is left to # _sendRC d = c.start() # The rm -rf may fail if there is a left-over subdir with chmod 000 # permissions. So if we get a failure, we attempt to chmod suitable # permissions and re-try the rm -rf. if chmodDone: d.addCallback(self._abandonOnFailure) else: d.addCallback(lambda rc: self.doClobberTryChmodIfFail(rc, dirname)) return d
def doClobber(self, dummy, dirname, chmodDone=False): # TODO: remove the old tree in the background ## workdir = os.path.join(self.builder.basedir, self.workdir) ## deaddir = self.workdir + ".deleting" ## if os.path.isdir(workdir): ## try: ## os.rename(workdir, deaddir) ## # might fail if deaddir already exists: previous deletion ## # hasn't finished yet ## # start the deletion in the background ## # TODO: there was a solaris/NetApp/NFS problem where a ## # process that was still running out of the directory we're ## # trying to delete could prevent the rm-rf from working. I ## # think it stalled the rm, but maybe it just died with ## # permission issues. Try to detect this. ## os.commands("rm -rf %s &" % deaddir) ## except: ## # fall back to sequential delete-then-checkout ## pass d = os.path.join(self.builder.basedir, dirname) if runtime.platformType != "posix": # if we're running on w32, use rmtree instead. It will block, # but hopefully it won't take too long. utils.rmdirRecursive(d) return defer.succeed(0) command = ["rm", "-rf", d] c = runprocess.RunProcess(self.builder, command, self.builder.basedir, sendRC=0, timeout=self.timeout, maxTime=self.maxTime, logEnviron=self.logEnviron, usePTY=False) self.command = c # sendRC=0 means the rm command will send stdout/stderr to the # master, but not the rc=0 when it finishes. That job is left to # _sendRC d = c.start() # The rm -rf may fail if there is a left-over subdir with chmod 000 # permissions. So if we get a failure, we attempt to chmod suitable # permissions and re-try the rm -rf. if chmodDone: d.addCallback(self._abandonOnFailure) else: d.addCallback(lambda rc: self.doClobberTryChmodIfFail(rc, dirname)) return d
def _purgeAndUpdate2(self, res): """Delete everything that shown up on status.""" result_xml = parseString(self.command.stdout) for entry in result_xml.getElementsByTagName("entry"): filename = entry.getAttribute("path") if filename in self.keep_on_purge: continue filepath = os.path.join(self.builder.basedir, self.workdir, filename) self.sendStatus({"stdout": "%s\n" % filepath}) if os.path.isfile(filepath): os.chmod(filepath, 0700) os.remove(filepath) else: utils.rmdirRecursive(filepath) # Now safe to update. revision = self.args["revision"] or "HEAD" return self._dovccmd("update", ["--revision", str(revision)], keepStdout=True)
def test_rmdirRecursive_symlink(self): # this was intended as a regression test for #792, but doesn't seem # to trigger it. It can't hurt to check it, all the same. if runtime.platformType == 'win32': raise unittest.SkipTest("no symlinks on this platform") os.mkdir("noperms") open("noperms/x", "w") os.chmod("noperms/x", 0) try: os.symlink("../noperms", os.path.join(self.target, "link")) utils.rmdirRecursive(self.target) # that shouldn't delete the target of the symlink self.assertTrue(os.path.exists("noperms")) finally: # even Twisted can't clean this up very well, so try hard to # clean it up ourselves.. os.chmod("noperms/x", 0o777) os.unlink("noperms/x") os.rmdir("noperms") self.assertFalse(os.path.exists(self.target))
def test_rmdirRecursive_symlink(self): # this was intended as a regression test for #792, but doesn't seem # to trigger it. It can't hurt to check it, all the same. if runtime.platformType == "win32": raise unittest.SkipTest("no symlinks on this platform") os.mkdir("noperms") open("noperms/x", "w") os.chmod("noperms/x", 0) try: os.symlink("../noperms", os.path.join(self.target, "link")) utils.rmdirRecursive(self.target) # that shouldn't delete the target of the symlink self.assertTrue(os.path.exists("noperms")) finally: # even Twisted can't clean this up very well, so try hard to # clean it up ourselves.. os.chmod("noperms/x", 0777) os.unlink("noperms/x") os.rmdir("noperms") self.assertFalse(os.path.exists(self.target))
def start(self): args = self.args # args['dir'] is relative to Builder directory, and is required. assert args['dir'] is not None dirname = args['dir'] self.timeout = args.get('timeout', 120) self.maxTime = args.get('maxTime', None) # TODO: remove the old tree in the background self.dir = os.path.join(self.builder.basedir, dirname) if runtime.platformType != "posix": # if we're running on w32, use rmtree instead. It will block, # but hopefully it won't take too long. utils.rmdirRecursive(self.dir) d = defer.succeed(0) else: d = self._clobber(None) # always add the RC, regardless of platform d.addCallbacks(self._sendRC, self._checkAbandoned) return d
def test_rmdirRecursive_easy(self): utils.rmdirRecursive(self.target) self.assertFalse(os.path.exists(self.target))