Selaa lähdekoodia

implicit dll dependencies

David Rose 16 vuotta sitten
vanhempi
sitoutus
b7a53cf63b
1 muutettua tiedostoa jossa 340 lisäystä ja 97 poistoa
  1. 340 97
      direct/src/showutil/Packager.py

+ 340 - 97
direct/src/showutil/Packager.py

@@ -29,13 +29,82 @@ class Packager:
     notify = directNotify.newCategory("Packager")
     notify = directNotify.newCategory("Packager")
 
 
     class PackFile:
     class PackFile:
-        def __init__(self, filename, newName = None, deleteTemp = False,
-                     extract = None):
+        def __init__(self, package, filename,
+                     newName = None, deleteTemp = False,
+                     compress = None, extract = None, executable = None):
             assert isinstance(filename, Filename)
             assert isinstance(filename, Filename)
-            self.filename = filename
+            self.filename = Filename(filename)
             self.newName = newName
             self.newName = newName
             self.deleteTemp = deleteTemp
             self.deleteTemp = deleteTemp
+            self.compress = compress
             self.extract = extract
             self.extract = extract
+            self.executable = executable
+
+            if not self.newName:
+                self.newName = self.filename.cStr()
+
+            packager = package.packager
+            ext = Filename(self.newName).getExtension()
+            if self.compress is None:
+                self.compress = (ext not in packager.uncompressibleExtensions)
+
+            if self.executable is None:
+                self.executable = (ext in packager.executableExtensions)
+
+            if self.extract is None:
+                self.extract = self.executable or (ext in packager.extractExtensions)
+            self.platformSpecific = self.executable or (ext in packager.platformSpecificExtensions)
+                
+
+            if self.executable:
+                # Look up the filename along the system PATH, if necessary.
+                self.filename.resolveFilename(packager.dllPath)
+
+            # Convert the filename to an unambiguous filename for
+            # searching.
+            self.filename.makeCanonical()
+
+        def isExcluded(self, package):
+            """ Returns true if this file should be excluded or
+            skipped, false otherwise. """
+
+            if self.newName in package.skipFilenames:
+                return True
+
+            basename = Filename(self.newName).getBasename()
+            if not package.packager.caseSensitive:
+                basename = basename.lower()
+            if basename in package.packager.excludeSystemFiles:
+                return True
+
+            for exclude in package.packager.excludeSystemGlobs:
+                if exclude.matches(basename):
+                    return True
+
+            for exclude in package.excludedFilenames:
+                if exclude.matches(self.filename):
+                    return True
+
+            return False
+                
+    class ExcludeFilename:
+        def __init__(self, filename, caseSensitive):
+            self.localOnly = (not filename.get_dirname())
+            if not self.localOnly:
+                filename = Filename(filename)
+                filename.makeCanonical()
+            self.glob = GlobPattern(filename.cStr())
+
+            if PandaSystem.getPlatform().startswith('win'):
+                self.glob.setCaseSensitive(False)
+            elif PandaSystem.getPlatform().startswith('osx'):
+                self.glob.setCaseSensitive(False)
+
+        def matches(self, filename):
+            if self.localOnly:
+                return self.glob.matches(filename.getBasename())
+            else:
+                return self.glob.matches(filename.cStr())
 
 
     class Package:
     class Package:
         def __init__(self, packageName, packager):
         def __init__(self, packageName, packager):
@@ -45,7 +114,6 @@ class Packager:
             self.platform = None
             self.platform = None
             self.p3dApplication = False
             self.p3dApplication = False
             self.displayName = None
             self.displayName = None
-            self.files = []
             self.compressionLevel = 0
             self.compressionLevel = 0
             self.importedMapsDir = 'imported_maps'
             self.importedMapsDir = 'imported_maps'
             self.mainModule = None
             self.mainModule = None
@@ -56,6 +124,16 @@ class Packager:
             self.skipFilenames = {}
             self.skipFilenames = {}
             self.skipModules = {}
             self.skipModules = {}
 
 
+            # This is a list of ExcludeFilename objects, representing
+            # the files that have been explicitly excluded.
+            self.excludedFilenames = []
+
+            # This is the list of files we will be adding, and a pair
+            # of cross references.
+            self.files = []
+            self.sourceFilenames = {}
+            self.targetFilenames = {}
+
             # This records the current list of modules we have added so
             # This records the current list of modules we have added so
             # far.
             # far.
             self.freezer = FreezeTool.Freezer()
             self.freezer = FreezeTool.Freezer()
@@ -86,15 +164,15 @@ class Packager:
             # First, add the explicit py files.  These get turned into
             # First, add the explicit py files.  These get turned into
             # Python modules.
             # Python modules.
             for file in self.files:
             for file in self.files:
-                if not file.newName:
-                    file.newName = file.filename
-                if file.newName in self.skipFilenames:
+                ext = file.filename.getExtension()
+                if ext != 'py':
+                    continue
+
+                if file.isExcluded(self):
                     # Skip this file.
                     # Skip this file.
                     continue
                     continue
 
 
-                ext = file.filename.getExtension()
-                if ext == 'py':
-                    self.addPyFile(file)
+                self.addPyFile(file)
 
 
             if not self.mainModule and self.p3dApplication:
             if not self.mainModule and self.p3dApplication:
                 message = 'No main_module specified for application %s' % (self.packageName)
                 message = 'No main_module specified for application %s' % (self.packageName)
@@ -121,35 +199,30 @@ class Packager:
             self.freezer.addToMultifile(self.multifile, self.compressionLevel)
             self.freezer.addToMultifile(self.multifile, self.compressionLevel)
             self.addExtensionModules()
             self.addExtensionModules()
 
 
-            # Build up a cross-reference of files we've already
-            # discovered.
-            self.sourceFilenames = {}
-            self.targetFilenames = {}
-            processFiles = []
-            for file in self.files:
-                if not file.newName:
-                    file.newName = file.filename
-                if file.newName in self.skipFilenames:
-                    # Skip this file.
-                    continue
-
-                # Convert the source filename to an unambiguous
-                # filename for searching.
-                filename = Filename(file.filename)
-                filename.makeCanonical()
-                
-                self.sourceFilenames[filename] = file
-                self.targetFilenames[file.newName] = file
-                processFiles.append(file)
+            # Now look for implicit shared-library dependencies.
+            if PandaSystem.getPlatform().startswith('win'):
+                self.__addImplicitDependenciesWindows()
+            elif PandaSystem.getPlatform().startswith('osx'):
+                self.__addImplicitDependenciesOSX()
+            else:
+                self.__addImplicitDependenciesPosix()
 
 
             # Now add all the real, non-Python files.  This will
             # Now add all the real, non-Python files.  This will
             # include the extension modules we just discovered above.
             # include the extension modules we just discovered above.
-            for file in processFiles:
+
+            # We walk through the list as we modify it.  That's OK,
+            # because we may add new files that we want to process.
+            for file in self.files:
                 ext = file.filename.getExtension()
                 ext = file.filename.getExtension()
                 if ext == 'py':
                 if ext == 'py':
                     # Already handled, above.
                     # Already handled, above.
-                    pass
-                elif not self.dryRun:
+                    continue
+
+                if file.isExcluded(self):
+                    # Skip this file.
+                    continue
+                
+                if not self.dryRun:
                     if ext == 'pz':
                     if ext == 'pz':
                         # Strip off an implicit .pz extension.
                         # Strip off an implicit .pz extension.
                         filename = Filename(file.filename)
                         filename = Filename(file.filename)
@@ -166,8 +239,6 @@ class Packager:
                         self.addEggFile(file)
                         self.addEggFile(file)
                     elif ext == 'bam':
                     elif ext == 'bam':
                         self.addBamFile(file)
                         self.addBamFile(file)
-                    elif ext in self.packager.imageExtensions:
-                        self.addTexture(file)
                     else:
                     else:
                         # Any other file.
                         # Any other file.
                         self.addComponent(file)
                         self.addComponent(file)
@@ -230,6 +301,118 @@ class Packager:
                 if file.deleteTemp:
                 if file.deleteTemp:
                     file.filename.unlink()
                     file.filename.unlink()
 
 
+        def addFile(self, *args, **kw):
+            """ Adds the named file to the package. """
+
+            file = Packager.PackFile(self, *args, **kw)
+            if file.filename in self.sourceFilenames:
+                # Don't bother, it's already here.
+                return
+
+            if not file.filename.exists():
+                self.packager.notify.warning("No such file: %s" % (file.filename))
+                return
+            
+            self.files.append(file)
+            self.sourceFilenames[file.filename] = file
+            self.targetFilenames[file.newName] = file
+
+        def excludeFile(self, filename):
+            """ Excludes the named file (or glob pattern) from the
+            package. """
+            xfile = Packager.ExcludeFilename(filename, self.packager.caseSensitive)
+            self.excludedFilenames.append(xfile)
+
+        def __addImplicitDependenciesWindows(self):
+            """ Walks through the list of files, looking for dll's and
+            exe's that might include implicit dependencies on other
+            dll's.  Tries to determine those dependencies, and adds
+            them back into the filelist. """
+
+            # We walk through the list as we modify it.  That's OK,
+            # because we want to follow the transitive closure of
+            # dependencies anyway.
+            for file in self.files:
+                if not file.executable:
+                    continue
+                
+                if file.isExcluded(self):
+                    # Skip this file.
+                    continue
+
+                tempFile = Filename.temporary('', 'p3d_')
+                command = 'dumpbin /dependents "%s" >"%s"' % (
+                    file.filename.toOsSpecific(),
+                    tempFile.toOsSpecific())
+                try:
+                    os.system(command)
+                except:
+                    pass
+                filenames = None
+
+                if tempFile.exists():
+                    filenames = self.__parseDependenciesWindows(tempFile)
+                if filenames is None:
+                    print "Unable to determine dependencies from %s" % (file.filename)
+                    continue
+
+                for filename in filenames:
+                    filename = Filename.fromOsSpecific(filename)
+                    self.addFile(filename, executable = True)
+                        
+                    
+        def __parseDependenciesWindows(self, tempFile):
+            """ Reads the indicated temporary file, the output from
+            dumpbin /dependents, to determine the list of dll's this
+            executable file depends on. """
+
+            lines = open(tempFile.toOsSpecific(), 'rU').readlines()
+            li = 0
+            while li < len(lines):
+                line = lines[li]
+                li += 1
+                if line.find(' has the following dependencies') != -1:
+                    break
+
+            if li < len(lines):
+                line = lines[li]
+                if line.strip() == '':
+                    # Skip a blank line.
+                    li += 1
+
+            # Now we're finding filenames, until the next blank line.
+            filenames = []
+            while li < len(lines):
+                line = lines[li]
+                li += 1
+                line = line.strip()
+                if line == '':
+                    # We're done.
+                    return filenames
+                filenames.append(line)
+
+            # Hmm, we ran out of data.  Oh well.
+            if not filenames:
+                # Some parse error.
+                return None
+
+            # At least we got some data.
+            return filenames
+
+        def __addImplicitDependenciesOSX(self):
+            """ Walks through the list of files, looking for dylib's
+            and executables that might include implicit dependencies
+            on other dylib's.  Tries to determine those dependencies,
+            and adds them back into the filelist. """
+            pass
+
+        def __addImplicitDependenciesPosix(self):
+            """ Walks through the list of files, looking for so's
+            and executables that might include implicit dependencies
+            on other so's.  Tries to determine those dependencies,
+            and adds them back into the filelist. """
+            pass
+
         def addExtensionModules(self):
         def addExtensionModules(self):
             """ Adds the extension modules detected by the freezer to
             """ Adds the extension modules detected by the freezer to
             the current list of files. """
             the current list of files. """
@@ -247,7 +430,7 @@ class Packager:
                     newName += '/' + filename.getBasename()
                     newName += '/' + filename.getBasename()
                 # Sometimes the PYTHONPATH has the wrong case in it.
                 # Sometimes the PYTHONPATH has the wrong case in it.
                 filename.makeTrueCase()
                 filename.makeTrueCase()
-                self.files.append(Packager.PackFile(filename, newName = newName, extract = True))
+                self.addFile(filename, newName = newName, extract = True)
             freezer.extras = []
             freezer.extras = []
 
 
 
 
@@ -561,43 +744,19 @@ class Packager:
                     self.importedMapsDir, filename.getBasenameWoExtension(),
                     self.importedMapsDir, filename.getBasenameWoExtension(),
                     uniqueId, filename.getExtension())
                     uniqueId, filename.getExtension())
 
 
-            file = Packager.PackFile(filename, newName = newName)
-            self.sourceFilenames[filename] = file
-            self.targetFilenames[newName] = file
-            self.addTexture(file)
-
-            return newName
+            self.addFile(filename, newName = newName, compress = False)
 
 
-        def addTexture(self, file):
-            """ Adds a texture image to the output. """
-
-            if self.multifile.findSubfile(file.newName) >= 0:
-                # Already have this texture.
-                return
-
-            # Texture file formats are generally already compressed and
-            # not further compressible.
-            self.addComponent(file, compressible = False)
-
-        def addComponent(self, file, compressible = True, extract = None):
-            ext = Filename(file.newName).getExtension()
-            if ext in self.packager.uncompressibleExtensions:
-                compressible = False
-
-            extract = file.extract
-            if extract is None and ext in self.packager.extractExtensions:
-                extract = True
-
-            if ext in self.packager.platformSpecificExtensions:
+        def addComponent(self, file):
+            if file.platformSpecific:
                 if not self.platform:
                 if not self.platform:
                     self.platform = PandaSystem.getPlatform()
                     self.platform = PandaSystem.getPlatform()
                 
                 
             compressionLevel = 0
             compressionLevel = 0
-            if compressible:
+            if file.compress:
                 compressionLevel = self.compressionLevel
                 compressionLevel = self.compressionLevel
                 
                 
             self.multifile.addSubfile(file.newName, file.filename, compressionLevel)
             self.multifile.addSubfile(file.newName, file.filename, compressionLevel)
-            if extract:
+            if file.extract:
                 xextract = self.getFileSpec('extract', file.filename, file.newName)
                 xextract = self.getFileSpec('extract', file.filename, file.newName)
                 self.extracts.append(xextract)
                 self.extracts.append(xextract)
 
 
@@ -632,6 +791,16 @@ class Packager:
         # installed packages.
         # installed packages.
         self.installSearch = []
         self.installSearch = []
 
 
+        # The system PATH, for searching dll's.
+        self.dllPath = DSearchPath()
+        if PandaSystem.getPlatform().startswith('win'):
+            self.addWindowsSearchPath(self.dllPath, "PATH")
+        elif PandaSystem.getPlatform().startswith('osx'):
+            self.addPosixSearchPath(self.dllPath, "DYLD_LIBRARY_PATH")
+            self.addPosixSearchPath(self.dllPath, "LD_LIBRARY_PATH")
+        else:
+            self.addPosixSearchPath(self.dllPath, "LD_LIBRARY_PATH")
+
         # The platform string.
         # The platform string.
         self.platform = PandaSystem.getPlatform()
         self.platform = PandaSystem.getPlatform()
 
 
@@ -657,6 +826,13 @@ class Packager:
         # are server-side only and should be ignored by the Scrubber.
         # are server-side only and should be ignored by the Scrubber.
         self.dcClientSuffixes = ['OV']
         self.dcClientSuffixes = ['OV']
 
 
+        # Is this file system case-sensitive?
+        self.caseSensitive = True
+        if PandaSystem.getPlatform().startswith('win'):
+            self.caseSensitive = False
+        elif PandaSystem.getPlatform().startswith('osx'):
+            self.caseSensitive = False
+
         # Get the list of filename extensions that are recognized as
         # Get the list of filename extensions that are recognized as
         # image files.
         # image files.
         self.imageExtensions = []
         self.imageExtensions = []
@@ -677,16 +853,37 @@ class Packager:
         # processing.
         # processing.
         self.binaryExtensions = [ 'ttf', 'wav', 'mid' ]
         self.binaryExtensions = [ 'ttf', 'wav', 'mid' ]
 
 
+        # Files that represent an executable or shared library.
+        self.executableExtensions = [ 'dll', 'pyd', 'so', 'dylib', 'exe' ]
+
         # Files that should be extracted to disk.
         # Files that should be extracted to disk.
-        self.extractExtensions = [ 'dll', 'pyd', 'so', 'dylib', 'exe' ]
+        self.extractExtensions = self.executableExtensions[:]
 
 
         # Files that indicate a platform dependency.
         # Files that indicate a platform dependency.
-        self.platformSpecificExtensions = [ 'dll', 'pyd', 'so', 'dylib', 'exe' ]
+        self.platformSpecificExtensions = self.executableExtensions[:]
 
 
         # Binary files that are considered uncompressible, and are
         # Binary files that are considered uncompressible, and are
         # copied without compression.
         # copied without compression.
         self.uncompressibleExtensions = [ 'mp3', 'ogg' ]
         self.uncompressibleExtensions = [ 'mp3', 'ogg' ]
 
 
+        # System files that should never be packaged.  For
+        # case-insensitive filesystems (like Windows), put the
+        # lowercase filename here.  Case-sensitive filesystems should
+        # use the correct case.
+        self.excludeSystemFiles = [
+            'kernel32.dll', 'user32.dll', 'wsock32.dll', 'ws2_32.dll',
+            'advapi32.dll', 'opengl32.dll', 'glu32.dll', 'gdi32.dll',
+            'shell32.dll', 'ntdll.dll', 'ws2help.dll', 'rpcrt4.dll',
+            'imm32.dll', 'ddraw.dll', 'shlwapi.dll', 'secur32.dll',
+            'dciman32.dll', 'comdlg32.dll', 'comctl32.dll',
+            ]
+
+        # As above, but with filename globbing to catch a range of
+        # filenames.
+        self.excludeSystemGlobs = [
+            GlobPattern('d3dx9_*.dll'),
+            ]
+
         # A Loader for loading models.
         # A Loader for loading models.
         self.loader = Loader.Loader(self)
         self.loader = Loader.Loader(self)
         self.sfxManagerList = None
         self.sfxManagerList = None
@@ -700,6 +897,26 @@ class Packager:
 
 
         self.dryRun = False
         self.dryRun = False
 
 
+    def addWindowsSearchPath(self, searchPath, varname):
+        """ Expands $varname, interpreting as a Windows-style search
+        path, and adds its contents to the indicated DSearchPath. """
+
+        path = ExecutionEnvironment.getEnvironmentVariable(varname)
+        for dirname in path.split(';'):
+            dirname = Filename.fromOsSpecific(dirname)
+            if dirname.makeTrueCase():
+                searchPath.appendDirectory(dirname)
+
+    def addPosixSearchPath(self, searchPath, varname):
+        """ Expands $varname, interpreting as a Posix-style search
+        path, and adds its contents to the indicated DSearchPath. """
+
+        path = ExecutionEnvironment.getEnvironmentVariable(varname)
+        for dirname in path.split(':'):
+            dirname = Filename.fromOsSpecific(dirname)
+            if dirname.makeTrueCase():
+                searchPath.appendDirectory(dirname)
+
 
 
     def setup(self):
     def setup(self):
         """ Call this method to initialize the class after filling in
         """ Call this method to initialize the class after filling in
@@ -1027,7 +1244,7 @@ class Packager:
         """
         """
         newName = None
         newName = None
 
 
-        args = self.__parseArgs(words, ['extract'])
+        args = self.__parseArgs(words, ['forbid'])
 
 
         try:
         try:
             command, moduleName = words
             command, moduleName = words
@@ -1077,10 +1294,10 @@ class Packager:
 
 
     def parse_file(self, words):
     def parse_file(self, words):
         """
         """
-        file filename [newNameOrDir] [extract=1]
+        file filename [newNameOrDir] [extract=1] [executable=1]
         """
         """
 
 
-        args = self.__parseArgs(words, ['extract'])
+        args = self.__parseArgs(words, ['extract', 'executable'])
 
 
         newNameOrDir = None
         newNameOrDir = None
 
 
@@ -1096,8 +1313,25 @@ class Packager:
         if extract is not None:
         if extract is not None:
             extract = int(extract)
             extract = int(extract)
 
 
+        executable = args.get('executable', None)
+        if executable is not None:
+            executable = int(executable)
+
         self.file(Filename.fromOsSpecific(filename),
         self.file(Filename.fromOsSpecific(filename),
-                  newNameOrDir = newNameOrDir, extract = extract)
+                  newNameOrDir = newNameOrDir, extract = extract,
+                  executable = executable)
+
+    def parse_exclude(self, words):
+        """
+        exclude filename
+        """
+
+        try:
+            command, filename = words
+        except ValueError:
+            raise ArgumentError
+
+        self.exclude(Filename.fromOsSpecific(filename))
 
 
     def parse_dir(self, words):
     def parse_dir(self, words):
         """
         """
@@ -1471,7 +1705,8 @@ class Packager:
 
 
             basename = freezer.generateCode(basename, compileToExe = compileToExe)
             basename = freezer.generateCode(basename, compileToExe = compileToExe)
 
 
-            package.files.append(self.PackFile(Filename(basename), newName = dirname + basename, deleteTemp = True, extract = True))
+            package.addFile(Filename(basename), newName = dirname + basename,
+                            deleteTemp = True, extract = True)
             package.addExtensionModules()
             package.addExtensionModules()
             if not package.platform:
             if not package.platform:
                 package.platform = PandaSystem.getPlatform()
                 package.platform = PandaSystem.getPlatform()
@@ -1480,7 +1715,8 @@ class Packager:
         freezer.reset()
         freezer.reset()
         package.mainModule = None
         package.mainModule = None
 
 
-    def file(self, filename, newNameOrDir = None, extract = None):
+    def file(self, filename, newNameOrDir = None, extract = None,
+             executable = None):
         """ Adds the indicated arbitrary file to the current package.
         """ Adds the indicated arbitrary file to the current package.
 
 
         The file is placed in the named directory, or the toplevel
         The file is placed in the named directory, or the toplevel
@@ -1495,14 +1731,17 @@ class Packager:
         If newNameOrDir ends in a slash character, it specifies the
         If newNameOrDir ends in a slash character, it specifies the
         directory in which the file should be placed.  In this case,
         directory in which the file should be placed.  In this case,
         all files matched by the filename expression are placed in the
         all files matched by the filename expression are placed in the
-        named directory.
+        named directory.  If newNameOrDir ends in something other than
+        a slash character, it specifies a new filename.  In this case,
+        the filename expression must match only one file.  If
+        newNameOrDir is unspecified or None, the file is placed in the
+        toplevel directory, regardless of its source directory.
 
 
-        If newNameOrDir ends in something other than a slash
-        character, it specifies a new filename.  In this case, the
-        filename expression must match only one file.
+        If extract is true, the file is explicitly extracted at
+        runtime.
 
 
-        If newNameOrDir is unspecified or None, the file is placed in
-        the toplevel directory, regardless of its source directory.
+        If executable is true, the file is marked as an executable
+        filename, for special treatment.
         
         
         """
         """
 
 
@@ -1512,8 +1751,7 @@ class Packager:
         filename = Filename(filename)
         filename = Filename(filename)
         files = glob.glob(filename.toOsSpecific())
         files = glob.glob(filename.toOsSpecific())
         if not files:
         if not files:
-            self.notify.warning("No such file: %s" % (filename))
-            return
+            files = [filename.toOsSpecific()]
 
 
         newName = None
         newName = None
         prefix = ''
         prefix = ''
@@ -1530,10 +1768,25 @@ class Packager:
         for filename in files:
         for filename in files:
             filename = Filename.fromOsSpecific(filename)
             filename = Filename.fromOsSpecific(filename)
             basename = filename.getBasename()
             basename = filename.getBasename()
-            if newName:
-                self.addFile(filename, newName = newName, extract = extract)
-            else:
-                self.addFile(filename, newName = prefix + basename, extract = extract)
+            name = newName
+            if not name:
+                name = prefix + basename
+                
+            self.currentPackage.addFile(
+                filename, newName = name, extract = extract,
+                executable = executable)
+
+    def exclude(self, filename):
+        """ Marks the indicated filename as not to be included.  The
+        filename may include shell globbing characters, and may or may
+        not include a dirname.  (If it does not include a dirname, it
+        refers to any file with the given basename from any
+        directory.)"""
+
+        if not self.currentPackage:
+            raise OutsideOfPackageError
+
+        self.currentPackage.excludeFile(filename)
 
 
     def dir(self, dirname, newDir = None):
     def dir(self, dirname, newDir = None):
 
 
@@ -1571,7 +1824,7 @@ class Packager:
         # It's a file name.  Add it.
         # It's a file name.  Add it.
         ext = filename.getExtension()
         ext = filename.getExtension()
         if ext == 'py':
         if ext == 'py':
-            self.addFile(filename, newName = newName)
+            self.currentPackage.addFile(filename, newName = newName)
         else:
         else:
             if ext == 'pz':
             if ext == 'pz':
                 # Strip off an implicit .pz extension.
                 # Strip off an implicit .pz extension.
@@ -1581,14 +1834,4 @@ class Packager:
                 ext = newFilename.getExtension()
                 ext = newFilename.getExtension()
 
 
             if ext in self.knownExtensions:
             if ext in self.knownExtensions:
-                self.addFile(filename, newName = newName)
-
-    def addFile(self, filename, newName = None, extract = None):
-        """ Adds the named file, giving it the indicated name within
-        the package. """
-
-        if not self.currentPackage:
-            raise OutsideOfPackageError
-
-        self.currentPackage.files.append(
-            self.PackFile(filename, newName = newName, extract = extract))
+                self.currentPackage.addFile(filename, newName = newName)