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 #include <Basics.H>
00027 #include <Text.H>
00028 #include <VestaConfig.H>
00029 #include <VestaSource.H>
00030 #include <VDirSurrogate.H>
00031 #include <VestaSourceAtomic.H>
00032 #include "ReposUI.H"
00033 #include <Units.H>
00034
00035 #if !defined(__sun__)
00036 extern "C" {
00037 #include <getopt.h>
00038 }
00039 #endif
00040
00041 using std::cout;
00042 using std::cerr;
00043 using std::endl;
00044
00045 Text program_name;
00046 const unsigned long MAXUL = (0UL - 1UL);
00047 const Text default_junk = "*~ .*~ core";
00048 const unsigned long default_maxsize = 1024*1024;
00049
00050 void
00051 usage()
00052 {
00053 cerr << "Usage: " << program_name << endl <<
00054 " [-q] [-Q] [-f]" << endl <<
00055 " [-F fp-content]" << endl <<
00056 " [-j junk | -J]" << endl <<
00057 " [-z maxsize | -Z]" << endl <<
00058 " [-s session-dir]" << endl <<
00059 " [-a session-ver-arc]" << endl <<
00060 " [-R repos]" << endl <<
00061 " [ [-w] work-dir]" << endl << endl;
00062 exit(1);
00063 }
00064
00065 void fix_work_dir_attrib(const Text &cworkdir, const Text &ctarget,
00066 VestaSource *vs_target)
00067 {
00068
00069 char *workdir_val = vs_target->getAttrib("work-dir");
00070
00071
00072 if((workdir_val == 0) || (cworkdir != workdir_val))
00073 {
00074 VestaSource::errorCode err =
00075 vs_target->setAttrib("work-dir", cworkdir.cchars());
00076 if(err != VestaSource::ok)
00077 {
00078
00079 cerr << program_name
00080 << ": WARNING: the 'work-dir' attribute on " << ctarget
00081 << " seems incorrect (maybe you renamed ";
00082 if(workdir_val != 0)
00083 cerr << workdir_val << " to ";
00084 cerr << cworkdir << "?) and correcting it failed: "
00085 << ReposUI::errorCodeText(err) << endl;
00086 }
00087 }
00088
00089 if(workdir_val != 0)
00090 delete [] workdir_val;
00091 }
00092
00093 void fix_work_dir_attrib(const Text &cworkdir, const Text &ctarget,
00094 const Text &lhost, const Text &lport)
00095 {
00096 VestaSource *vs_target;
00097 try
00098 {
00099 vs_target = ReposUI::filenameToVS(ctarget, lhost, lport);
00100 }
00101 catch(ReposUI::failure)
00102 {
00103
00104
00105
00106 return;
00107 }
00108 fix_work_dir_attrib(cworkdir, ctarget, vs_target);
00109 delete vs_target;
00110 }
00111
00112 int
00113 main(int argc, char* argv[])
00114 {
00115 program_name = argv[0];
00116 try {
00117
00118
00119
00120 Text defpkgpar, defworkpar;
00121 defpkgpar = VestaConfig::get_Text("UserInterface",
00122 "DefaultPackageParent");
00123 defworkpar = VestaConfig::get_Text("UserInterface",
00124 "DefaultWorkParent");
00125 Text lhost(VDirSurrogate::defaultHost());
00126 Text lport(VDirSurrogate::defaultPort());
00127 time_t now = time(NULL);
00128 Text cuser(AccessControl::self()->user());
00129 Text user(cuser.Sub(0, cuser.FindChar('@')));
00130 Text workdir, sessdir, sessverarc, repos;
00131 bool default_workdir = true, default_sessdir = true;
00132 bool default_sessverarc = true, default_repos = true;
00133 bool quiet = false, query = false, force = false;
00134 bool test = false;
00135 int c;
00136 VestaSource::errorCode err;
00137 unsigned int fp_content = VestaConfig::get_int("UserInterface",
00138 "FpContent");
00139 Text junk = default_junk;
00140 VestaConfig::get("UserInterface", "vadvance_junk", junk);
00141 unsigned long maxsize = default_maxsize;
00142 Text t;
00143 if (VestaConfig::get("UserInterface", "vadvance_maxsize", t)) {
00144 try
00145 {
00146 maxsize = Basics::ParseUnitVal(t);
00147 }
00148 catch(Basics::ParseUnitValFailure f)
00149 {
00150 cerr << program_name << ": Error parsing [UserInterface]vadvance_maxsize setting: " << f.emsg << endl
00151 << "\tUsing default value (" + Basics::FormatUnitVal(maxsize) + ")" << endl;
00152 }
00153 }
00154
00155
00156
00157
00158 opterr = 0;
00159 for (;;) {
00160 c = getopt(argc, argv, "tqQfF:j:Jz:Zw:s:a:R:");
00161 if (c == EOF) break;
00162 switch (c) {
00163 case 't':
00164 test = true;
00165 query = true;
00166 break;
00167 case 'q':
00168 quiet = true;
00169 break;
00170 case 'Q':
00171 query = true;
00172 break;
00173 case 'f':
00174 force = true;
00175 break;
00176 case 'F':
00177 fp_content = strtol(optarg, 0, 0);
00178 break;
00179 case 'j':
00180 junk = optarg;
00181 break;
00182 case 'J':
00183 junk = "";
00184 break;
00185 case 'z':
00186 maxsize = Basics::ParseUnitVal(optarg);
00187 break;
00188 case 'Z':
00189 maxsize = MAXUL;
00190 break;
00191 case 'w':
00192 workdir = optarg;
00193 default_workdir = false;
00194 break;
00195 case 's':
00196 sessdir = optarg;
00197 default_sessdir = false;
00198 break;
00199 case 'a':
00200 sessverarc = optarg;
00201 default_sessverarc = false;
00202 break;
00203 case 'R':
00204 repos = optarg;
00205 default_repos = false;
00206 break;
00207 case '?':
00208 default:
00209 usage();
00210 }
00211 }
00212
00213 switch (argc - optind) {
00214 case 1:
00215 if (default_workdir) {
00216 workdir = argv[optind];
00217 default_workdir = false;
00218 }
00219 break;
00220 case 0:
00221 break;
00222 default:
00223 usage();
00224
00225 }
00226
00227
00228
00229
00230 if (!default_repos) {
00231 int colon = repos.FindCharR(':');
00232 if (colon == -1) {
00233 lhost = repos;
00234 repos = repos + ":" + lport;
00235 } else {
00236 lhost = repos.Sub(0, colon);
00237 lport = repos.Sub(colon+1);
00238 }
00239 }
00240
00241
00242
00243
00244
00245 if (default_workdir) {
00246 workdir = ".";
00247 }
00248 Text cworkdir = ReposUI::canonicalize(workdir, defworkpar + "/" + user);
00249 VestaSource* vs_workdir = ReposUI::filenameToVS(cworkdir, lhost, lport);
00250
00251 Text csessdir;
00252 if (default_sessdir) {
00253
00254 char* attribval = vs_workdir->getAttrib("session-dir");
00255 if (attribval == NULL) {
00256 cerr << program_name << ": " << cworkdir
00257 << " is not a session working directory" << endl;
00258 exit(2);
00259 }
00260 sessdir = attribval;
00261 csessdir = ReposUI::canonicalize(attribval);
00262 delete attribval;
00263 } else {
00264 csessdir = ReposUI::canonicalize(sessdir, defpkgpar);
00265 }
00266 VestaSource* vs_sessdir = ReposUI::filenameToVS(csessdir, lhost, lport);
00267
00268
00269 Text prev_sessverarc;
00270 long high = ReposUI::highver(vs_sessdir);
00271 if (high < 0) high = 0;
00272 char buf[64];
00273 sprintf(buf, "%ld", high);
00274 prev_sessverarc = buf;
00275 if (default_sessverarc) {
00276
00277 char buf[64];
00278 sprintf(buf, "%ld", high + 1);
00279 sessverarc = buf;
00280 }
00281 Text csessver = csessdir + "/" + sessverarc;
00282
00283
00284 if (!force) {
00285 if (!vs_sessdir->inAttribs("type", "session")) {
00286 cerr << program_name << ": " << csessdir
00287 << " is not a session directory" << endl;
00288 exit(2);
00289 }
00290 }
00291
00292 if (!query && (junk != "" || maxsize != MAXUL)) {
00293 ReposUI::cleanup(vs_workdir, junk, maxsize, cworkdir);
00294 }
00295
00296 if(!query)
00297 {
00298
00299
00300
00301
00302 fix_work_dir_attrib(cworkdir, csessdir, vs_sessdir);
00303 char *cnewver = vs_workdir->getAttrib("new-version");
00304 if(cnewver != 0)
00305 {
00306 fix_work_dir_attrib(cworkdir, cnewver, lhost,lport);
00307 delete [] cnewver;
00308 }
00309 }
00310
00311 if (!force) {
00312
00313
00314 if (!ReposUI::changed(vs_workdir, vs_sessdir->timestamp())) {
00315 if (!quiet) {
00316 cout << "Unchanged from "
00317 << csessdir << "/" << prev_sessverarc << endl;
00318 exit(0);
00319 }
00320 }
00321 }
00322
00323 if (!quiet) {
00324 cout << "Advancing to " << csessver << endl;
00325 }
00326
00327 if (query) {
00328 if (!quiet) {
00329 cerr << program_name << ": nothing done (-Q or -t flag given)" << endl;
00330 }
00331 if (test) {
00332 exit(255);
00333 } else {
00334 exit(0);
00335 }
00336 }
00337
00338 if (fp_content) {
00339
00340 err = vs_workdir->makeFilesImmutable(fp_content);
00341 if (err != VestaSource::ok) {
00342 cerr << program_name
00343 << ": error in makeFilesImmutable: "
00344 << ReposUI::errorCodeText(err) << endl;
00345 exit(2);
00346 }
00347 }
00348
00349
00350
00351
00352 VestaSourceAtomic vsa(lhost, lport);
00353
00354
00355 VestaSourceAtomic::VSIndex vsi_sessdir = vsa.decl(csessdir, vs_sessdir);
00356 vsa.testMaster(csessdir, vsi_sessdir, true, VestaSource::notMaster);
00357
00358
00359
00360 VestaSourceAtomic::VSIndex vsi_workdir = vsa.decl(cworkdir, vs_workdir);
00361 vsa.accessCheck(cworkdir, vsi_workdir, AccessControl::write,
00362 true, VestaSource::noPermission);
00363
00364
00365
00366
00367 vsa.insertImmutableDirectory(csessver, vsi_sessdir, sessverarc,
00368 vsi_workdir, true, VestaSource::dontReplace);
00369
00370
00371 vsa.setAttrib(cworkdir, vsi_workdir, "session-ver-arc", sessverarc);
00372
00373
00374 if (!vsa.run()) {
00375 VestaSource::errorCode err;
00376 if (vsa.lasterr == VestaSource::ok) {
00377 err = vsa.okreplace;
00378 } else {
00379 err = vsa.lasterr;
00380 }
00381 cerr << program_name << ": " << vsa.name(vsa.ndone) << ": "
00382 << ReposUI::errorCodeText(err) << endl;
00383 exit(2);
00384 }
00385
00386 } catch (VestaConfig::failure f) {
00387 cerr << program_name << ": " << f.msg << endl;
00388 exit(2);
00389 } catch (SRPC::failure f) {
00390 cerr << program_name
00391 << ": SRPC failure; " << f.msg << " (" << f.r << ")" << endl;
00392 exit(2);
00393 } catch (ReposUI::failure f) {
00394 cerr << program_name << ": " << f.msg << endl;
00395 if(f.msg.FindText("max file size") > 0)
00396 {
00397 cerr << "\tUse '-z maxsize' to override or '-Z' to disable" << endl;
00398 }
00399 exit(2);
00400 } catch(Basics::ParseUnitValFailure f) {
00401 cerr << program_name << ": " << f.emsg << endl;
00402 exit(2);
00403 }
00404
00405 return 0;
00406 }