source: trunk/gsinstaller/gsManifest.cpp@ 1537

Last change on this file since 1537 was 1536, checked in by sjboddie, 24 years ago

Changes to get compiling on VC++ and gcc

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