00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include <sys/types.h>
00028 #if defined(__linux__) && !defined(__GNUC__)
00029
00030
00031 typedef long int int64_t;
00032 #endif
00033 #include <sys/param.h>
00034 #include <fnmatch.h>
00035 #include <string.h>
00036
00037
00038 #include <Basics.H>
00039 #include <Table.H>
00040 #include <FS.H>
00041 #include <FP.H>
00042 #include <SourceOrDerived.H>
00043 #include <VestaSource.H>
00044 #include <ReadConfig.H>
00045 #include <Debug.H>
00046 #include "PkgBuild.H"
00047 #include "CommonErrors.H"
00048 #include "RootTbl.H"
00049 #include "GatherWeedRoots.H"
00050
00051 using std::ifstream;
00052 using std::cout;
00053 using std::cerr;
00054 using std::endl;
00055
00056
00057 typedef Table<FP::Tag,const PkgBuild*>::Default FPPkgTbl;
00058 typedef Table<FP::Tag,const PkgBuild*>::Iterator FPPkgIter;
00059
00060
00061 static const int MaxPatternLen = MAXPATHLEN;
00062 static const int MaxPathLen = MAXPATHLEN;
00063
00064
00065 static const char *FirstStr = "FIRST";
00066 static const char *LastStr = "LAST";
00067 static const char Pound = '#';
00068 static const char Plus = '+';
00069 static const char Minus = '-';
00070 static const char OpenBracket = '[';
00071 static const char CloseBracket = ']';
00072 static const char Slash = '/';
00073 static const char Null = '\0';
00074 static const char OpenCurly = '{';
00075 static const char CloseCurly = '}';
00076 static const char Comma = ',';
00077 static const FP::Tag EmptyFP("");
00078
00079 enum Op { Add, Remove };
00080
00081
00082
00083
00084 static bool GatherWeedRoots_printModelNames;
00085
00086
00087 static int GatherWeedRoots_instructionModelCnt;
00088
00089
00090 static FPPkgTbl *GatherWeedRoots_pkgTbl = (FPPkgTbl *)NULL;
00091
00092
00093 static VestaSource *GatherWeedRoots_reposRoot = (VestaSource *)NULL;
00094
00095
00096 static Text GatherWeedRoots_rootName;
00097 static int GatherWeedRoots_rootNameLen;
00098
00099 static inline bool IsEmpty(const char *str) throw ()
00100
00101 { return *str == Null; }
00102
00103
00104
00105 static void GatherWeedRoots_MaxPathLenErr() throw ()
00106 {
00107 cerr << "Fatal error: built-in constant 'MaxPathLen' too small; ";
00108 cerr << "exiting..." << endl;
00109 exit(1);
00110 }
00111
00112
00113
00114 static PkgBuild* GatherWeedRoots_GetPkgBuild(VestaSource *vs,
00115 const FP::Tag &parentFP, VestaSource::typeTag parentType)
00116 throw (ReposError, SRPC::failure)
00117
00118
00119
00120
00121 {
00122 if (vs->type != VestaSource::immutableFile
00123 || parentType != VestaSource::immutableDirectory) {
00124 return (PkgBuild *)NULL;
00125 }
00126 ShortId shortId = vs->shortId();
00127 assert(shortId != NullShortId);
00128 return NEW_PTRFREE_CONSTR(PkgBuild, (parentFP, shortId));
00129 }
00130
00131 static void GatherWeedRoots_HandleFile(Op op, VestaSource *vs,
00132 const char *filename, const FP::Tag &parentFP,
00133 VestaSource::typeTag parentType)
00134 throw (ReposError, SRPC::failure)
00135
00136
00137
00138 {
00139 if (GatherWeedRoots_printModelNames) {
00140 cout << " ";
00141 cout << ((op == Add) ? Plus : Minus) << ' ' << filename << endl;
00142 GatherWeedRoots_instructionModelCnt++;
00143 }
00144 FP::Tag fp(filename);
00145 switch (op) {
00146 case Add:
00147
00148 const PkgBuild *pkg;
00149 if (!(GatherWeedRoots_pkgTbl->Get(fp, pkg))) {
00150 pkg = GatherWeedRoots_GetPkgBuild(vs, parentFP, parentType);
00151 if (pkg != (PkgBuild *)NULL) {
00152 bool inTbl = GatherWeedRoots_pkgTbl->Put(fp, pkg);
00153 assert(!inTbl);
00154 } else {
00155 cerr << "Warning: ignoring '" << filename << "'" << endl;
00156 }
00157 }
00158 break;
00159 case Remove:
00160 const PkgBuild *dummy;
00161 (void) GatherWeedRoots_pkgTbl->Delete(fp, dummy);
00162 break;
00163 default:
00164 assert(false);
00165 }
00166 }
00167
00168
00169
00170 static int GatherWeedRoots_DecimalValue( const char* &str,
00171 bool allowSuffix = false) throw ()
00172
00173
00174
00175
00176
00177
00178 {
00179 const char *init = str;
00180 int res = 0;
00181 while (isdigit(*str)) {
00182 res = (10 * res) + (*str++ - '0');
00183 }
00184 if (init == str) return -1;
00185 if (*init == '0' && (str - init) > 1) return -1;
00186 return ((IsEmpty(str) || allowSuffix) ? res : -1);
00187 }
00188
00189 struct FirstLastState {
00190 VestaSource *parentVS;
00191 char *path;
00192 int first;
00193 int last;
00194 };
00195
00196 static bool GatherWeedRoots_FirstLastCallback(void *arg,
00197 VestaSource::typeTag type, Arc arc, unsigned int index,
00198 Bit32 pseudoInode, ShortId filesid, bool master)
00199 throw (ReposError, SRPC::failure)
00200
00201
00202
00203
00204
00205 {
00206 FirstLastState *s = (FirstLastState *)arg;
00207
00208 const char *dummy_name = arc;
00209 int value = GatherWeedRoots_DecimalValue( dummy_name);
00210 if (value >= 0) {
00211
00212 VestaSource *childVS;
00213 VestaSource::errorCode errCode;
00214 errCode = s->parentVS->lookupIndex(index, childVS);
00215 if (errCode != VestaSource::ok) {
00216 throw ReposError(errCode, "VestaSource::lookupIndex", s->path);
00217 }
00218 if (childVS->type == VestaSource::immutableDirectory
00219 || childVS->type == VestaSource::appendableDirectory) {
00220 s->first = (s->first == -1) ? value : min(s->first, value);
00221 s->last = (s->last == -1) ? value : max(s->last, value);
00222 }
00223 }
00224 return true;
00225 }
00226
00227 static void GatherWeedRoots_GetFirstLast(VestaSource *vs, char *path,
00228 int &first, int &last) throw (ReposError, SRPC::failure)
00229
00230
00231
00232
00233 {
00234
00235 FirstLastState s;
00236 s.parentVS = vs;
00237 s.path = path;
00238 s.first = s.last = -1;
00239
00240
00241 VestaSource::errorCode errCode;
00242 errCode = vs->list( 0,
00243 GatherWeedRoots_FirstLastCallback, (void*)(&s));
00244 if (errCode != VestaSource::ok) {
00245 throw ReposError(errCode, "VestaSource::list", path);
00246 }
00247
00248
00249 first = s.first;
00250 last = s.last;
00251 }
00252
00253 static char* GatherWeedRoots_ReplaceFirstLast(VestaSource *vs, char *path,
00254 char *pattern) throw (ReposError, SRPC::failure)
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264 {
00265
00266 if (strstr(pattern, FirstStr) == (char *)NULL &&
00267 strstr(pattern, LastStr) == (char *)NULL)
00268 return pattern;
00269
00270
00271 int first, last;
00272 GatherWeedRoots_GetFirstLast(vs, path, first, last);
00273
00274
00275 Text res;
00276 while (!IsEmpty(pattern)) {
00277
00278 char *firstLoc = strstr(pattern, FirstStr);
00279 char *lastLoc = strstr(pattern, LastStr);
00280
00281
00282 char *minLoc;
00283 if (firstLoc == (char *)NULL) minLoc = lastLoc;
00284 else if (lastLoc == (char *)NULL) minLoc = firstLoc;
00285 else minLoc = (firstLoc < lastLoc) ? firstLoc : lastLoc;
00286
00287
00288 int value = -1, skipLen = 0;
00289 if (minLoc == (char *)NULL) {
00290 minLoc = index(pattern, Null);
00291 } else {
00292 if (minLoc == firstLoc) {
00293 value = first; skipLen = strlen(FirstStr);
00294 } else {
00295 value = last; skipLen = strlen(LastStr);
00296 }
00297 assert(skipLen > 0);
00298 }
00299
00300
00301 if (minLoc > pattern) {
00302 res += Text(pattern, minLoc - pattern);
00303 }
00304 pattern = (minLoc + skipLen);
00305
00306
00307 if (value >= 0) {
00308 char buff[20];
00309 int spres = sprintf(buff, "%d", value);
00310 assert(spres >= 0);
00311 res += buff;
00312 } else if (skipLen > 0) {
00313
00314
00315 res += "_NO_MATCH_";
00316 }
00317 }
00318 return res.chars();
00319 }
00320
00321 static int GatherWeedRoots_ParseExpr( const char* &curr)
00322 throw (InputError)
00323 {
00324 int res, sign = 0;
00325 while (isdigit(*curr)) {
00326
00327 int num =
00328 GatherWeedRoots_DecimalValue( curr, true);
00329 if (num < 0) {
00330 throw InputError("expected number in interval expression");
00331 }
00332
00333
00334 if (sign == 0) res = num;
00335 else res += (sign * num);
00336
00337
00338 if (*curr == Plus) { sign = 1; curr++; }
00339 else if (*curr == Minus) { sign = -1; curr++; }
00340 }
00341 return res;
00342 }
00343
00344 static char* GatherWeedRoots_ReplaceInterval(const char *pattern)
00345 throw (SysError, InputError)
00346
00347
00348
00349
00350 {
00351 Text res;
00352 while (!IsEmpty(pattern)) {
00353 char *intvStart = index(pattern, OpenBracket);
00354 char *intvEnd, *comma;
00355 int low, high;
00356 if (intvStart != (char *)NULL) {
00357 comma = index(intvStart, Comma);
00358 intvEnd = index(intvStart, CloseBracket);
00359
00360 if (comma != NULL && intvEnd != NULL &&
00361 intvStart < comma && comma < intvEnd &&
00362 intvStart+1 != comma && comma != intvEnd-1) {
00363
00364 const char *curr = intvStart + 1;
00365 low = GatherWeedRoots_ParseExpr( curr);
00366 if (*curr++ != Comma) {
00367 throw InputError("expected comma in interval");
00368 }
00369 high = GatherWeedRoots_ParseExpr( curr);
00370 if (*curr++ != CloseBracket) {
00371 throw InputError("expected ']' at end of interval");
00372 }
00373 } else {
00374
00375 if (intvEnd == NULL) {
00376 throw InputError("no matching ']' in pattern");
00377 }
00378 }
00379 } else {
00380 intvStart = index(pattern, Null);
00381 }
00382
00383
00384 if (intvStart > pattern) {
00385 res += Text(pattern, intvStart - pattern);
00386 }
00387
00388
00389 if (IsEmpty(intvStart)) {
00390 pattern = intvStart;
00391 } else {
00392 pattern = intvEnd + 1;
00393 if (low <= high) {
00394
00395 const int MaxNumLen = 20;
00396
00397
00398
00399
00400 char *buff = NEW_PTRFREE_ARRAY(char,
00401 2 + ((MaxNumLen+1) * (high-low+1)));
00402 char *curr = buff;
00403 *curr++ = OpenCurly;
00404 for (int i = low; i <= high; i++) {
00405 char numBuff[MaxNumLen];
00406 int spres = sprintf(numBuff, "%d", i);
00407 assert(spres >= 0);
00408 if (strcpy(curr, numBuff) == NULL)
00409 throw SysError("strcpy(3)");
00410 curr += strlen(numBuff);
00411 if (i < high) *curr++ = Comma;
00412 }
00413 *curr++ = CloseCurly;
00414 res += Text(buff, curr - buff);
00415 } else {
00416
00417 res += "_NO_MATCH_";
00418 }
00419 }
00420 }
00421 return res.chars();
00422 }
00423
00424 static int GatherWeedRoots_CurlyMatchHelper(char *buff, char *end,
00425 const char *pattern, const char *name) throw (InputError, SysError)
00426 {
00427
00428 char *openCurly, *closeCurly;
00429 if ((openCurly = index(pattern, OpenCurly)) == NULL) {
00430 if (strcpy(end, pattern) == NULL) throw SysError("strcpy(3)");
00431 return fnmatch(buff, name, FNM_PERIOD);
00432 }
00433
00434
00435 if ((closeCurly = index(openCurly+1, CloseCurly)) == NULL) {
00436 throw InputError("opening '{' not matched by a closing '}'");
00437 }
00438
00439
00440 int len = openCurly - pattern;
00441 if (strncpy(end, pattern, len) == NULL) throw SysError("strncpy(3)");
00442 end += len;
00443
00444
00445 int res = FNM_NOMATCH;
00446 char *curr;
00447 for (curr = openCurly + 1; (curr-1) != closeCurly; curr++) {
00448 char *wdEnd = index(curr, Comma);
00449 if (wdEnd == (char *)NULL || wdEnd > closeCurly) wdEnd = closeCurly;
00450 int len = wdEnd - curr;
00451 if (strncpy(end, curr, len) == NULL) throw SysError("strncpy(3)");
00452 res = GatherWeedRoots_CurlyMatchHelper(buff,
00453 end + len, closeCurly + 1, name);
00454 if (res != FNM_NOMATCH) return res;
00455 curr = wdEnd;
00456 }
00457 return res;
00458 }
00459
00460 static int GatherWeedRoots_CurlyMatch(const char *pattern, const char *name)
00461 throw (SysError, InputError)
00462
00463
00464
00465
00466
00467 {
00468
00469 if (index(pattern, OpenCurly) == NULL) {
00470 return fnmatch(pattern, name, FNM_PERIOD);
00471 }
00472
00473
00474
00475
00476
00477 char *buff = NEW_PTRFREE_ARRAY(char, strlen(pattern));
00478 return GatherWeedRoots_CurlyMatchHelper(buff, buff, pattern, name);
00479 }
00480
00481
00482
00483
00484 static void GatherWeedRoots_SearchPath(Op op, VestaSource *vs, char *path,
00485 char *end, int rem, char *rest, const FP::Tag &parentFP,
00486 VestaSource::typeTag parentType)
00487 throw (SysError, ReposError, InputError, SRPC::failure);
00488
00489 struct SearchDirState {
00490 Op op;
00491 VestaSource *parentVS;
00492 char *path;
00493 char *end;
00494 int rem;
00495 char *dirPattern;
00496 char *rest;
00497 };
00498
00499 static bool GatherWeedRoots_SearchDirCallback(void *closure,
00500 VestaSource::typeTag type, Arc arc, unsigned int index,
00501 Bit32 pseudoInode, ShortId filesid, bool master)
00502 throw (SysError, ReposError, InputError, SRPC::failure)
00503
00504
00505 {
00506
00507 SearchDirState *s = (SearchDirState *)closure;
00508
00509
00510 int match = GatherWeedRoots_CurlyMatch(s->dirPattern, arc);
00511 switch (match) {
00512 case 0:
00513 {
00514 int namlen = strlen(arc);
00515 if (namlen >= s->rem) GatherWeedRoots_MaxPathLenErr();
00516
00517
00518 if (strcpy(s->end, arc) == (char *)NULL) {
00519 throw SysError("strcpy(3)");
00520 }
00521
00522
00523 VestaSource *childVS;
00524 VestaSource::errorCode errCode;
00525 errCode = s->parentVS->lookupIndex(index, childVS);
00526 if (errCode != VestaSource::ok) {
00527 throw ReposError(errCode, "VestaSource::lookupIndex", s->path);
00528 }
00529
00530
00531 GatherWeedRoots_SearchPath(s->op, childVS, s->path,
00532 s->end + namlen, s->rem - namlen, s->rest, s->parentVS->fptag,
00533 s->parentVS->type);
00534 }
00535 break;
00536 case FNM_NOMATCH:
00537 break;
00538 default:
00539 throw SysError("fnmatch(3)");
00540 }
00541 return true;
00542 }
00543
00544 static void GatherWeedRoots_SearchDir(Op op, VestaSource *vs, char *path,
00545 char *end, int rem, char *rest, const FP::Tag &parentFP)
00546 throw (SysError, ReposError, InputError, SRPC::failure)
00547
00548
00549 {
00550
00551 char *restStart = rest;
00552 char *dirPattern;
00553 if ((rest = index(restStart, Slash)) != NULL) {
00554 int dirPatternLen = rest - restStart;
00555 dirPattern = NEW_PTRFREE_ARRAY(char, dirPatternLen+1);
00556 if (strncpy(dirPattern, restStart, dirPatternLen) == NULL) {
00557 throw SysError("strncpy(3)");
00558 }
00559 dirPattern[dirPatternLen] = Null;
00560 rest++;
00561 } else {
00562 dirPattern = restStart;
00563 rest = restStart + strlen(restStart);
00564 }
00565
00566
00567 dirPattern = GatherWeedRoots_ReplaceFirstLast(vs, path, dirPattern);
00568 dirPattern = GatherWeedRoots_ReplaceInterval(dirPattern);
00569
00570
00571 assert(*(end-1) != Slash);
00572 if (rem == 0) GatherWeedRoots_MaxPathLenErr();
00573 *end++ = Slash; *end = Null;
00574 rem--;
00575
00576
00577 SearchDirState s;
00578 s.op = op;
00579 s.parentVS = vs;
00580 s.path = path;
00581 s.end = end;
00582 s.rem = rem;
00583 s.dirPattern = dirPattern;
00584 s.rest = rest;
00585
00586
00587 VestaSource::errorCode errCode;
00588 errCode = vs->list( 0,
00589 GatherWeedRoots_SearchDirCallback, (void *)(&s));
00590 if (errCode != VestaSource::ok) {
00591 throw ReposError(errCode, "VestaSource::list", path);
00592 }
00593 }
00594
00595 static void GatherWeedRoots_SearchPath(Op op, VestaSource *vs, char *path,
00596 char *end, int rem, char *rest, const FP::Tag &parentFP,
00597 VestaSource::typeTag parentType)
00598 throw (SysError, ReposError, InputError, SRPC::failure)
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611 {
00612 assert(IsEmpty(end) && *(end-1) != Slash);
00613
00614 switch (vs->type) {
00615 case VestaSource::immutableFile:
00616
00617 if (IsEmpty(rest)) {
00618 GatherWeedRoots_HandleFile(op, vs, path, parentFP, parentType);
00619 }
00620 break;
00621 case VestaSource::immutableDirectory:
00622 case VestaSource::appendableDirectory:
00623 GatherWeedRoots_SearchDir(op, vs, path, end, rem, rest, parentFP);
00624 break;
00625 case VestaSource::ghost:
00626 case VestaSource::stub:
00627
00628 break;
00629 default:
00630
00631 cerr << "Warning: ignoring '" << path << "'" << endl;
00632 break;
00633 }
00634 }
00635
00636 static void GatherWeedRoots_ProcessPattern(Op op, char *pattern)
00637 throw (SysError, ReposError, InputError, SRPC::failure)
00638
00639
00640 {
00641
00642 if (GatherWeedRoots_rootNameLen == 0) {
00643 throw InputError("repository root name is empty");
00644 } else if (GatherWeedRoots_rootName[0] != Slash) {
00645 throw InputError("repository root name is not an absolute path");
00646 } else if (GatherWeedRoots_rootNameLen == 1) {
00647 throw InputError("repository root name must be different from '/'");
00648 }
00649
00650
00651 char dir[MaxPathLen];
00652 int rem = MaxPathLen;
00653 char *end = dir;
00654 if (strlen(pattern) > GatherWeedRoots_rootNameLen
00655 && strncmp(pattern, GatherWeedRoots_rootName.cchars(),
00656 GatherWeedRoots_rootNameLen) == 0
00657 && pattern[GatherWeedRoots_rootNameLen] == Slash)
00658 {
00659 strncpy(dir, pattern, GatherWeedRoots_rootNameLen);
00660 end += GatherWeedRoots_rootNameLen;
00661 rem -= GatherWeedRoots_rootNameLen;
00662 pattern += GatherWeedRoots_rootNameLen + 1;
00663 } else {
00664 throw InputError("weeder pattern does not start with repository root");
00665 }
00666 *end = Null;
00667
00668
00669 try {
00670 GatherWeedRoots_SearchPath(op, GatherWeedRoots_reposRoot,
00671 dir, end, rem, pattern, EmptyFP, VestaSource::unused);
00672 }
00673 catch (InputError &err) {
00674
00675 if (err.arg.Empty()) err.arg = pattern;
00676
00677 throw;
00678 }
00679 }
00680
00681
00682
00683 static void GatherWeedRoots_SkipWhite( char* &ptr) throw ()
00684
00685 {
00686 while (*ptr == ' ' || *ptr == '\t') ptr++;
00687 }
00688
00689 static void GatherWeedRoots_GetLine(ifstream &ifs, char *buff, int rem)
00690 throw (FS::Failure)
00691 {
00692 while (rem > 0) {
00693 int c = ifs.get();
00694 if (c == EOF || c == '\n') break;
00695 *buff++ = (char)c;
00696 rem--;
00697 }
00698 if (rem == 0) GatherWeedRoots_MaxPathLenErr();
00699 *buff = Null;
00700 }
00701
00702 static void GatherWeedRoots_ProcessFile(ifstream &ifs)
00703 throw (FS::Failure, SysError, ReposError, InputError, SRPC::failure)
00704
00705
00706
00707 {
00708 while (!FS::AtEOF(ifs)) {
00709
00710 char buff[MaxPatternLen];
00711 GatherWeedRoots_GetLine(ifs, buff, MaxPatternLen);
00712
00713
00714 if (strlen(buff) == 0) continue;
00715 if (strlen(buff) > 0 && buff[0] == Pound) continue;
00716
00717
00718 Op op;
00719 char *curr = buff;
00720 GatherWeedRoots_SkipWhite( curr);
00721 switch (*curr++) {
00722 case Plus:
00723 op = Add;
00724 break;
00725 case Minus:
00726 op = Remove;
00727 break;
00728 default:
00729 throw InputError("model pattern does not start with '+' or '-'");
00730 }
00731 GatherWeedRoots_SkipWhite( curr);
00732 GatherWeedRoots_ProcessPattern(op, curr);
00733 }
00734 }
00735
00736
00737
00738 void GatherWeedRoots::P(char *file, bool echoModels, RootTbl *rootTbl)
00739 throw (SRPC::failure, FS::Failure, FS::DoesNotExist,
00740 InputError, SysError, ReposError)
00741 {
00742
00743 GatherWeedRoots_printModelNames = echoModels;
00744 GatherWeedRoots_pkgTbl = NEW_CONSTR(FPPkgTbl,
00745 ( 500, true));
00746 GatherWeedRoots_reposRoot = VestaSource::repositoryRoot();
00747 assert(GatherWeedRoots_reposRoot->type ==VestaSource::appendableDirectory);
00748 GatherWeedRoots_rootName =
00749 ReadConfig::TextVal("UserInterface", "AppendableRootName");
00750 GatherWeedRoots_rootNameLen = GatherWeedRoots_rootName.Length();
00751
00752
00753 ifstream ifs;
00754 FS::OpenReadOnly(file, ifs);
00755 try {
00756 try {
00757 if (GatherWeedRoots_printModelNames) {
00758 cout << "Models in weeder instructions:" << endl;
00759 GatherWeedRoots_instructionModelCnt = 0;
00760 }
00761 GatherWeedRoots_ProcessFile(ifs);
00762 if (GatherWeedRoots_printModelNames) {
00763 if (GatherWeedRoots_instructionModelCnt == 0) {
00764 cout << " NONE" << endl;
00765 }
00766 cout << endl;
00767 }
00768 } catch (...) {
00769 if (GatherWeedRoots_printModelNames) {
00770 if (GatherWeedRoots_instructionModelCnt == 0) {
00771 cout << " NONE SO FAR" << endl;
00772 }
00773 cout << endl;
00774 }
00775 FS::Close(ifs);
00776 throw;
00777 }
00778 FS::Close(ifs);
00779
00780 if (GatherWeedRoots_pkgTbl != (FPPkgTbl *)NULL) {
00781
00782 FPPkgIter it(GatherWeedRoots_pkgTbl);
00783 FP::Tag fp;
00784 const PkgBuild *pkg;
00785 while (it.Next( fp, pkg)) {
00786 (void) rootTbl->Put(*pkg, false);
00787 }
00788 }
00789
00790 } catch (...) {
00791
00792 GatherWeedRoots_pkgTbl = (FPPkgTbl *)NULL;
00793 GatherWeedRoots_reposRoot = (VestaSource *)NULL;
00794 throw;
00795 }
00796
00797 GatherWeedRoots_pkgTbl = (FPPkgTbl *)NULL;
00798 GatherWeedRoots_reposRoot = (VestaSource *)NULL;
00799 GatherWeedRoots_rootName = "";
00800 }