source: trunk/gsinstaller/gsManifest.cpp@ 1545

Last change on this file since 1545 was 1545, checked in by cs025, 24 years ago

Improved logging of manifest items, tidied the handling of items with extended
paths in the manifest (logging creation of directories on the path); finally
removed some old garbage from gsinstall.cpp.

  • Property svn:keywords set to Author Date Id Revision
File size: 7.2 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 RemoveDirectory(params[0].c_str());
308 return true;
309 }
310 else if (actionName == "Manifest.CopyFile" || actionName == "CopyFile")
311 {
312 DeleteFile(params[1].c_str());
313 return true;
314 }
315 return false;
316}
317
318FileVector *gsManifest::selection(FilePath &root, stringArray &array)
319{
320 FileVector *reply = new FileVector();
321
322 for (unsigned int i = 0; i < array.size(); i++)
323 {
324 FilePath fileName(root.pathString(), array[i]);
325 File file(fileName.pathString());
326 reply->push_back(file);
327 }
328 return reply;
329}
330
331FileVector *gsManifest::selection(FilePath &source, FilePath &destination)
332{
333 return this->selection(source, this->selected[destination]);
334}
335
Note: See TracBrowser for help on using the repository browser.