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 #include <sys/types.h>
00026 #if defined(__linux__) && !defined(__GNUC__)
00027
00028
00029 typedef long int int64_t;
00030 #endif
00031 #include <string.h>
00032 #include <dirent.h>
00033 #include <Basics.H>
00034 #include <Table.H>
00035 #include <SourceOrDerived.H>
00036 #include <VestaSource.H>
00037 #include <ReadConfig.H>
00038 #include <Debug.H>
00039 #include "PkgBuild.H"
00040 #include "Pathname.H"
00041 #include "CommonErrors.H"
00042 #include "ReposRoots.H"
00043
00044 using std::cout;
00045 using std::endl;
00046
00047
00048 static const char Slash = '/';
00049 static const char Null = '\0';
00050
00051
00052 static void ReposRoots_SearchRepos(VestaSource *reposDir, Pathname::T pathT,
00053 PkgTbl *pkgTbl) throw (SRPC::failure, ReposError);
00054
00055 static bool ReposRoots_ValidFilename(Arc arc) throw ()
00056
00057 {
00058 static const char *ext = ".ves";
00059 static const int extLen = strlen(ext);
00060
00061 int len = strlen(arc);
00062 if (len <= extLen) return false;
00063 return (strncmp(arc + (len - extLen), ext, extLen) == 0);
00064 }
00065
00066 struct CallbackArgs {
00067 VestaSource *parent;
00068 Pathname::T parentPath;
00069 PkgTbl *pkgTbl;
00070 };
00071
00072 static bool ReposRoots_DirCallback(void *closure, VestaSource::typeTag type,
00073 Arc arc, unsigned int index, Bit32 pseudoInode,
00074 ShortId filesid, bool master)
00075 throw (SRPC::failure, ReposError)
00076 {
00077 CallbackArgs *args = (CallbackArgs *)closure;
00078 VestaSource::errorCode errCode;
00079
00080
00081 switch (type) {
00082 case VestaSource::immutableFile:
00083
00084 if (args->parent->type == VestaSource::immutableDirectory
00085 && ReposRoots_ValidFilename(arc)) {
00086
00087 PkgBuild pkgBuild(args->parent->fptag, filesid);
00088 Pathname::T newPathT = Pathname::New(args->parentPath, arc);
00089
00090
00091 (void) args->pkgTbl->Put(pkgBuild, newPathT);
00092 }
00093 break;
00094 case VestaSource::appendableDirectory:
00095 case VestaSource::immutableDirectory:
00096
00097 VestaSource *dir;
00098 errCode = args->parent->lookupIndex(index, dir);
00099 if (errCode != VestaSource::ok) {
00100 throw ReposError(errCode, "VestaSource::lookupIndex");
00101 }
00102
00103
00104 Pathname::T newPathT = Pathname::New(args->parentPath, arc);
00105
00106
00107 ReposRoots_SearchRepos(dir, newPathT, args->pkgTbl);
00108 break;
00109 }
00110 return true;
00111 }
00112
00113 static void ReposRoots_SearchRepos(VestaSource *reposDir, Pathname::T pathT,
00114 PkgTbl *pkgTbl) throw (SRPC::failure, ReposError)
00115
00116
00117
00118
00119
00120
00121 {
00122
00123 if (reposDir->type == VestaSource::immutableDirectory) {
00124 PkgBuild pkgBuild(reposDir->fptag, NullShortId);
00125 (void) pkgTbl->Put(pkgBuild, pathT);
00126 } else {
00127 assert(reposDir->type == VestaSource::appendableDirectory);
00128 }
00129
00130
00131 CallbackArgs args;
00132 args.parent = reposDir;
00133 args.parentPath = pathT;
00134 args.pkgTbl = pkgTbl;
00135
00136 VestaSource::errorCode errCode;
00137 errCode = reposDir->list( 0,
00138 ReposRoots_DirCallback, (void *)(&args));
00139 if (errCode != VestaSource::ok) {
00140 throw ReposError(errCode, "VestaSource::list");
00141 }
00142 }
00143
00144 PkgTbl *ReposRoots::Scan(bool debug) throw (SRPC::failure, ReposError)
00145 {
00146
00147 if (debug) {
00148 cout << Debug::Timestamp() << "Starting repository scan" << endl;
00149 cout << endl;
00150 }
00151
00152
00153 PkgTbl *res = NEW_CONSTR(PkgTbl, ( 2000, true));
00154
00155
00156 VestaSource *reposRoot = VestaSource::repositoryRoot();
00157 assert(reposRoot->type == VestaSource::appendableDirectory);
00158
00159
00160 Text rootName(ReadConfig::TextVal("UserInterface", "AppendableRootName"));
00161 int rootNameLen = rootName.Length();
00162 Pathname::T rootPathT = Pathname::New(-1, rootName.chars());
00163
00164
00165 ReposRoots_SearchRepos(reposRoot, rootPathT, res);
00166
00167
00168 if (debug) {
00169 cout << Debug::Timestamp() << "Finished repository scan" << endl;
00170 cout << " total models found = " << res->Size() << endl;
00171 cout << endl;
00172 }
00173 return res;
00174 }