]>
git.proxmox.com Git - mirror_edk2.git/blob - Tools/Python/InstallFar.py
6e28998cff1c5771d3beedcafa8a4eaccc656189
3 """This is a python script that takes user input from the command line and
4 installs a far (Framework Archive Manifest) file into the workspace."""
6 import os
, sys
, getopt
, string
, xml
.dom
.minidom
, zipfile
, md5
7 from XmlRoutines
import *
8 from WorkspaceRoutines
import *
11 """Keep track of some command line flags and operating modes."""
15 self
.reinstall
= False
19 """This class encapsulates the FrameworkDatabase file for the workspace we
22 def __init__(self
, filename
="Tools/Conf/FrameworkDatabase.db"):
24 # First try to get a lock file.
25 self
.DBFile
= inWorkspace(filename
)
26 self
.lockfile
= inWorkspace("Tools/Conf/FrameworkDatabase.lock")
27 if os
.path
.exists(self
.lockfile
):
28 self
.itsMyLockFile
= False
29 print "Error: The database file is locked by ", self
.lockfile
30 raise OSError("The Database is locked.")
32 self
.lock
= open(self
.lockfile
, 'w')
33 self
.lock
.write("pid "+str(os
.getpid()))
34 self
.itsMyLockFile
= True
36 self
.dom
= XmlParseFile(inWorkspace(filename
))
38 self
.installedPackages
= {}
39 self
.installedPlatforms
= {}
40 self
.installedFars
= {}
42 for spdfile
in XmlList(self
.dom
, "/FrameworkDatabase/PackageList/Filename"):
43 filename
= str(XmlElementData(spdfile
))
44 spd
= XmlParseFileSection(inWorkspace(filename
), "SpdHeader")
45 self
.installedPackages
[GetSpdGuidVersion(spd
, 1)] = \
46 XmlElement(spd
, "/SpdHeader/PackageName")
48 for fpdfile
in XmlList(self
.dom
, "/FrameworkDatabase/PlatformList/Filename"):
49 filename
= str(XmlElementData(fpdfile
))
50 fpd
= XmlParseFileSection(inWorkspace(filename
), "PlatformHeader")
51 self
.installedPlatforms
[GetFpdGuidVersion(fpd
, 1)] = \
52 XmlElement(fpd
, "/PlatformHeader/PlatformName")
54 for farfile
in XmlList(self
.dom
, "/FrameworkDatabase/FarList/Filename"):
55 farGuid
= farfile
.getAttribute("FarGuid")
56 self
.installedFars
[farGuid
] = XmlElementData(farfile
)
58 self
.packageList
= XmlNode(self
.dom
, "/FrameworkDatabase/PackageList")
59 self
.platformList
= XmlNode(self
.dom
, "/FrameworkDatabase/PlatformList")
60 self
.farList
= XmlNode(self
.dom
, "/FrameworkDatabase/FarList")
63 if self
.itsMyLockFile
:
65 os
.unlink(self
.lockfile
)
67 def HasPackage(self
, (guid
, version
)):
68 """Return true iff this package is already installed."""
71 for (g
, v
) in self
.installedPackages
.keys():
74 return self
.installedPackages
.has_key((guid
, version
))
76 def HasPlatform(self
, (guid
, version
)):
77 """Return true iff this platform is already installed."""
80 for (g
, v
) in self
.installedPlatforms
.keys():
83 return self
.installedPlatforms
.has_key((guid
, version
))
85 def HasFar(self
, farguid
):
86 """Return true iff this far is already installed."""
87 return self
.installedFars
.has_key(farguid
)
89 def AddPackage(self
, f
):
90 """Put this package in the database"""
91 XmlAppendChildElement(self
.packageList
, "Filename", f
)
93 def AddPlatform(self
, f
):
94 """Put this platform in the database"""
95 XmlAppendChildElement(self
.platformList
, "Filename", f
)
97 def AddFar(self
, f
, guid
=""):
98 """Put this far in the database"""
99 XmlAppendChildElement(self
.farList
, "Filename", f
, {"FarGuid":guid
} )
102 """Save the Xml tree out to the file."""
104 XmlSaveFile(self
.dom
, self
.DBFile
)
106 f
=open(self
.DBFile
, 'w')
107 f
.write(self
.dom
.toprettyxml(2*" "))
110 def ExtractFile(zip, file, defaultDir
="", workspaceLocation
="", md5sum
=""):
113 print "Extracting ", file
115 destFile
= os
.path
.join(inWorkspace(workspaceLocation
), str(file))
116 destDir
= os
.path
.dirname(destFile
)
120 f
= open(destFile
, "w")
121 contents
= zip.read(os
.path
.join(defaultDir
,file))
122 if md5sum
and (md5
.md5(contents
).hexdigest() != md5sum
):
123 print "Error: The md5 sum does not match on file %s." % file
127 def GetFpdGuidVersion(Dom
, strip
=0):
129 """Get the Guid and version of the fpd from a dom object."""
131 gpath
= ["PlatformSurfaceArea", "PlatformHeader", "GuidValue"]
132 vpath
= ["PlatformSurfaceArea", "PlatformHeader", "Version"]
134 return string
.lower(XmlElement(Dom
, "/".join(gpath
[strip
:]))), \
135 XmlElement(Dom
, "/".join(vpath
[strip
:]))
137 def GetSpdGuidVersion(Dom
, strip
=0):
139 """Get the Guid and version of the spd from a dom object."""
141 gpath
= ["PackageSurfaceArea", "SpdHeader", "GuidValue"]
142 vpath
= ["PackageSurfaceArea", "SpdHeader", "Version"]
144 return string
.lower(XmlElement(Dom
, "/".join(gpath
[strip
:]))), \
145 XmlElement(Dom
, "/".join(vpath
[strip
:]))
147 def InstallFar(farfile
, workspaceLocation
=""):
149 """Unpack the far an install it in the workspace. We need to adhere to the
150 rules of far handling."""
152 far
= zipfile
.ZipFile(farfile
, "r")
154 # Use this list to make sure we get everything from the far.
155 zipContents
= far
.namelist()
157 manifest
= xml
.dom
.minidom
.parseString(far
.read("FrameworkArchiveManifest.xml"))
158 zipContents
.remove("FrameworkArchiveManifest.xml")
161 # First we need to make sure that the far will install cleanly.
163 installError
= False # Let's hope for the best.
168 for farPackage
in XmlList(manifest
, "/FrameworkArchiveManifest/FarPackageList/FarPackage/FarFilename"):
169 spdfile
= str(XmlElementData(farPackage
))
170 spd
= XmlParseStringSection(far
.read(spdfile
), "SpdHeader")
171 packageGV
= GetSpdGuidVersion(spd
, 1)
172 if fdb
.HasPackage(packageGV
):
173 if not flags
.reinstall
:
174 print "Error: This package is already installed: ", spdfile
177 # Build up a list of the package guid versions that this far is bringing in.
178 # This is needed to satisfy dependencies of msas that are in the other packages of
180 farSpds
.append(packageGV
)
182 spdDoms
.append((spd
, spdfile
))
184 for spd
, spdfile
in spdDoms
:
185 # Now we need to get a list of every msa in this spd and check the package dependencies.
186 for msafile
in XmlList(spd
, "/PackageSurfaceArea/MsaFiles/Filename"):
187 msafilePath
= str(os
.path
.join(os
.path
.dirname(spdfile
), XmlElementData(msafile
)))
189 msa
= XmlParseString(far
.read(msafilePath
))
191 for package
in XmlList(msa
, "/ModuleSurfaceArea/PackageDependencies/Package"):
192 guid
= package
.getAttribute("PackageGuid")
193 version
= package
.getAttribute("PackageVersion")
195 # Does anyone provide this package?
196 if not fdb
.HasPackage((guid
, version
)) and not (guid
, version
) in farSpds
:
197 print ("Error: The module %s depends on the package guid %s version %s, which " + \
198 "is not installed in the workspace, nor is it provided by this far.") \
199 % (msafilePath
, guid
, version
)
202 # Check the platforms
203 for farPlatform
in XmlList(manifest
, "/FrameworkArchiveManifest/FarPlatformList/FarPlatform/FarFilename"):
204 fpdfile
= str(XmlElementData(farPlatform
))
205 fpd
= XmlParseString(far
.read(fpdfile
))
206 if fdb
.HasPlatform(GetFpdGuidVersion(fpd
, 0)):
207 if not flags
.reinstall
:
208 print "Error: This platform is already installed: ", fpdfile
211 # Now we need to check that all the Platforms (and modules?) that are
212 # referenced by this fpd are installed in the workspace or are in this far.
213 packagesNeeded
= set()
215 # Go through the dependencies
216 for dependency
in XmlList(fpd
, "/PlatformSurfaceArea/FrameworkModules/ModuleSA") + \
217 XmlList(fpd
, "/PlatformSurfaceArea/FrameworkModules/ModuleSA/Libraries/Instance"):
218 packagesNeeded
.add((string
.lower(dependency
.getAttribute("PackageGuid")),
219 dependency
.getAttribute("PackageVersion")))
221 # Let's see if all the packages are in the workspace
222 for guid
, version
in packagesNeeded
:
223 # Does anyone provide this package?
224 if not fdb
.HasPackage((guid
, version
)) and not (guid
, version
) in farSpds
:
225 print ("Error: The fpd %s depends on the package guid %s version %s, which " + \
226 "is not installed in the workspace, nor is it provided by this far.") \
227 % (fpdfile
, guid
, version
)
231 thisFarGuid
= string
.lower(XmlElement(manifest
, "/FrameworkArchiveManifest/FarHeader/GuidValue"))
232 if fdb
.HasFar(thisFarGuid
):
233 if not flags
.reinstall
:
234 print "Error: There is a far with this guid already installed."
237 # We can not do the install
240 print "Warning: Ignoring previous errors as you requested."
244 # Install the packages
245 for farPackage
in XmlList(manifest
, "/FrameworkArchiveManifest/FarPackageList/FarPackage"):
247 filename
= XmlElement(farPackage
, "FarPackage/FarFilename")
248 if not flags
.reinstall
:
249 fdb
.AddPackage(filename
)
250 ExtractFile(far
, filename
, workspaceLocation
)
251 zipContents
.remove(filename
)
253 DefaultPath
= XmlElement(farPackage
, "FarPackage/DefaultPath")
255 for content
in XmlList(farPackage
, "FarPackage/Contents/FarFilename"):
257 filename
= XmlElementData(content
)
258 ExtractFile(far
, filename
, DefaultPath
, workspaceLocation
, md5sum
=content
.getAttribute("Md5Sum"))
259 zipContents
.remove(os
.path
.join(DefaultPath
, filename
))
261 # Install the platforms
262 for farPlatform
in XmlList(manifest
, "/FrameworkArchiveManifest/FarPlatformList/FarPlatform"):
264 filename
= XmlElement(farPlatform
, "FarPlatform/FarFilename")
265 if not flags
.reinstall
:
266 fdb
.AddPlatform(filename
)
267 ExtractFile(far
, filename
, "", workspaceLocation
)
268 zipContents
.remove(filename
)
270 # Install the Contents
271 for content
in XmlList(manifest
, "/FrameworkArchiveManifest/Contents/FarFilename"):
273 filename
= XmlElementData(content
)
274 ExtractFile(far
, filename
, "", workspaceLocation
)
275 zipContents
.remove(filename
)
277 # What if there are more files in the far?
278 if not zipContents
== []:
279 print "Warning: There are files in the far that were not expected: ", zipContents
281 if not flags
.reinstall
:
282 fdb
.AddFar(farfile
, thisFarGuid
)
284 # If everything has gone well, we can put the manifest file in a safe place...
285 farDir
= inWorkspace("Tools/Conf/InstalledFars/")
287 f
=open(os
.path
.join(farDir
, thisFarGuid
), 'w')
288 f
.write(far
.read("FrameworkArchiveManifest.xml"))
291 # Write out the new database
292 if not flags
.reinstall
:
297 # This acts like the main() function for the script, unless it is 'import'ed
298 # into another script.
299 if __name__
== '__main__':
303 # Process the command line args.
304 optlist
, args
= getopt
.getopt(sys
.argv
[1:], '?hvf', ['help', 'verbose', 'force', 'reinstall'])
306 # First pass through the options list.
308 if o
in ["-h", "-?", "--help"]:
310 %s: Install a far (Framework Archive) into the current workspace.
311 """ % os
.path
.basename(sys
.argv
[0])
314 optlist
.remove((o
,a
))
315 if o
in ["-v", "--verbose"]:
317 if o
in ["-f", "--force"]:
319 if o
in ["--reinstall"]:
320 flags
.reinstall
= True
325 print "Please pass a far filename on the command line."