]>
Commit | Line | Data |
---|---|---|
4040421a | 1 | #!/usr/bin/env python |
2 | ||
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.""" | |
5 | ||
6 | import os, sys, getopt, string, xml.dom.minidom, zipfile, md5 | |
7 | from XmlRoutines import * | |
8 | from WorkspaceRoutines import * | |
9 | ||
10 | verbose = False | |
11 | force = False | |
12 | ||
13 | class 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 | ||
24a86f9a | 60 | def HasPackage(self, (guid, version)): |
4040421a | 61 | """Return true iff this package is already installed.""" |
24a86f9a | 62 | if version == "": |
63 | # Look for the guid. | |
64 | for (g, v) in self.installedPackages.keys(): | |
65 | if g == guid: | |
66 | return True | |
4040421a | 67 | return self.installedPackages.has_key((guid, version)) |
68 | ||
24a86f9a | 69 | def HasPlatform(self, (guid, version)): |
4040421a | 70 | """Return true iff this platform is already installed.""" |
24a86f9a | 71 | if version == "": |
72 | # Look for the guid. | |
73 | for (g, v) in self.installedPlatforms.keys(): | |
74 | if g == guid: | |
75 | return True | |
4040421a | 76 | return self.installedPlatforms.has_key((guid, version)) |
77 | ||
78 | def HasFar(self, farguid): | |
79 | """Return true iff this far is already installed.""" | |
80 | return self.installedFars.has_key(farguid) | |
81 | ||
82 | def AddPackage(self, f): | |
83 | filename = self.dom.createElement("Filename") | |
84 | filename.appendChild(self.dom.createTextNode(f)) | |
85 | self.packageList.appendChild(filename) | |
86 | ||
87 | def AddPlatform(self, f): | |
88 | filename = self.dom.createElement("Filename") | |
89 | filename.appendChild(self.dom.createTextNode(f)) | |
90 | self.platformList.appendChild(filename) | |
91 | ||
92 | def AddFar(self, f, guid=""): | |
93 | filename = self.dom.createElement("Filename") | |
94 | filename.setAttribute("FarGuid", guid) | |
95 | filename.appendChild(self.dom.createTextNode(f)) | |
96 | self.farList.appendChild(filename) | |
97 | ||
98 | def Write(self): | |
99 | if True: | |
100 | XmlSaveFile(self.dom, self.DBFile) | |
101 | else: | |
102 | f=open(self.DBFile, 'w') | |
103 | f.write(self.dom.toprettyxml(2*" ")) | |
104 | f.close() | |
105 | ||
106 | def ExtractFile(zip, file, workspaceLocation=""): | |
107 | ||
108 | if verbose: | |
109 | print "Extracting ", file | |
110 | ||
111 | destFile = os.path.join(inWorkspace(workspaceLocation), str(file)) | |
112 | destDir = os.path.dirname(destFile) | |
113 | ||
114 | mkdir(destDir) | |
115 | ||
116 | f = open(destFile, "w") | |
117 | f.write(zip.read(file)) | |
118 | f.close() | |
119 | ||
24a86f9a | 120 | def GetFpdGuidVersion(Dom): |
121 | ||
122 | """Get the Guid and version of the fpd from a dom object.""" | |
123 | ||
124 | return XmlElement(Dom, "/PlatformSurfaceArea/PlatformHeader/GuidValue"), \ | |
125 | XmlElement(Dom, "/PlatformSurfaceArea/PlatformHeader/Version") | |
126 | ||
127 | def GetSpdGuidVersion(Dom): | |
128 | ||
129 | """Get the Guid and version of the spd from a dom object.""" | |
130 | ||
131 | return XmlElement(Dom, "/PackageSurfaceArea/SpdHeader/GuidValue"), \ | |
132 | XmlElement(Dom, "/PackageSurfaceArea/SpdHeader/Version") | |
133 | ||
4040421a | 134 | def InstallFar(farfile, workspaceLocation=""): |
135 | ||
136 | far = zipfile.ZipFile(farfile, "r") | |
137 | ||
138 | # Use this list to make sure we get everything from the far. | |
139 | zipContents = far.namelist() | |
140 | ||
141 | manifest = xml.dom.minidom.parseString(far.read("FrameworkArchiveManifest.xml")) | |
142 | zipContents.remove("FrameworkArchiveManifest.xml") | |
143 | fdb = Database() | |
144 | ||
145 | # First we need to make sure that the far will install cleanly. | |
146 | ||
24a86f9a | 147 | installError = False # Let's hope for the best. |
148 | spdDoms = [] | |
149 | farSpds = [] | |
150 | ||
4040421a | 151 | # Check the packages |
152 | for farPackage in XmlList(manifest, "/FrameworkArchiveManifest/FarPackageList/FarPackage/FarFilename"): | |
153 | spdfile = str(XmlElementData(farPackage)) | |
24a86f9a | 154 | spd = XmlParseString(far.read(spdfile)) |
155 | packageGV = GetSpdGuidVersion(spd) | |
156 | if fdb.HasPackage(packageGV): | |
4040421a | 157 | print "Error: This package is already installed: ", spdfile |
158 | installError = True | |
159 | ||
24a86f9a | 160 | # Build up a list of the package guid versions that this far is bringing in. |
161 | # This is needed to satisfy dependencies of msas that are in the other packages of | |
162 | # this far. | |
163 | ||
164 | farSpds.append(packageGV) | |
165 | ||
166 | spdDoms.append(spd) | |
167 | ||
168 | for spd in spdDoms: | |
169 | # Now we need to get a list of every msa in this spd and check the package dependencies. | |
170 | for msafile in XmlList(spd, "/PackageSurfaceArea/MsaFiles/Filename"): | |
171 | msafilePath = str(os.path.join(os.path.dirname(spdfile), XmlElementData(msafile))) | |
172 | ||
173 | msa = XmlParseString(far.read(msafilePath)) | |
174 | ||
175 | for package in XmlList(msa, "/ModuleSurfaceArea/PackageDependencies/Package"): | |
176 | guid = package.getAttribute("PackageGuid") | |
177 | version = package.getAttribute("PackageVersion") | |
178 | ||
179 | if not fdb.HasPackage((guid, version)) and not (guid, version) in farSpds: | |
180 | print "The module %s depends on the package guid % version %s, which is not installed in the workspace." \ | |
181 | % (msafilePath, guid, version) | |
182 | installError = True | |
183 | ||
4040421a | 184 | # Check the platforms |
185 | for farPlatform in XmlList(manifest, "/FrameworkArchiveManifest/FarPlatformList/FarPlatform/FarFilename"): | |
186 | fpdfile = str(XmlElementData(farPlatform)) | |
24a86f9a | 187 | fpd = XmlParseString(far.read(fpdfile)) |
188 | if fdb.HasPlatform(GetFpdGuidVersion(fpd)): | |
4040421a | 189 | print "Error: This platform is already installed: ", fpdfile |
190 | installError = True | |
191 | ||
192 | # Check the fars | |
193 | thisFarGuid = XmlElement(manifest, "/FrameworkArchiveManifest/FarHeader/GuidValue") | |
194 | if fdb.HasFar(thisFarGuid): | |
195 | print "Error: There is a far with this guid already installed." | |
196 | installError = True | |
197 | ||
198 | # We can not do the install | |
199 | if installError: | |
200 | if force: | |
201 | print "Ignoring previous errors as you requested." | |
202 | else: | |
203 | return False | |
204 | ||
205 | # Install the packages | |
206 | for farPackage in XmlList(manifest, "/FrameworkArchiveManifest/FarPackageList/FarPackage"): | |
207 | ||
208 | filename = XmlElement(farPackage, "FarPackage/FarFilename") | |
209 | fdb.AddPackage(filename) | |
210 | ExtractFile(far, filename, workspaceLocation) | |
211 | zipContents.remove(filename) | |
212 | ||
213 | for content in XmlList(farPackage, "FarPackage/Contents/FarFilename"): | |
214 | ||
215 | filename = XmlElementData(content) | |
216 | ExtractFile(far, filename, workspaceLocation) | |
217 | zipContents.remove(filename) | |
218 | ||
219 | # Install the platforms | |
220 | for farPlatform in XmlList(manifest, "/FrameworkArchiveManifest/FarPlatformList/FarPlatform"): | |
221 | ||
222 | filename = XmlElement(farPlatform, "FarPlatform/FarFilename") | |
223 | fdb.AddPlatform(filename) | |
224 | ExtractFile(far, filename, workspaceLocation) | |
225 | zipContents.remove(filename) | |
226 | ||
227 | # Install the Contents | |
228 | for content in XmlList(manifest, "/FrameworkArchiveManifest/Contents/FarFilename"): | |
229 | ||
230 | filename = XmlElementData(content) | |
231 | ExtractFile(far, filename, workspaceLocation) | |
232 | zipContents.remove(filename) | |
233 | ||
234 | # What if there are more files in the far? | |
235 | if not zipContents == []: | |
236 | print "There are still files in the far:", zipContents | |
237 | ||
238 | fdb.AddFar(farfile, thisFarGuid) | |
239 | ||
240 | # If everything has gone well, we can put the manifest file in a safe place... | |
241 | farDir = inWorkspace("Tools/Conf/InstalledFars/") | |
242 | mkdir(farDir) | |
243 | f=open(os.path.join(farDir, thisFarGuid), 'w') | |
244 | f.write(far.read("FrameworkArchiveManifest.xml")) | |
245 | f.close() | |
246 | ||
247 | # Write out the new database | |
248 | fdb.Write() | |
249 | ||
250 | far.close() | |
251 | ||
252 | # This acts like the main() function for the script, unless it is 'import'ed | |
253 | # into another script. | |
254 | if __name__ == '__main__': | |
255 | ||
256 | # Process the command line args. | |
257 | optlist, args = getopt.getopt(sys.argv[1:], '?hvf', ['help', 'verbose', 'force']) | |
258 | ||
259 | # First pass through the options list. | |
260 | for o, a in optlist: | |
261 | if o in ["-h", "--help"]: | |
262 | print """ | |
263 | Install a far (Framework Archive) into the current workspace. | |
264 | """ % os.path.basename(sys.argv[0]) | |
265 | ||
266 | sys.exit() | |
267 | optlist.remove((o,a)) | |
268 | if o in ["-v", "--verbose"]: | |
269 | verbose = True | |
270 | if o in ["-f", "--force"]: | |
271 | force = True | |
272 | ||
273 | for f in args: | |
274 | InstallFar(f) | |
275 | if args == []: | |
276 | print "Please pass a far filename on the command line." |