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
00028
00029
00030 #include <Basics.H>
00031 #include <Text.H>
00032 #include <VestaConfig.H>
00033 #include <VestaSource.H>
00034 #include <VDirSurrogate.H>
00035 #include "ReposUI.H"
00036
00037 #if !defined(__sun__)
00038 extern "C" {
00039 #include <getopt.h>
00040 }
00041 #endif
00042
00043 using std::cout;
00044 using std::cerr;
00045 using std::endl;
00046
00047 enum Recursion {
00048 r_none, r_pkg, r_branch
00049 };
00050
00051 Text program_name, defpkgpar;
00052 int errcount = 0;
00053
00054 void
00055 Usage()
00056 {
00057 cerr << "Usage: " << program_name
00058 << " [-n | -p | -b] [-m] [-t] [-v] [-R repos] [package]" << endl;
00059 exit(1);
00060 }
00061
00062 struct verclosure {
00063 VestaSource* parent;
00064 Text prefix;
00065 Recursion recurse;
00066 bool mast;
00067 int elide;
00068 bool comment;
00069 Text lhost, lport;
00070 };
00071
00072 static bool
00073 vercallback(void* closure, VestaSource::typeTag type, Arc arc,
00074 unsigned int index, Bit32 pseudoInode, ShortId filesid,
00075 bool master);
00076
00077 static void
00078 printwhohas(VestaSource* vs, Text prefix, Recursion recurse,
00079 bool mast, int elide, bool comment, Text lhost, Text lport)
00080 {
00081 verclosure cl;
00082 cl.parent = vs;
00083 cl.prefix = prefix;
00084 cl.recurse = recurse;
00085 cl.mast = mast;
00086 cl.elide = elide;
00087 cl.comment = comment;
00088 cl.lhost = lhost;
00089 cl.lport = lport;
00090 VestaSource::errorCode err = vs->list(0, vercallback, &cl);
00091 if (err != VestaSource::ok) {
00092 cerr << program_name
00093 << ": error listing directory " << cl.prefix << ": "
00094 << ReposUI::errorCodeText(err) << endl;
00095 errcount++;
00096 }
00097 }
00098
00099 static bool
00100 vercallback(void* closure, VestaSource::typeTag type, Arc arc,
00101 unsigned int index, Bit32 pseudoInode, ShortId filesid,
00102 bool master)
00103 {
00104 verclosure* cl = (verclosure*) closure;
00105 char* endptr;
00106 char* v;
00107 VestaSource* vs;
00108
00109 if (cl->mast && !master &&
00110 type != VestaSource::immutableDirectory &&
00111 type != VestaSource::immutableFile) {
00112 try {
00113 vs = ReposUI::filenameToMasterVS(cl->prefix + arc,
00114 cl->parent->host() + ":" +
00115 cl->parent->port() + " " +
00116 cl->lhost + ":" + cl->lport);
00117 } catch (ReposUI::failure f) {
00118 cerr << program_name << ": " << f.msg << endl;
00119 errcount++;
00120 return true;
00121 }
00122 } else {
00123 VestaSource::errorCode err = cl->parent->lookupIndex(index, vs);
00124 if (err != VestaSource::ok) {
00125 cerr << program_name << ": error on lookupIndex: "
00126 << ReposUI::errorCodeText(err) << endl;
00127 errcount++;
00128 return true;
00129 }
00130 }
00131
00132 if (vs->type == VestaSource::stub) {
00133 char* owner = vs->getAttrib("checkout-by");
00134 char* dest = vs->getAttrib("checkout-to");
00135 if (owner) {
00136 cout << cl->prefix.Sub(cl->elide) << arc << " " << owner;
00137 delete owner;
00138 if (dest) {
00139 cout << " " << dest;
00140 delete dest;
00141 }
00142 cout << endl;
00143 if(cl->comment)
00144 {
00145 char* message = vs->getAttrib("message");
00146 if(message)
00147 {
00148 cout << "\t" << message << endl;
00149 delete message;
00150 }
00151 }
00152 }
00153 } else if (vs->type == VestaSource::appendableDirectory) {
00154 if (cl->recurse == r_none) {
00155 delete vs;
00156 return true;
00157 }
00158 if (!vs->inAttribs("type", "checkout") &&
00159 (cl->recurse >= r_branch || !vs->inAttribs("type", "branch"))) {
00160
00161 printwhohas(vs, cl->prefix + arc + "/", cl->recurse,
00162 cl->mast, cl->elide, cl->comment, cl->lhost, cl->lport);
00163 }
00164 }
00165 delete vs;
00166 return true;
00167 }
00168
00169 void
00170 doit(Text pkg, Recursion recurse, bool mast, bool fullpath, bool comment,
00171 Text lhost, Text lport)
00172 {
00173 Text cpkg = ReposUI::canonicalize(pkg, defpkgpar);
00174 VestaSource* vs_pkg;
00175 if (mast) {
00176 vs_pkg = ReposUI::filenameToMasterVS(cpkg, lhost + ":" + lport);
00177 } else {
00178 vs_pkg = ReposUI::filenameToVS(cpkg, lhost, lport);
00179 }
00180
00181
00182 if (vs_pkg->type != VestaSource::appendableDirectory) {
00183
00184 return;
00185 }
00186 if (recurse == r_none && !vs_pkg->inAttribs("type", "package")) {
00187 cerr << program_name << ": " << cpkg << " is not a package" << endl;
00188 errcount++;
00189 return;
00190 }
00191 printwhohas(vs_pkg, cpkg + "/", recurse, mast,
00192 fullpath ? 0 : (cpkg.Length() + 1), comment, lhost, lport);
00193 }
00194
00195 int
00196 main(int argc, char* argv[])
00197 {
00198 program_name = argv[0];
00199 try {
00200
00201
00202
00203 defpkgpar = VestaConfig::get_Text("UserInterface",
00204 "DefaultPackageParent");
00205
00206 Recursion recurse = r_pkg;
00207 bool mast = false;
00208 bool fullpath = true;
00209 bool comment = false;
00210 Text repos;
00211
00212
00213
00214
00215 opterr = 0;
00216 for (;;) {
00217 char* slash;
00218 int c = getopt(argc, argv, "npbmtvR:");
00219 if (c == EOF) break;
00220 switch (c) {
00221 case 'n':
00222 recurse = r_none;
00223 break;
00224 case 'p':
00225 recurse = r_pkg;
00226 break;
00227 case 'b':
00228 recurse = r_branch;
00229 break;
00230 case 'm':
00231 mast = true;
00232 break;
00233 case 't':
00234 fullpath = false;
00235 break;
00236 case 'v':
00237 comment = true;
00238 break;
00239 case 'R':
00240 repos = optarg;
00241 break;
00242 case '?':
00243 default:
00244 Usage();
00245 }
00246 }
00247
00248 Text lhost(VDirSurrogate::defaultHost());
00249 Text lport(VDirSurrogate::defaultPort());
00250 if (repos != "") {
00251 int colon = repos.FindCharR(':');
00252 if (colon == -1) {
00253 lhost = repos;
00254 repos = repos + ":" + lport;
00255 } else {
00256 lhost = repos.Sub(0, colon);
00257 lport = repos.Sub(colon+1);
00258 }
00259 }
00260
00261 if (optind > argc) {
00262 Usage();
00263
00264 }
00265 if (optind == argc) {
00266 doit("/vesta", recurse, mast, fullpath, comment, lhost, lport);
00267 } else {
00268 if (!fullpath) {
00269 cerr << program_name <<
00270 ": only one package allowed with -t flag" << endl;
00271 exit(errcount + 1);
00272 }
00273 while (optind < argc) {
00274 doit(argv[optind++], recurse, mast, fullpath,
00275 comment, lhost, lport);
00276 }
00277 }
00278
00279 } catch (VestaConfig::failure f) {
00280 cerr << program_name << ": " << f.msg << endl;
00281 exit(errcount + 1);
00282 } catch (SRPC::failure f) {
00283 cerr << program_name
00284 << ": SRPC failure; " << f.msg << " (" << f.r << ")" << endl;
00285 exit(errcount + 1);
00286 } catch (ReposUI::failure f) {
00287 cerr << program_name << ": " << f.msg << endl;
00288 exit(errcount + 1);
00289 }
00290 return errcount;
00291 }
00292
00293
00294