Add a program to install fars.
[mirror_edk2.git] / Tools / Python / InstallFar.py
CommitLineData
4040421a 1#!/usr/bin/env python
2
3"""This is a python script that takes user input from the command line and
4installs a far (Framework Archive Manifest) file into the workspace."""
5
6import os, sys, getopt, string, xml.dom.minidom, zipfile, md5
7from XmlRoutines import *
8from WorkspaceRoutines import *
9
10verbose = False
11force = False
12
13class Database:
14
15 def __init__(self, filename="Tools/Conf/FrameworkDatabase.db"):
16
17 # First try to get a lock file.
18 self.DBFile = inWorkspace(filename)
19 self.lockfile = inWorkspace("Tools/Conf/FrameworkDatabase.lock")
20 if os.path.exists(self.lockfile):
21 self.itsMyLockFile = False
22 print "Error: The database file is locked by ", self.lockfile
23 raise OSError("The Database is locked.")
24 else:
25 self.lock = open(self.lockfile, 'w')
26 self.lock.write("pid "+str(os.getpid()))
27 self.itsMyLockFile = True
28
29 self.dom = XmlParseFile(inWorkspace(filename))
30
31 self.installedPackages = {}
32 self.installedPlatforms = {}
33 self.installedFars = {}
34
35 for spdfile in XmlList(self.dom, "/FrameworkDatabase/PackageList/Filename"):
36 filename = str(XmlElementData(spdfile))
37 spd = XmlParseFileSection(inWorkspace(filename), "SpdHeader")
38 self.installedPackages[XmlElement(spd, "/SpdHeader/GuidValue"), XmlElement(spd, "/SpdHeader/Version")] = \
39 XmlElement(spd, "/SpdHeader/PackageName")
40
41 for fpdfile in XmlList(self.dom, "/FrameworkDatabase/PlatformList/Filename"):
42 filename = str(XmlElementData(fpdfile))
43 fpd = XmlParseFileSection(inWorkspace(filename), "PlatformHeader")
44 self.installedPlatforms[XmlElement(fpd, "/PlatformHeader/GuidValue"), XmlElement(fpd, "/PlatformHeader/Version") ] = \
45 XmlElement(fpd, "/PlatformHeader/PlatformName")
46
47 for farfile in XmlList(self.dom, "/FrameworkDatabase/FarList/Filename"):
48 farGuid = farfile.getAttribute("FarGuid")
49 self.installedFars[farGuid] = XmlElementData(farfile)
50
51 self.packageList = XmlNode(self.dom, "/FrameworkDatabase/PackageList")
52 self.platformList = XmlNode(self.dom, "/FrameworkDatabase/PlatformList")
53 self.farList = XmlNode(self.dom, "/FrameworkDatabase/FarList")
54
55 def __del__(self):
56 if self.itsMyLockFile:
57 self.lock.close()
58 os.unlink(self.lockfile)
59
60 def HasPackage(self, spdString):
61 """Return true iff this package is already installed."""
62 spdHeader = XmlParseStringSection(spdString, "SpdHeader")
63 guid = XmlElement(spdHeader, "/SpdHeader/GuidValue")
64 version = XmlElement(spdHeader, "/SpdHeader/Version")
65 return self.installedPackages.has_key((guid, version))
66
67 def HasPlatform(self, fpdString):
68 """Return true iff this platform is already installed."""
69 fpdHeader = XmlParseStringSection(fpdString, "PlatformHeader")
70 guid = XmlElement(fpdHeader, "/PlatformHeader/GuidValue")
71 version = XmlElement(fpdHeader, "/PlatformHeader/Version")
72 return self.installedPlatforms.has_key((guid, version))
73
74 def HasFar(self, farguid):
75 """Return true iff this far is already installed."""
76 return self.installedFars.has_key(farguid)
77
78 def AddPackage(self, f):
79 filename = self.dom.createElement("Filename")
80 filename.appendChild(self.dom.createTextNode(f))
81 self.packageList.appendChild(filename)
82
83 def AddPlatform(self, f):
84 filename = self.dom.createElement("Filename")
85 filename.appendChild(self.dom.createTextNode(f))
86 self.platformList.appendChild(filename)
87
88 def AddFar(self, f, guid=""):
89 filename = self.dom.createElement("Filename")
90 filename.setAttribute("FarGuid", guid)
91 filename.appendChild(self.dom.createTextNode(f))
92 self.farList.appendChild(filename)
93
94 def Write(self):
95 if True:
96 XmlSaveFile(self.dom, self.DBFile)
97 else:
98 f=open(self.DBFile, 'w')
99 f.write(self.dom.toprettyxml(2*" "))
100 f.close()
101
102def ExtractFile(zip, file, workspaceLocation=""):
103
104 if verbose:
105 print "Extracting ", file
106
107 destFile = os.path.join(inWorkspace(workspaceLocation), str(file))
108 destDir = os.path.dirname(destFile)
109
110 mkdir(destDir)
111
112 f = open(destFile, "w")
113 f.write(zip.read(file))
114 f.close()
115
116def InstallFar(farfile, workspaceLocation=""):
117
118 far = zipfile.ZipFile(farfile, "r")
119
120 # Use this list to make sure we get everything from the far.
121 zipContents = far.namelist()
122
123 manifest = xml.dom.minidom.parseString(far.read("FrameworkArchiveManifest.xml"))
124 zipContents.remove("FrameworkArchiveManifest.xml")
125 fdb = Database()
126
127 # First we need to make sure that the far will install cleanly.
128
129 # Check the packages
130 for farPackage in XmlList(manifest, "/FrameworkArchiveManifest/FarPackageList/FarPackage/FarFilename"):
131 spdfile = str(XmlElementData(farPackage))
132 if fdb.HasPackage(far.read(spdfile)):
133 print "Error: This package is already installed: ", spdfile
134 installError = True
135
136 # Check the platforms
137 for farPlatform in XmlList(manifest, "/FrameworkArchiveManifest/FarPlatformList/FarPlatform/FarFilename"):
138 fpdfile = str(XmlElementData(farPlatform))
139 if fdb.HasPlatform(far.read(fpdfile)):
140 print "Error: This platform is already installed: ", fpdfile
141 installError = True
142
143 # Check the fars
144 thisFarGuid = XmlElement(manifest, "/FrameworkArchiveManifest/FarHeader/GuidValue")
145 if fdb.HasFar(thisFarGuid):
146 print "Error: There is a far with this guid already installed."
147 installError = True
148
149 # We can not do the install
150 if installError:
151 if force:
152 print "Ignoring previous errors as you requested."
153 else:
154 return False
155
156 # Install the packages
157 for farPackage in XmlList(manifest, "/FrameworkArchiveManifest/FarPackageList/FarPackage"):
158
159 filename = XmlElement(farPackage, "FarPackage/FarFilename")
160 fdb.AddPackage(filename)
161 ExtractFile(far, filename, workspaceLocation)
162 zipContents.remove(filename)
163
164 for content in XmlList(farPackage, "FarPackage/Contents/FarFilename"):
165
166 filename = XmlElementData(content)
167 ExtractFile(far, filename, workspaceLocation)
168 zipContents.remove(filename)
169
170 # Install the platforms
171 for farPlatform in XmlList(manifest, "/FrameworkArchiveManifest/FarPlatformList/FarPlatform"):
172
173 filename = XmlElement(farPlatform, "FarPlatform/FarFilename")
174 fdb.AddPlatform(filename)
175 ExtractFile(far, filename, workspaceLocation)
176 zipContents.remove(filename)
177
178 # Install the Contents
179 for content in XmlList(manifest, "/FrameworkArchiveManifest/Contents/FarFilename"):
180
181 filename = XmlElementData(content)
182 ExtractFile(far, filename, workspaceLocation)
183 zipContents.remove(filename)
184
185 # What if there are more files in the far?
186 if not zipContents == []:
187 print "There are still files in the far:", zipContents
188
189 fdb.AddFar(farfile, thisFarGuid)
190
191 # If everything has gone well, we can put the manifest file in a safe place...
192 farDir = inWorkspace("Tools/Conf/InstalledFars/")
193 mkdir(farDir)
194 f=open(os.path.join(farDir, thisFarGuid), 'w')
195 f.write(far.read("FrameworkArchiveManifest.xml"))
196 f.close()
197
198 # Write out the new database
199 fdb.Write()
200
201 far.close()
202
203# This acts like the main() function for the script, unless it is 'import'ed
204# into another script.
205if __name__ == '__main__':
206
207 # Process the command line args.
208 optlist, args = getopt.getopt(sys.argv[1:], '?hvf', ['help', 'verbose', 'force'])
209
210 # First pass through the options list.
211 for o, a in optlist:
212 if o in ["-h", "--help"]:
213 print """
214Install a far (Framework Archive) into the current workspace.
215""" % os.path.basename(sys.argv[0])
216
217 sys.exit()
218 optlist.remove((o,a))
219 if o in ["-v", "--verbose"]:
220 verbose = True
221 if o in ["-f", "--force"]:
222 force = True
223
224 for f in args:
225 InstallFar(f)
226 if args == []:
227 print "Please pass a far filename on the command line."