source: trunk/gsinstaller/gsManifest.cpp@ 2535

Last change on this file since 2535 was 2534, checked in by cs025, 23 years ago

Added better monitoring of installation

  • Property svn:keywords set to Author Date Id Revision
File size: 8.0 KB
RevLine 
[1536]1#include "gsManifest.h"
2
3#include <string.h>
4#include <stdio.h>
5
6#include <windows.h>
7
8gsManifest::gsManifest(installManager &manager)
9 : installAgent(manager)
[1539]10{
11 // do nothing!
[1536]12}
13
14gsManifest::gsManifest(installManager &manager, FilePath &root)
15 : installAgent(manager), fileCopyMonitor()
[2534]16{
[1539]17 this->getManifest(root);
18 this->expandGroups();
[1536]19}
20
21bool gsManifest::getManifest(FilePath &root)
[1539]22{
23 FilePath *manifestPath = new FilePath((char *) root.cString(), "manifest.cfg");
24 FILE *file;
25 DWORD fileSize;
26 string currentgroup;
27 char *buffer;
28 char *line;
29 char *eol;
[1536]30
[1539]31 // open file handle for read access
[1536]32 file = fopen(manifestPath->cString(), "rb");
[1539]33 if (file == NULL)
34 {
35 return false;
36 }
[1536]37
38 // get size of file
39 File f(manifestPath->cString());
[1539]40 fileSize = f.getFileSize();
[1536]41
42 // allocate buffer for whole file and read it in
[1539]43 buffer = new char[fileSize];
[1536]44 if (fread(buffer, 1, fileSize, file) < fileSize)
[1539]45 {
46 // TODO: error handling
47 }
[1536]48 fclose(file);
49
50 //parse file into lines and send to the line fn
51 line = buffer;
[1539]52 while ((eol = strchr(line, '\x0a')) != NULL)
53 // use 0a for the eol to remove
54 // dependency on dos 0d,0a eol
55 {
56 *eol = '\0';
[1536]57
[1539]58 this->getManifestLine(line, currentgroup);
[1536]59
[1539]60 line = eol + 1;
61 }
[1536]62 this->getManifestLine(line, currentgroup);
63
[1539]64 delete buffer;
[1536]65 return true;
66}
67
68bool gsManifest::getManifestLine(char *line, string &group)
[1539]69{
70 char *eol; // we (potentially) need to clean up the end of
71 // line, and we won't use the eol from the main
72 // getManifest fn. as for the last line it'd be
73 // null.
[1536]74
[1539]75 // clean up the start of the line
76 while (*line <= ' ' && *line != '\0')
77 {
78 line ++;
79 }
[1536]80
81 // it's a blank line - don't bother!
[1539]82 if (*line == '\0')
83 {
84 return true;
85 }
[1536]86
87 // clean up the end of line
[1539]88 eol = line + strlen(line) - 1;
[1536]89 while (*eol <= ' ' && eol >= line)
[1539]90 {
91 *eol = '\0';
92 eol --;
93 }
[1536]94
95 // does the line end with a colon?; if so take it as a group definition
96 if (*eol == ':')
[1539]97 {
98 if (eol == line) // if it's literally just a colon do nothing
99 {
100 return true;
101 }
102
103 // note the new group name
104 string newgroup(line, 0, eol - line);
105 group = newgroup;
[1536]106 }
107 // if it starts with a hash it's just a comment line; skip it
108 else if (*line == '#')
[1539]109 {
110 // do nothing!
111 }
[1536]112 // an actual line of member items; read them in
113 else
[1539]114 {
115 stringArray array;
116 array = stringArray::words(line);
[1536]117
[1539]118 if (group.length() == 0)
119 {
120 this->manifests["all"].add(array);
121 }
122 else
123 {
124 this->manifests[group].add(array);
125 }
[1536]126 }
127 return true;
128}
129
130/**
131 * Expand all groups
132 */
133void gsManifest::expandGroups()
134{
135 strArrayMap::iterator here = this->manifests.begin();
136 strArrayMap::iterator end = this->manifests.end();
137
138 while (here != end)
139 {
140 this->expandGroup((*here).first);
141 here ++;
142 }
143}
144
145/**
146 * expand a particular group
147 */
148void gsManifest::expandGroup(const string &group)
149{
150 stringArray &array = this->manifests[group];
151
152 unsigned int i = 0;
153 while (i < array.size())
154 {
155 if (this->isGroup(array[i]))
156 {
157 this->expandGroupInstance(group, array[i]);
158 }
159 else
160 {
161 i ++;
162 }
163 }
164}
165
166/**
167 * expand a group instance inside a given group
168 */
169void gsManifest::expandGroupInstance(const string &parentgroup, string groupName)
170{
171 // remove the group instance from the parent
172 this->manifests[parentgroup].remove(groupName);
173
174 // create a "clean" name without the { } brackets
175 string group(groupName, 1, groupName.length() - 2);
176
177 // circular reference - we're kind and ignore it!!
178 if (parentgroup.compare(group) == 0)
179 {
180 return;
181 }
182
183 // lookup chidl group and add it to the parent
184 this->manifests[parentgroup].add(this->manifests[group]);
185}
186
187/**
188 * Check if a member of a group is itself a group - look for { } brackets
189 * around the name
190 */
191bool gsManifest::isGroup(string &name)
192{
193 if (name[0] == '{' && name[name.length()-1] == '}')
194 {
195 return true;
196 }
197 return false;
198}
199
200void gsManifest::expandMacro(string macro, string value)
201{
202 // illegal escape sequence ??
203 // string macroRef = "\$(" + macro + ")";
204 string macroRef = "$(" + macro + ")";
205
206 strArrayMap::iterator here = this->manifests.begin();
[1543]207 strArrayMap::iterator end = this->manifests.end();
[1536]208
209 while (here != end)
210 {
211 stringArray &array = this->manifests[(*here).first];
212
213 unsigned int i = 0;
214 while (i < array.size())
215 {
216 unsigned int pos;
217 while ((pos = array[i].find(macroRef)) < array[i].length() && pos != -1)
218 {
219 array[i].replace(pos, macroRef.length(), value);
220 }
221 i ++;
222 }
223 here ++;
224 }
225}
226
227void gsManifest::clearSelection()
[1539]228{
229 this->selected.empty();
[1536]230}
231
232void gsManifest::selectGroup(string groupName, FilePath &destination)
233{
234 stringArray &groupArray = this->manifests[groupName];
235
[2534]236 this->selected[destination].add(groupArray);
[1536]237
[2534]238 if (groupName == "collection")
239 { FilePath *temp = new FilePath(destination, "\\collect");
240 this->collectRoot = *temp;
241 delete temp;
242 }
[1536]243}
244
245/**
246 * Copy the manifest
247 */
248bool gsManifest::copy(FilePath *source)
[1539]249{
250 fileCopier copy(this);
[1536]251
[1539]252 pathStringArrayMap::iterator here = this->selected.begin();
253 pathStringArrayMap::iterator end = this->selected.end();
[1536]254
255 // add all the sets to copy to the manifest
256 while (here != end)
[1539]257 {
258 FileVector *fileList;
259 stringArray &array = (*here).second;
260 FilePath path((*here).first);
[1536]261
[1539]262 // TODO: eliminate inefficiency; we're doing FilePath->string->FilePath in
263 // effect between constructing the copy lists, and then the sets, as far
264 // as the destinations go
265 fileList = this->selection(*source, array);
[2534]266 fileCopySet copySet("", *fileList, *source, path);
[1539]267 copy.addSet(copySet);
268 delete fileList;
269 here ++;
270 }
[1536]271
272 // check that we've got enough space @ the destination(s)
273 if (!copy.checkSpace())
[1764]274 {
[1539]275 return false;
276 }
[1536]277
278 // do the actual copying
279 copy.copy();
280 return true;
281}
282
[1545]283void gsManifest::copiedFile(string from, string to)
[2534]284{ if (!this->collectRoot.isAncestorOf(to))
285 { this->logAction("Manifest.CopyFile", from, to);
286 }
[1536]287}
288
[2534]289void gsManifest::createdDir(string dirName)
[1545]290{ this->logAction("Manifest.CreateDir", dirName);
291}
292
[2534]293void gsManifest::copiedDir(string dirName)
294{
295 if (!this->collectRoot.isAncestorOf(dirName))
296 { if (this->collectRoot.pathString() == dirName)
297 {
298 this->logAction("Manifest.CopyDir", dirName);
299 }
300 else
301 {
302 this->logAction("Manifest.CreateDir", dirName);
303 }
304 }
305}
306
[1536]307void gsManifest::logAction(string actionName, string file)
[1539]308{
309 unInstallCommand command(actionName);
310 command.addParameter(file);
[1536]311 manager->storeCommand(command);
312}
313
314void gsManifest::logAction(string actionName, string source, string dest)
[1539]315{
316 unInstallCommand command(actionName);
317 command.addParameter(source);
[1536]318 command.addParameter(dest);
319 manager->storeCommand(command);
320}
321
322bool gsManifest::undoAction(string actionName, stringArray &params)
[1539]323{
324 if (actionName == "Manifest.CreateDir" || actionName == "CreateDir")
325 {
[2534]326 if (!RemoveDirectory(params[0].c_str()))
327 {
328 this->removeFailed.add(params[0]);
[2013]329 }
[1539]330 return true;
331 }
[2534]332 else if (actionName == "Manifest.CopyDir")
333 {
334 // do a recursive delete then
335 File f(params[0]);
336 if (!f.remove())
337 {
338 this->removeFailed.add(params[0]);
339 }
340 return true;
341 }
[1536]342 else if (actionName == "Manifest.CopyFile" || actionName == "CopyFile")
[1539]343 {
344 DeleteFile(params[1].c_str());
345 return true;
346 }
[1536]347 return false;
[2013]348}
349
350bool gsManifest::undoFailed(string path)
351{
352 return this->removeFailed.includes(path);
[1536]353}
354
355FileVector *gsManifest::selection(FilePath &root, stringArray &array)
[1539]356{
357 FileVector *reply = new FileVector();
[1536]358
359 for (unsigned int i = 0; i < array.size(); i++)
[1539]360 {
361 FilePath fileName(root.pathString(), array[i]);
362 File file(fileName.pathString());
363 reply->push_back(file);
[1536]364 }
365 return reply;
366}
367
368FileVector *gsManifest::selection(FilePath &source, FilePath &destination)
[1539]369{
370 return this->selection(source, this->selected[destination]);
[1536]371}
372
Note: See TracBrowser for help on using the repository browser.