Add a program to install fars.
authorbbahnsen <bbahnsen@de2fecce-e211-0410-80a6-f3fac2684e05>
Sat, 20 Jan 2007 00:41:32 +0000 (00:41 +0000)
committerbbahnsen <bbahnsen@de2fecce-e211-0410-80a6-f3fac2684e05>
Sat, 20 Jan 2007 00:41:32 +0000 (00:41 +0000)
git-svn-id: https://edk2.tianocore.org/svn/edk2/trunk@2276 de2fecce-e211-0410-80a6-f3fac2684e05

edk2/Tools/Python/GenMake.py
edk2/Tools/Python/InstallFar.py [new file with mode: 0755]
edk2/Tools/Python/WorkspaceRoutines.py
edk2/Tools/Python/XmlRoutines.py

index df78f72..171a6d7 100755 (executable)
@@ -19,14 +19,6 @@ OBJECTS = $OBJECTS
 include $$(MAKEROOT)/lib.makefile
 """)
 
-def mkdir(path):
-  """Make a directory if it is not there already."""
-
-  try:
-    os.makedirs(path)
-  except:
-    pass
-
 def openSpd(spdFile):
 
   """Open the spdFile and process the msa files it contains."""
diff --git a/edk2/Tools/Python/InstallFar.py b/edk2/Tools/Python/InstallFar.py
new file mode 100755 (executable)
index 0000000..c1dc4c1
--- /dev/null
@@ -0,0 +1,227 @@
+#!/usr/bin/env python
+
+"""This is a python script that takes user input from the command line and
+installs a far (Framework Archive Manifest) file into the workspace."""
+
+import os, sys, getopt, string, xml.dom.minidom, zipfile, md5
+from XmlRoutines import *
+from WorkspaceRoutines import *
+
+verbose = False
+force = False
+
+class Database:
+
+  def __init__(self, filename="Tools/Conf/FrameworkDatabase.db"): 
+
+    # First try to get a lock file.
+    self.DBFile = inWorkspace(filename)
+    self.lockfile = inWorkspace("Tools/Conf/FrameworkDatabase.lock")
+    if os.path.exists(self.lockfile):
+      self.itsMyLockFile = False
+      print "Error: The database file is locked by ", self.lockfile
+      raise OSError("The Database is locked.")
+    else:
+      self.lock = open(self.lockfile, 'w')
+      self.lock.write("pid "+str(os.getpid()))
+      self.itsMyLockFile = True
+
+    self.dom = XmlParseFile(inWorkspace(filename))
+
+    self.installedPackages = {}
+    self.installedPlatforms = {}
+    self.installedFars = {}
+
+    for spdfile in XmlList(self.dom, "/FrameworkDatabase/PackageList/Filename"):
+      filename = str(XmlElementData(spdfile))
+      spd = XmlParseFileSection(inWorkspace(filename), "SpdHeader")
+      self.installedPackages[XmlElement(spd, "/SpdHeader/GuidValue"), XmlElement(spd, "/SpdHeader/Version")] = \
+        XmlElement(spd, "/SpdHeader/PackageName")
+
+    for fpdfile in XmlList(self.dom, "/FrameworkDatabase/PlatformList/Filename"):
+      filename = str(XmlElementData(fpdfile))
+      fpd = XmlParseFileSection(inWorkspace(filename), "PlatformHeader")
+      self.installedPlatforms[XmlElement(fpd, "/PlatformHeader/GuidValue"), XmlElement(fpd, "/PlatformHeader/Version") ] = \
+        XmlElement(fpd, "/PlatformHeader/PlatformName")
+
+    for farfile in  XmlList(self.dom, "/FrameworkDatabase/FarList/Filename"):
+      farGuid = farfile.getAttribute("FarGuid")
+      self.installedFars[farGuid] = XmlElementData(farfile)
+
+    self.packageList = XmlNode(self.dom, "/FrameworkDatabase/PackageList")
+    self.platformList = XmlNode(self.dom, "/FrameworkDatabase/PlatformList")
+    self.farList = XmlNode(self.dom, "/FrameworkDatabase/FarList")
+
+  def __del__(self):
+    if self.itsMyLockFile:
+      self.lock.close()
+      os.unlink(self.lockfile)
+
+  def HasPackage(self, spdString):
+    """Return true iff this package is already installed."""
+    spdHeader = XmlParseStringSection(spdString, "SpdHeader")
+    guid = XmlElement(spdHeader, "/SpdHeader/GuidValue")
+    version = XmlElement(spdHeader, "/SpdHeader/Version")
+    return self.installedPackages.has_key((guid, version))
+
+  def HasPlatform(self, fpdString):
+    """Return true iff this platform is already installed."""
+    fpdHeader = XmlParseStringSection(fpdString, "PlatformHeader")
+    guid = XmlElement(fpdHeader, "/PlatformHeader/GuidValue")
+    version = XmlElement(fpdHeader, "/PlatformHeader/Version")
+    return self.installedPlatforms.has_key((guid, version))
+
+  def HasFar(self, farguid):
+    """Return true iff this far is already installed."""
+    return self.installedFars.has_key(farguid)
+
+  def AddPackage(self, f):
+    filename = self.dom.createElement("Filename")
+    filename.appendChild(self.dom.createTextNode(f))
+    self.packageList.appendChild(filename)
+    
+  def AddPlatform(self, f):
+    filename = self.dom.createElement("Filename")
+    filename.appendChild(self.dom.createTextNode(f))
+    self.platformList.appendChild(filename)
+
+  def AddFar(self, f, guid=""):
+    filename = self.dom.createElement("Filename")
+    filename.setAttribute("FarGuid", guid)
+    filename.appendChild(self.dom.createTextNode(f))
+    self.farList.appendChild(filename)
+
+  def Write(self):
+    if True:
+      XmlSaveFile(self.dom, self.DBFile)
+    else:
+      f=open(self.DBFile, 'w')
+      f.write(self.dom.toprettyxml(2*" "))
+      f.close()
+
+def ExtractFile(zip, file, workspaceLocation=""):
+
+  if verbose:
+    print "Extracting ", file
+
+  destFile = os.path.join(inWorkspace(workspaceLocation), str(file))
+  destDir = os.path.dirname(destFile)
+
+  mkdir(destDir)
+
+  f = open(destFile, "w")
+  f.write(zip.read(file))
+  f.close()
+
+def InstallFar(farfile, workspaceLocation=""):
+
+  far = zipfile.ZipFile(farfile, "r")
+
+  # Use this list to make sure we get everything from the far.
+  zipContents = far.namelist()
+
+  manifest = xml.dom.minidom.parseString(far.read("FrameworkArchiveManifest.xml"))
+  zipContents.remove("FrameworkArchiveManifest.xml")
+  fdb = Database()
+
+  # First we need to make sure that the far will install cleanly.
+
+  # Check the packages
+  for farPackage in XmlList(manifest, "/FrameworkArchiveManifest/FarPackageList/FarPackage/FarFilename"):
+    spdfile = str(XmlElementData(farPackage))
+    if fdb.HasPackage(far.read(spdfile)):
+      print "Error: This package is already installed: ", spdfile
+      installError = True
+
+  # Check the platforms
+  for farPlatform in XmlList(manifest, "/FrameworkArchiveManifest/FarPlatformList/FarPlatform/FarFilename"):
+    fpdfile = str(XmlElementData(farPlatform))
+    if fdb.HasPlatform(far.read(fpdfile)):
+      print "Error: This platform is already installed: ", fpdfile
+      installError = True
+
+  # Check the fars
+  thisFarGuid = XmlElement(manifest, "/FrameworkArchiveManifest/FarHeader/GuidValue")
+  if fdb.HasFar(thisFarGuid):
+    print "Error: There is a far with this guid already installed."
+    installError = True
+
+  # We can not do the install
+  if installError:
+    if force:
+      print "Ignoring previous errors as you requested."
+    else:
+      return False
+
+  # Install the packages
+  for farPackage in XmlList(manifest, "/FrameworkArchiveManifest/FarPackageList/FarPackage"):
+
+    filename = XmlElement(farPackage, "FarPackage/FarFilename")
+    fdb.AddPackage(filename)
+    ExtractFile(far, filename, workspaceLocation)
+    zipContents.remove(filename)
+
+    for content in XmlList(farPackage, "FarPackage/Contents/FarFilename"):
+
+      filename = XmlElementData(content)
+      ExtractFile(far, filename, workspaceLocation)
+      zipContents.remove(filename)
+
+  # Install the platforms
+  for farPlatform in XmlList(manifest, "/FrameworkArchiveManifest/FarPlatformList/FarPlatform"):
+    
+    filename = XmlElement(farPlatform, "FarPlatform/FarFilename")
+    fdb.AddPlatform(filename)
+    ExtractFile(far, filename, workspaceLocation)
+    zipContents.remove(filename)
+
+  # Install the Contents
+  for content in XmlList(manifest, "/FrameworkArchiveManifest/Contents/FarFilename"):
+
+    filename = XmlElementData(content)
+    ExtractFile(far, filename, workspaceLocation)
+    zipContents.remove(filename)
+
+  # What if there are more files in the far?
+  if not zipContents == []:
+    print "There are still files in the far:", zipContents
+
+  fdb.AddFar(farfile, thisFarGuid)
+
+  # If everything has gone well, we can put the manifest file in a safe place...
+  farDir = inWorkspace("Tools/Conf/InstalledFars/")
+  mkdir(farDir)
+  f=open(os.path.join(farDir, thisFarGuid), 'w')
+  f.write(far.read("FrameworkArchiveManifest.xml"))
+  f.close()
+
+  # Write out the new database
+  fdb.Write()
+  
+  far.close()
+
+# This acts like the main() function for the script, unless it is 'import'ed
+# into another script.
+if __name__ == '__main__':
+
+  # Process the command line args.
+  optlist, args = getopt.getopt(sys.argv[1:], '?hvf', ['help', 'verbose', 'force'])
+
+  # First pass through the options list.
+  for o, a in optlist:
+    if o in ["-h", "--help"]:
+      print """
+Install a far (Framework Archive) into the current workspace.
+""" % os.path.basename(sys.argv[0])
+
+      sys.exit()
+      optlist.remove((o,a))
+    if o in ["-v", "--verbose"]:
+      verbose = True
+    if o in ["-f", "--force"]:
+      force = True
+
+  for f in args:
+    InstallFar(f)
+  if args == []:
+    print "Please pass a far filename on the command line."
index 3634d25..8ca88b7 100755 (executable)
@@ -33,3 +33,12 @@ def lean(path):
   """Lean the slashes forward"""
 
   return os.path.normpath(path).replace("\\", "/")
+
+def mkdir(path):
+  """Make a directory if it is not there already."""
+
+  try:
+    os.makedirs(path)
+  except:
+    pass
+
index 53f5aa8..0345f4a 100755 (executable)
@@ -16,12 +16,12 @@ import xml.dom.minidom
 
 def XmlList(Dom, String):
   """Get a list of XML Elements using XPath style syntax."""
+  if String == "" :
+    return []
   if Dom.nodeType==Dom.DOCUMENT_NODE:
     return XmlList(Dom.documentElement, String)
   if String[0] == "/":
     return XmlList(Dom, String[1:])
-  if String == "" :
-    return []
   TagList = String.split('/')
   nodes = []
   if Dom.nodeType == Dom.ELEMENT_NODE and Dom.tagName.strip() == TagList[0]:
@@ -33,6 +33,14 @@ def XmlList(Dom, String):
         nodes = nodes + XmlList(child, restOfPath)
   return nodes
 
+def XmlNode (Dom, String):
+  """Return a single node that matches the String which is XPath style syntax."""
+  try:
+    return XmlList (Dom, String)[0]
+  except:
+    return None
+
+
 def XmlElement (Dom, String):
   """Return a single element that matches the String which is XPath style syntax."""
   try:
@@ -88,6 +96,19 @@ def XmlParseFileSection (FileName, Tag):
   except:
     return xml.dom.minidom.parseString('<empty/>')
 
+def XmlParseStringSection (XmlString, Tag):
+  """Parse a section of an XML string into a DOM(Document Object Model) and return the DOM."""
+  Start = '<' + Tag
+  End = '</' + Tag + '>'
+  File = XmlString
+  if File.find(Start) < 0 or File.find(End) < 0:
+    return xml.dom.minidom.parseString('<empty/>')
+  File = File[File.find(Start):File.find(End)+len(End)]
+  try:
+    return xml.dom.minidom.parseString(File)
+  except:
+    return xml.dom.minidom.parseString('<empty/>')
+
 def XmlSaveFile (Dom, FileName, Encoding='UTF-8'):
   """Save a DOM(Document Object Model) into an XML file."""
   try: