source: trunk/gsinstaller/gsManifest.cpp@ 2013

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

Updates and fixes to permit removal of the main install directory successfully.

  • Property svn:keywords set to Author Date Id Revision
File size: 7.5 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 // do we really need this twice ??
237 // groupArray = this->manifests[groupName];
238
239 this->selected[destination].add(groupArray);
240}
241
242/**
243 * Copy the manifest
244 */
245bool gsManifest::copy(FilePath *source)
246{
247 fileCopier copy(this);
248
249 pathStringArrayMap::iterator here = this->selected.begin();
250 pathStringArrayMap::iterator end = this->selected.end();
251
252 // add all the sets to copy to the manifest
253 while (here != end)
254 {
255 FileVector *fileList;
256 stringArray &array = (*here).second;
257 FilePath path((*here).first);
258
259 // TODO: eliminate inefficiency; we're doing FilePath->string->FilePath in
260 // effect between constructing the copy lists, and then the sets, as far
261 // as the destinations go
262 fileList = this->selection(*source, array);
263 fileCopySet copySet(*fileList, *source, path);
264 copy.addSet(copySet);
265 delete fileList;
266 here ++;
267 }
268
269 // check that we've got enough space @ the destination(s)
270 if (!copy.checkSpace())
271 {
272 return false;
273 }
274
275 // do the actual copying
276 copy.copy();
277 return true;
278}
279
280void gsManifest::copiedFile(string from, string to)
281{ this->logAction("Manifest.CopyFile", from, to);
282}
283
284void gsManifest::copiedDir(string dirName)
285{ this->logAction("Manifest.CreateDir", dirName);
286}
287
288void gsManifest::logAction(string actionName, string file)
289{
290 unInstallCommand command(actionName);
291 command.addParameter(file);
292 manager->storeCommand(command);
293}
294
295void gsManifest::logAction(string actionName, string source, string dest)
296{
297 unInstallCommand command(actionName);
298 command.addParameter(source);
299 command.addParameter(dest);
300 manager->storeCommand(command);
301}
302
303bool gsManifest::undoAction(string actionName, stringArray &params)
304{
305 if (actionName == "Manifest.CreateDir" || actionName == "CreateDir")
306 {
307 if (!RemoveDirectory(params[0].c_str()))
308 {
309 MessageBox(0, "Remove failed", params[0].c_str(), MB_OK);
310 this->removeFailed.add(params[0]);
311 }
312 return true;
313 }
314 else if (actionName == "Manifest.CopyFile" || actionName == "CopyFile")
315 {
316 DeleteFile(params[1].c_str());
317 return true;
318 }
319 return false;
320}
321
322bool gsManifest::undoFailed(string path)
323{
324 return this->removeFailed.includes(path);
325}
326
327FileVector *gsManifest::selection(FilePath &root, stringArray &array)
328{
329 FileVector *reply = new FileVector();
330
331 for (unsigned int i = 0; i < array.size(); i++)
332 {
333 FilePath fileName(root.pathString(), array[i]);
334 File file(fileName.pathString());
335 reply->push_back(file);
336 }
337 return reply;
338}
339
340FileVector *gsManifest::selection(FilePath &source, FilePath &destination)
341{
342 return this->selection(source, this->selected[destination]);
343}
344
Note: See TracBrowser for help on using the repository browser.