From 6d64fbeb5f77255c306b03f26c1160ff0a136968 Mon Sep 17 00:00:00 2001 From: David Rose Date: Tue, 2 Mar 2010 02:17:47 +0000 Subject: [PATCH] shutil.rmtree() not reliable on Windows --- direct/src/p3d/AppRunner.py | 21 ++++++++++++++++++--- direct/src/p3d/HostInfo.py | 7 +++---- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/direct/src/p3d/AppRunner.py b/direct/src/p3d/AppRunner.py index e49acddc0c..7ae298a68c 100644 --- a/direct/src/p3d/AppRunner.py +++ b/direct/src/p3d/AppRunner.py @@ -12,7 +12,6 @@ runp3d.py for a command-line tool to invoke this module. import sys import os import types -import shutil import __builtin__ if 'VFSImporter' in sys.modules: @@ -408,7 +407,7 @@ class AppRunner(DirectObject): removed all of the packages). """ self.notify.info("Deleting host %s: %s" % (host.hostUrl, host.hostDir)) - shutil.rmtree(host.hostDir.toOsSpecific(), True) + self.rmtree(host.hostDir) self.sendRequest('forget_package', host.hostUrl, '', '') @@ -561,7 +560,7 @@ class AppRunner(DirectObject): else: # If it's an unknown package, just delete it directly. print "Deleting unknown package %s" % (packageData.pathname) - shutil.rmtree(packageData.pathname.toOsSpecific(), True) + self.rmtree(packageData.pathname()) packages = self.deletePackages(packages) if packages: @@ -606,6 +605,22 @@ class AppRunner(DirectObject): else: raise + def rmtree(self, filename): + """ This is like shutil.rmtree(), but it can remove read-only + files on Windows. It receives a Filename, the root directory + to delete. """ + if filename.isDirectory(): + for child in os.listdir(filename.toOsSpecific()): + self.rmtree(Filename(filename, child)) + try: + os.chmod(filename.toOsSpecific(), 777) + os.rmdir(filename.toOsSpecific()) + except OSError: + print "could not remove directory %s" % (filename) + else: + if not filename.unlink(): + print "could not delete %s" % (filename) + def setSessionId(self, sessionId): """ This message should come in at startup. """ self.sessionId = sessionId diff --git a/direct/src/p3d/HostInfo.py b/direct/src/p3d/HostInfo.py index cd61c6c047..134bcfb35c 100644 --- a/direct/src/p3d/HostInfo.py +++ b/direct/src/p3d/HostInfo.py @@ -4,7 +4,6 @@ from direct.p3d.PackageInfo import PackageInfo from direct.p3d.FileSpec import FileSpec from direct.directnotify.DirectNotifyGlobal import directNotify import time -import shutil class HostInfo: """ This class represents a particular download host serving up @@ -482,10 +481,10 @@ class HostInfo: """ Called by deletePackage(), this actually removes the files for the indicated package. """ - self.notify.info("Deleting package %s: %s" % (package.packageName, package.getPackageDir())) - shutil.rmtree(package.getPackageDir().toOsSpecific(), True) - if self.appRunner: + self.notify.info("Deleting package %s: %s" % (package.packageName, package.getPackageDir())) + self.appRunner.rmtree(package.getPackageDir()) + self.appRunner.sendRequest('forget_package', self.hostUrl, package.packageName, package.packageVersion or '') def __determineHostDir(self, hostDirBasename, hostUrl):