source: trunk/gsinstaller/gsManifest.cpp@ 1397

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

Initial revision

  • Property svn:keywords set to Author Date Id Revision
File size: 5.6 KB
Line 
1#include "gsManifest.h"
2#include "fileCopier.h"
3
4#include <string.h>
5#include <stdio.h>
6
7#include <windows.h>
8
9gsManifest::gsManifest(FilePath &root)
10{ this->getManifest(root);
11 this->expandGroups();
12}
13
14bool gsManifest::getManifest(FilePath &root)
15{ FilePath *manifestPath = new FilePath((char *) root.cString(), "manifest.cfg");
16 FILE * file;
17 DWORD fileSize;
18 string currentgroup;
19 char * buffer;
20 char * line;
21 char * eol;
22
23 // open file handle for read access
24 file = fopen(manifestPath->cString(), "rb");
25 if (file == NULL)
26 { return false;
27 }
28
29 // get size of file
30 File f(manifestPath->cString());
31 fileSize = f.getFileSize();
32
33 // allocate buffer for whole file and read it in
34 buffer = new char[fileSize];
35 if (fread(buffer, 1, fileSize, file) < fileSize)
36 { // TODO: error handling
37 }
38 fclose(file);
39
40 //parse file into lines and send to the line fn
41 line = buffer;
42 while ((eol = strchr(line, '\x0a')) != NULL) // use 0a for the eol to remove
43 // dependency on dos 0d,0a eol
44 { *eol = '\0';
45
46 this->getManifestLine(line, currentgroup);
47
48 line = eol + 1;
49 }
50 this->getManifestLine(line, currentgroup);
51
52 delete buffer;
53 return true;
54}
55
56bool gsManifest::getManifestLine(char *line, string &group)
57{ char *eol; // we (potentially) need to clean up the end of
58 // line, and we won't use the eol from the main
59 // getManifest fn. as for the last line it'd be
60 // null.
61
62 // clean up the start of the line
63 while (*line <= ' ' && *line != '\0')
64 { line ++;
65 }
66
67 // it's a blank line - don't bother!
68 if (line == '\0')
69 { return true;
70 }
71
72 // clean up the end of line
73 eol = line + strlen(line) - 1;
74 while (*eol <= ' ' && eol >= line)
75 { *eol = '\0';
76 eol --;
77 }
78
79 // does the line end with a colon?; if so take it as a group definition
80 if (*eol == ':')
81 { if (eol == line) // if it's literally just a colon do nothing
82 { return true;
83 }
84
85 // note the new group name
86 string newgroup(line, 0, eol - line);
87 group = newgroup;
88 }
89 else
90 { stringArray array;
91 array = stringArray::words(line);
92
93 if (group.length() == 0)
94 { this->manifests["all"].add(array);
95 }
96 else
97 { this->manifests[group].add(array);
98 }
99 }
100 return true;
101}
102
103/**
104 * Expand all groups
105 */
106void gsManifest::expandGroups()
107{ strArrayMap::iterator here = this->manifests.begin();
108 strArrayMap::iterator end = this->manifests.end();
109
110 while (here != end)
111 { this->expandGroup((*here).first);
112 here ++;
113 }
114}
115
116/**
117 * expand a particular group
118 */
119void gsManifest::expandGroup(string &group)
120{ stringArray &array = this->manifests[group];
121
122 unsigned int i = 0;
123 while (i < array.size())
124 { if (this->isGroup(array[i]))
125 { this->expandGroupInstance(group, array[i]);
126 }
127 else
128 { i ++;
129 }
130 }
131}
132
133/**
134 * expand a group instance inside a given group
135 */
136void gsManifest::expandGroupInstance(string parentgroup, string groupName)
137{ // remove the group instance from the parent
138 this->manifests[parentgroup].remove(groupName);
139
140 // create a "clean" name without the { } brackets
141 string group(groupName, 1, groupName.length() - 2);
142
143 // circular reference - we're kind and ignore it!!
144 if (parentgroup.compare(group) == 0)
145 { return;
146 }
147
148 // lookup chidl group and add it to the parent
149 this->manifests[parentgroup].add(this->manifests[group]);
150}
151
152/**
153 * Check if a member of a group is itself a group - look for { } brackets
154 * around the name
155 */
156bool gsManifest::isGroup(string &name)
157{ if (name[0] == '{' && name[name.length()-1] == '}')
158 { return true;
159 }
160 return false;
161}
162
163void gsManifest::expandMacro(string macro, string value)
164{ string macroRef = "\$(" + macro + ")";
165
166 strArrayMap::iterator here = this->manifests.begin();
167 strArrayMap::iterator end = this->manifests.end();
168
169 while (here != end)
170 { stringArray &array = this->manifests[(*here).first];
171
172 unsigned int i = 0;
173 while (i < array.size())
174 { unsigned int pos;
175 while ((pos = array[i].find(macroRef)) < array[i].length() && pos != -1)
176 { array[i].replace(pos, macroRef.length(), value);
177 }
178 i ++;
179 }
180 here ++;
181 }
182}
183
184void gsManifest::clearSelection()
185{ this->selected.empty();
186}
187
188void gsManifest::selectGroup(string &groupName, FilePath &destination)
189{ stringArray &groupArray = this->manifests[groupName];
190
191 groupArray = this->manifests[groupName];
192 this->selected[destination].add(groupArray);
193}
194
195bool gsManifest::copy(FilePath *source)
196{ fileCopier copy;
197
198 pathStringArrayMap::iterator here = this->selected.begin();
199 pathStringArrayMap::iterator end = this->selected.end();
200
201 while (here != end)
202 { FileVector *fileList;
203 stringArray &array = (*here).second;
204 FilePath path((*here).first);
205
206 // TODO: eliminate inefficiency; we're doing FilePath->string->FilePath in
207 // effect between constructing the copy lists, and then the sets as far
208 // as the destinations go
209 fileList = this->selection(array);
210 fileCopySet copySet(*fileList, *source, path);
211 copy.addSet(copySet);
212 delete fileList;
213 here ++;
214 }
215
216 if (!copy.checkSpace())
217 { return false;
218 }
219 copy.copy();
220 return true;
221}
222
223FileVector *gsManifest::selection(stringArray &array)
224{ FileVector *reply = new FileVector();
225
226 for (unsigned int i = 0; i < array.size(); i++)
227 { File file(array[i]);
228 reply->push_back(file);
229 }
230 return reply;
231}
232
233FileVector *gsManifest::selection(FilePath &destination)
234{ return this->selection(this->selected[destination]);
235}
236
Note: See TracBrowser for help on using the repository browser.