#include "gsManifest.h" #include "fileCopier.h" #include #include #include gsManifest::gsManifest(FilePath &root) { this->getManifest(root); this->expandGroups(); } bool gsManifest::getManifest(FilePath &root) { FilePath *manifestPath = new FilePath((char *) root.cString(), "manifest.cfg"); FILE * file; DWORD fileSize; string currentgroup; char * buffer; char * line; char * eol; // open file handle for read access file = fopen(manifestPath->cString(), "rb"); if (file == NULL) { return false; } // get size of file File f(manifestPath->cString()); fileSize = f.getFileSize(); // allocate buffer for whole file and read it in buffer = new char[fileSize]; if (fread(buffer, 1, fileSize, file) < fileSize) { // TODO: error handling } fclose(file); //parse file into lines and send to the line fn line = buffer; while ((eol = strchr(line, '\x0a')) != NULL) // use 0a for the eol to remove // dependency on dos 0d,0a eol { *eol = '\0'; this->getManifestLine(line, currentgroup); line = eol + 1; } this->getManifestLine(line, currentgroup); delete buffer; return true; } bool gsManifest::getManifestLine(char *line, string &group) { char *eol; // we (potentially) need to clean up the end of // line, and we won't use the eol from the main // getManifest fn. as for the last line it'd be // null. // clean up the start of the line while (*line <= ' ' && *line != '\0') { line ++; } // it's a blank line - don't bother! if (line == '\0') { return true; } // clean up the end of line eol = line + strlen(line) - 1; while (*eol <= ' ' && eol >= line) { *eol = '\0'; eol --; } // does the line end with a colon?; if so take it as a group definition if (*eol == ':') { if (eol == line) // if it's literally just a colon do nothing { return true; } // note the new group name string newgroup(line, 0, eol - line); group = newgroup; } else { stringArray array; array = stringArray::words(line); if (group.length() == 0) { this->manifests["all"].add(array); } else { this->manifests[group].add(array); } } return true; } /** * Expand all groups */ void gsManifest::expandGroups() { strArrayMap::iterator here = this->manifests.begin(); strArrayMap::iterator end = this->manifests.end(); while (here != end) { this->expandGroup((*here).first); here ++; } } /** * expand a particular group */ void gsManifest::expandGroup(string &group) { stringArray &array = this->manifests[group]; unsigned int i = 0; while (i < array.size()) { if (this->isGroup(array[i])) { this->expandGroupInstance(group, array[i]); } else { i ++; } } } /** * expand a group instance inside a given group */ void gsManifest::expandGroupInstance(string parentgroup, string groupName) { // remove the group instance from the parent this->manifests[parentgroup].remove(groupName); // create a "clean" name without the { } brackets string group(groupName, 1, groupName.length() - 2); // circular reference - we're kind and ignore it!! if (parentgroup.compare(group) == 0) { return; } // lookup chidl group and add it to the parent this->manifests[parentgroup].add(this->manifests[group]); } /** * Check if a member of a group is itself a group - look for { } brackets * around the name */ bool gsManifest::isGroup(string &name) { if (name[0] == '{' && name[name.length()-1] == '}') { return true; } return false; } void gsManifest::expandMacro(string macro, string value) { string macroRef = "\$(" + macro + ")"; strArrayMap::iterator here = this->manifests.begin(); strArrayMap::iterator end = this->manifests.end(); while (here != end) { stringArray &array = this->manifests[(*here).first]; unsigned int i = 0; while (i < array.size()) { unsigned int pos; while ((pos = array[i].find(macroRef)) < array[i].length() && pos != -1) { array[i].replace(pos, macroRef.length(), value); } i ++; } here ++; } } void gsManifest::clearSelection() { this->selected.empty(); } void gsManifest::selectGroup(string &groupName, FilePath &destination) { stringArray &groupArray = this->manifests[groupName]; groupArray = this->manifests[groupName]; this->selected[destination].add(groupArray); } bool gsManifest::copy(FilePath *source) { fileCopier copy; pathStringArrayMap::iterator here = this->selected.begin(); pathStringArrayMap::iterator end = this->selected.end(); while (here != end) { FileVector *fileList; stringArray &array = (*here).second; FilePath path((*here).first); // TODO: eliminate inefficiency; we're doing FilePath->string->FilePath in // effect between constructing the copy lists, and then the sets as far // as the destinations go fileList = this->selection(array); fileCopySet copySet(*fileList, *source, path); copy.addSet(copySet); delete fileList; here ++; } if (!copy.checkSpace()) { return false; } copy.copy(); return true; } FileVector *gsManifest::selection(stringArray &array) { FileVector *reply = new FileVector(); for (unsigned int i = 0; i < array.size(); i++) { File file(array[i]); reply->push_back(file); } return reply; } FileVector *gsManifest::selection(FilePath &destination) { return this->selection(this->selected[destination]); }