source: other-projects/gs2-export-cdrom-installer/trunk/gsManifest.cpp@ 28892

Last change on this file since 28892 was 11664, checked in by mdewsnip, 18 years ago

Fixed the line endings... for real this time, I hope.

  • Property svn:keywords set to Author Date Id Revision
File size: 8.0 KB
Line 
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)
10{
11 // do nothing!
12}
13
14gsManifest::gsManifest(installManager &manager, FilePath &root)
15 : installAgent(manager), fileCopyMonitor()
16{
17 this->getManifest(root);
18 this->expandGroups();
19}
20
21bool gsManifest::getManifest(FilePath &root)
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;
30
31 // open file handle for read access
32 file = fopen(manifestPath->cString(), "rb");
33 if (file == NULL)
34 {
35 return false;
36 }
37
38 // get size of file
39 File f(manifestPath->cString());
40 fileSize = f.getFileSize();
41
42 // allocate buffer for whole file and read it in
43 buffer = new char[fileSize];
44 if (fread(buffer, 1, fileSize, file) < fileSize)
45 {
46 // TODO: error handling
47 }
48 fclose(file);
49
50 //parse file into lines and send to the line fn
51 line = buffer;
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';
57
58 this->getManifestLine(line, currentgroup);
59
60 line = eol + 1;
61 }
62 this->getManifestLine(line, currentgroup);
63
64 delete buffer;
65 return true;
66}
67
68bool gsManifest::getManifestLine(char *line, string &group)
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.
74
75 // clean up the start of the line
76 while (*line <= ' ' && *line != '\0')
77 {
78 line ++;
79 }
80
81 // it's a blank line - don't bother!
82 if (*line == '\0')
83 {
84 return true;
85 }
86
87 // clean up the end of line
88 eol = line + strlen(line) - 1;
89 while (*eol <= ' ' && eol >= line)
90 {
91 *eol = '\0';
92 eol --;
93 }
94
95 // does the line end with a colon?; if so take it as a group definition
96 if (*eol == ':')
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;
106 }
107 // if it starts with a hash it's just a comment line; skip it
108 else if (*line == '#')
109 {
110 // do nothing!
111 }
112 // an actual line of member items; read them in
113 else
114 {
115 stringArray array;
116 array = stringArray::words(line);
117
118 if (group.length() == 0)
119 {
120 this->manifests["all"].add(array);
121 }
122 else
123 {
124 this->manifests[group].add(array);
125 }
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();
207 strArrayMap::iterator end = this->manifests.end();
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()
228{
229 this->selected.empty();
230}
231
232void gsManifest::selectGroup(string groupName, FilePath &destination)
233{
234 stringArray &groupArray = this->manifests[groupName];
235
236 this->selected[destination].add(groupArray);
237
238 if (groupName == "collection")
239 { FilePath *temp = new FilePath(destination, "\\collect");
240 this->collectRoot = *temp;
241 delete temp;
242 }
243}
244
245/**
246 * Copy the manifest
247 */
248bool gsManifest::copy(FilePath *source)
249{
250 fileCopier copy(this);
251
252 pathStringArrayMap::iterator here = this->selected.begin();
253 pathStringArrayMap::iterator end = this->selected.end();
254
255 // add all the sets to copy to the manifest
256 while (here != end)
257 {
258 FileVector *fileList;
259 stringArray &array = (*here).second;
260 FilePath path((*here).first);
261
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);
266 fileCopySet copySet("", *fileList, *source, path);
267 copy.addSet(copySet);
268 delete fileList;
269 here ++;
270 }
271
272 // check that we've got enough space @ the destination(s)
273 if (!copy.checkSpace())
274 {
275 return false;
276 }
277
278 // do the actual copying
279 copy.copy();
280 return true;
281}
282
283void gsManifest::copiedFile(string from, string to)
284{ if (!this->collectRoot.isAncestorOf(to))
285 { this->logAction("Manifest.CopyFile", from, to);
286 }
287}
288
289void gsManifest::createdDir(string dirName)
290{ this->logAction("Manifest.CreateDir", dirName);
291}
292
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
307void gsManifest::logAction(string actionName, string file)
308{
309 unInstallCommand command(actionName);
310 command.addParameter(file);
311 manager->storeCommand(command);
312}
313
314void gsManifest::logAction(string actionName, string source, string dest)
315{
316 unInstallCommand command(actionName);
317 command.addParameter(source);
318 command.addParameter(dest);
319 manager->storeCommand(command);
320}
321
322bool gsManifest::undoAction(string actionName, stringArray &params)
323{
324 if (actionName == "Manifest.CreateDir" || actionName == "CreateDir")
325 {
326 if (!RemoveDirectory(params[0].c_str())) { this->removeFailed.add(params[0]); }
327 return true;
328 }
329 else if (actionName == "Manifest.CopyDir")
330 {
331 // do a recursive delete then
332 File f(params[0]);
333 if (!f.remove())
334 {
335 this->removeFailed.add(params[0]); }
336 return true;
337 }
338 else if (actionName == "Manifest.CopyFile" || actionName == "CopyFile")
339 {
340 DeleteFile(params[1].c_str());
341 return true;
342 }
343 return false;
344}
345
346bool gsManifest::undoFailed(string path)
347{
348 return this->removeFailed.includes(path);
349}
350
351FileVector *gsManifest::selection(FilePath &root, stringArray &array)
352{
353 FileVector *reply = new FileVector();
354
355 for (unsigned int i = 0; i < array.size(); i++)
356 {
357 FilePath fileName(root.pathString(), array[i]);
358 File file(fileName.pathString());
359 reply->push_back(file);
360 }
361 return reply;
362}
363
364FileVector *gsManifest::selection(FilePath &source, FilePath &destination)
365{
366 return this->selection(source, this->selected[destination]);
367}
368
Note: See TracBrowser for help on using the repository browser.