]>
git.proxmox.com Git - mirror_edk2.git/blob - Tools/Python/InstallFar.py
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
20 """This class encapsulates the FrameworkDatabase file for the workspace we
23 def __init__(self
, filename
="Tools/Conf/FrameworkDatabase.db"):
25 # First try to get a lock file.
26 self
.DBFile
= inWorkspace(filename
)
27 self
.lockfile
= inWorkspace("Tools/Conf/FrameworkDatabase.lock")
28 if os
.path
.exists(self
.lockfile
):
29 self
.itsMyLockFile
= False
30 print "Error: The database file is locked by ", self
.lockfile
31 raise OSError("The Database is locked.")
33 self
.lock
= open(self
.lockfile
, 'w')
34 self
.lock
.write("pid "+str(os
.getpid()))
35 self
.itsMyLockFile
= True
37 self
.dom
= XmlParseFile(inWorkspace(filename
))
39 self
.installedPackages
= {}
40 self
.installedPlatforms
= {}
41 self
.installedFars
= {}
43 for spdfile
in XmlList(self
.dom
, "/FrameworkDatabase/PackageList/Filename"):
44 filename
= str(XmlElementData(spdfile
))
45 spd
= XmlParseFileSection(inWorkspace(filename
), "SpdHeader")
46 self
.installedPackages
[GetSpdGuidVersion(spd
, 1)] = \
47 XmlElement(spd
, "/SpdHeader/PackageName")
49 for fpdfile
in XmlList(self
.dom
, "/FrameworkDatabase/PlatformList/Filename"):
50 filename
= str(XmlElementData(fpdfile
))
51 fpd
= XmlParseFileSection(inWorkspace(filename
), "PlatformHeader")
52 self
.installedPlatforms
[GetFpdGuidVersion(fpd
, 1)] = \
53 XmlElement(fpd
, "/PlatformHeader/PlatformName")
55 for farfile
in XmlList(self
.dom
, "/FrameworkDatabase/FarList/Filename"):
56 farGuid
= Guid(farfile
.getAttribute("FarGuid"))
57 self
.installedFars
[farGuid
] = XmlElementData(farfile
)
59 self
.packageList
= XmlNode(self
.dom
, "/FrameworkDatabase/PackageList")
60 self
.platformList
= XmlNode(self
.dom
, "/FrameworkDatabase/PlatformList")
61 self
.farList
= XmlNode(self
.dom
, "/FrameworkDatabase/FarList")
64 if self
.itsMyLockFile
:
66 os
.unlink(self
.lockfile
)
68 def HasPackage(self
, (guid
, version
)):
69 """Return true iff this package is already installed."""
72 for (g
, v
) in self
.installedPackages
.keys():
75 return self
.installedPackages
.has_key((guid
, version
))
77 def HasPlatform(self
, (guid
, version
)):
78 """Return true iff this platform is already installed."""
81 for (g
, v
) in self
.installedPlatforms
.keys():
84 return self
.installedPlatforms
.has_key((guid
, version
))
86 def HasFar(self
, farguid
):
87 """Return true iff this far is already installed."""
88 return self
.installedFars
.has_key(farguid
)
90 def AddPackage(self
, f
):
91 """Put this package in the database"""
92 XmlAppendChildElement(self
.packageList
, "Filename", f
)
94 def AddPlatform(self
, f
):
95 """Put this platform in the database"""
96 XmlAppendChildElement(self
.platformList
, "Filename", f
)
98 def AddFar(self
, f
, guid
=""):
99 """Put this far in the database"""
100 XmlAppendChildElement(self
.farList
, "Filename", f
, {"FarGuid":guid
} )
103 """Save the Xml tree out to the file."""
105 XmlSaveFile(self
.dom
, self
.DBFile
)
107 f
=open(self
.DBFile
, 'w')
108 f
.write(self
.dom
.toprettyxml(2*" "))
111 def ExtractFile(zip, file, defaultDir
="", workspaceLocation
="", md5sum
=""):
114 print "Extracting ", file
116 destFile
= os
.path
.join(inWorkspace(workspaceLocation
), str(file))
117 destDir
= os
.path
.dirname(destFile
)
121 f
= open(destFile
, "w")
122 contents
= zip.read(os
.path
.join(defaultDir
,file))
123 if md5sum
and (md5
.md5(contents
).hexdigest() != md5sum
):
124 print "Error: The md5 sum does not match on file %s." % file
128 def GetFpdGuidVersion(Dom
, strip
=0):
130 """Get the Guid and version of the fpd from a dom object."""
132 gpath
= ["PlatformSurfaceArea", "PlatformHeader", "GuidValue"]
133 vpath
= ["PlatformSurfaceArea", "PlatformHeader", "Version"]
135 return Guid(XmlElement(Dom
, "/".join(gpath
[strip
:]))), \
136 XmlElement(Dom
, "/".join(vpath
[strip
:]))
138 def GetSpdGuidVersion(Dom
, strip
=0):
140 """Get the Guid and version of the spd from a dom object."""
142 gpath
= ["PackageSurfaceArea", "SpdHeader", "GuidValue"]
143 vpath
= ["PackageSurfaceArea", "SpdHeader", "Version"]
145 return Guid(XmlElement(Dom
, "/".join(gpath
[strip
:]))), \
146 XmlElement(Dom
, "/".join(vpath
[strip
:]))
148 def InstallFar(farfile
, workspaceLocation
=""):
150 """Unpack the far an install it in the workspace. We need to adhere to the
151 rules of far handling."""
153 far
= zipfile
.ZipFile(farfile
, "r")
155 # Use this list to make sure we get everything from the far.
156 zipContents
= far
.namelist()
158 manifest
= xml
.dom
.minidom
.parseString(far
.read("FrameworkArchiveManifest.xml"))
159 zipContents
.remove("FrameworkArchiveManifest.xml")
162 # First we need to make sure that the far will install cleanly.
164 installError
= False # Let's hope for the best.
169 for farPackage
in XmlList(manifest
, "/FrameworkArchiveManifest/FarPackageList/FarPackage/FarFilename"):
170 spdfile
= str(XmlElementData(farPackage
))
171 spd
= XmlParseStringSection(far
.read(spdfile
), "SpdHeader")
172 packageGV
= GetSpdGuidVersion(spd
, 1)
173 if fdb
.HasPackage(packageGV
):
174 if not flags
.reinstall
:
175 print "Error: This package is already installed: ", spdfile
178 # Build up a list of the package guid versions that this far is bringing in.
179 # This is needed to satisfy dependencies of msas that are in the other packages of
181 farSpds
.append(packageGV
)
183 spdDoms
.append((spd
, spdfile
))
185 for spd
, spdfile
in spdDoms
:
186 # Now we need to get a list of every msa in this spd and check the package dependencies.
187 for msafile
in XmlList(spd
, "/PackageSurfaceArea/MsaFiles/Filename"):
188 msafilePath
= str(os
.path
.join(os
.path
.dirname(spdfile
), XmlElementData(msafile
)))
190 msa
= XmlParseString(far
.read(msafilePath
))
192 for package
in XmlList(msa
, "/ModuleSurfaceArea/PackageDependencies/Package"):
193 guid
= Guid(package
.getAttribute("PackageGuid"))
194 version
= package
.getAttribute("PackageVersion")
196 # Does anyone provide this package?
197 if not fdb
.HasPackage((guid
, version
)) and not (guid
, version
) in farSpds
:
198 print ("Error: The module %s depends on the package guid %s version %s, which " + \
199 "is not installed in the workspace, nor is it provided by this far.") \
200 % (msafilePath
, guid
, version
)
203 # Check the platforms
204 for farPlatform
in XmlList(manifest
, "/FrameworkArchiveManifest/FarPlatformList/FarPlatform/FarFilename"):
205 fpdfile
= str(XmlElementData(farPlatform
))
206 fpd
= XmlParseString(far
.read(fpdfile
))
207 if fdb
.HasPlatform(GetFpdGuidVersion(fpd
, 0)):
208 if not flags
.reinstall
:
209 print "Error: This platform is already installed: ", fpdfile
212 # Now we need to check that all the Platforms (and modules?) that are
213 # referenced by this fpd are installed in the workspace or are in this far.
214 packagesNeeded
= set()
216 # Go through the dependencies
217 for dependency
in XmlList(fpd
, "/PlatformSurfaceArea/FrameworkModules/ModuleSA") + \
218 XmlList(fpd
, "/PlatformSurfaceArea/FrameworkModules/ModuleSA/Libraries/Instance"):
219 packagesNeeded
.add((Guid(dependency
.getAttribute("PackageGuid")),
220 dependency
.getAttribute("PackageVersion")))
222 # Let's see if all the packages are in the workspace
223 for guid
, version
in packagesNeeded
:
224 # Does anyone provide this package?
225 if not fdb
.HasPackage((guid
, version
)) and not (guid
, version
) in farSpds
:
226 print ("Error: The fpd %s depends on the package guid %s version %s, which " + \
227 "is not installed in the workspace, nor is it provided by this far.") \
228 % (fpdfile
, guid
, version
)
232 thisFarGuid
= Guid(XmlElement(manifest
, "/FrameworkArchiveManifest/FarHeader/GuidValue"))
233 if fdb
.HasFar(thisFarGuid
):
234 if not flags
.reinstall
:
235 print "Error: There is a far with this guid already installed."
238 # We can not do the install
241 print "Warning: Ignoring previous errors as you requested."
245 # Install the packages
246 for farPackage
in XmlList(manifest
, "/FrameworkArchiveManifest/FarPackageList/FarPackage"):
248 filename
= XmlElement(farPackage
, "FarPackage/FarFilename")
249 if not flags
.reinstall
:
250 fdb
.AddPackage(filename
)
251 ExtractFile(far
, filename
, workspaceLocation
)
252 zipContents
.remove(filename
)
254 DefaultPath
= XmlElement(farPackage
, "FarPackage/DefaultPath")
256 for content
in XmlList(farPackage
, "FarPackage/Contents/FarFilename"):
258 filename
= XmlElementData(content
)
259 ExtractFile(far
, filename
, DefaultPath
, workspaceLocation
, md5sum
=content
.getAttribute("Md5Sum"))
260 zipContents
.remove(os
.path
.join(DefaultPath
, filename
))
262 # Install the platforms
263 for farPlatform
in XmlList(manifest
, "/FrameworkArchiveManifest/FarPlatformList/FarPlatform"):
265 filename
= XmlElement(farPlatform
, "FarPlatform/FarFilename")
266 if not flags
.reinstall
:
267 fdb
.AddPlatform(filename
)
268 ExtractFile(far
, filename
, "", workspaceLocation
)
269 zipContents
.remove(filename
)
271 # Install the Contents
272 for content
in XmlList(manifest
, "/FrameworkArchiveManifest/Contents/FarFilename"):
274 filename
= XmlElementData(content
)
275 ExtractFile(far
, filename
, "", workspaceLocation
)
276 zipContents
.remove(filename
)
278 # What if there are more files in the far?
279 if not zipContents
== []:
280 print "Warning: There are files in the far that were not expected: ", zipContents
282 if not flags
.reinstall
:
283 fdb
.AddFar(farfile
, thisFarGuid
)
285 # If everything has gone well, we can put the manifest file in a safe place...
286 farDir
= inWorkspace("Tools/Conf/InstalledFars/")
288 f
=open(os
.path
.join(farDir
, thisFarGuid
), 'w')
289 f
.write(far
.read("FrameworkArchiveManifest.xml"))
292 # Write out the new database
293 if not flags
.reinstall
:
298 # This acts like the main() function for the script, unless it is 'import'ed
299 # into another script.
300 if __name__
== '__main__':
304 # Process the command line args.
305 optlist
, args
= getopt
.getopt(sys
.argv
[1:], '?hvfd:', ['directory=', 'help', 'verbose', 'force', 'reinstall'])
307 # First pass through the options list.
309 if o
in ["-h", "-?", "--help"]:
311 %s: Install a far (Framework Archive) into the current workspace.
312 """ % os
.path
.basename(sys
.argv
[0])
315 optlist
.remove((o
,a
))
316 if o
in ["-v", "--verbose"]:
318 if o
in ["-d", "--directory"]:
320 if o
in ["-f", "--force"]:
322 if o
in ["--reinstall"]:
323 flags
.reinstall
= True
328 print "Please pass a far filename on the command line."