42 static void DefaultLogger(
const char *msg) { Printf(
"%s", msg); }
44 THashList *TPackMgr::fgGlobalPackMgrList = 0;
49 TPackMgr::TPackMgr(
const char *dir,
const char *key)
50 : fLogger(DefaultLogger), fName(key), fDir(dir), fLock(dir), fEnabledPackages(0)
53 if (gSystem->ExpandPathName(fDir))
54 Warning(
"TPackMgr",
"problems expanding path '%s'", fDir.Data());
56 TString lockname = TString::Format(
"%s/packdir-lock-%s",
57 gSystem->TempDirectory(), TString(fDir).ReplaceAll(
"/",
"%").Data());
58 fLock.SetName(lockname);
67 if (fEnabledPackages)
delete fEnabledPackages;
73 void TPackMgr::Log(
const char *msg)
79 (*fLogger)(TString::Format(
"%s: %s", fPfx.Data(), msg));
87 Int_t TPackMgr::Build(
const char *pack, Int_t opt)
91 TLockPathGuard lp(&fLock);
94 Info(
"Build",
"building package %s ...", pack);
96 TString ocwd = gSystem->WorkingDirectory();
97 TString pdir = TString::Format(
"%s/%s", fDir.Data(), pack);
98 gSystem->ChangeDirectory(pdir);
101 if (!gSystem->AccessPathName(
"PROOF-INF/BUILD.sh")) {
103 Log(TString::Format(
"building %s ...", pack));
107 Bool_t goodver = kTRUE;
108 Bool_t savever = kFALSE;
110 FILE *f = fopen(
"PROOF-INF/proofvers.txt",
"r");
115 if (opt == TPackMgr::kCheckROOT && v != gROOT->GetVersion()) goodver = kFALSE;
117 if (!f || !goodver) {
118 if (!gSystem->AccessPathName(pdir, kWritePermission)) {
120 Log(TString::Format(
"%s: version change"
121 " (current: %s, build: %s): cleaning ... ",
122 pack, gROOT->GetVersion(), v.Data()));
124 gSystem->ChangeDirectory(fDir);
126 gSystem->Exec(TString::Format(
"%s %s", kRM, pdir.Data()));
128 char *gunzip = gSystem->Which(gSystem->Getenv(
"PATH"), kGUNZIP,
132 par.Form(
"%s.par", pdir.Data());
135 cmd.Form(kUNTAR3, gunzip, par.Data());
136 rc = gSystem->Exec(cmd);
138 Error(
"Build",
"failure executing: %s", cmd.Data());
141 TMD5 *md5local = TMD5::FileChecksum(par);
143 TString md5f = pdir +
"/PROOF-INF/md5.txt";
144 TMD5::WriteChecksum(md5f, md5local);
146 gSystem->ChangeDirectory(pdir);
148 SafeDelete(md5local);
150 Warning(
"Build",
"failure calculating/saving MD5sum for '%s'", par.Data());
155 Error(
"Build",
"%s not found", kGUNZIP);
159 Log(TString::Format(
"%s: ROOT version inconsistency (current: %s, build: %s):"
160 " directory not writable: cannot re-build!!! ",
161 pack, gROOT->GetVersion(), v.Data()));
171 TString ipath(gSystem->GetIncludePath());
172 ipath.ReplaceAll(
"\"",
"");
174 cmd.Form(
"export ROOTINCLUDEPATH=\"%s\" ; PROOF-INF/BUILD.sh", ipath.Data());
175 rc = gSystem->Exec(cmd);
177 Error(
"Build",
"failure executing: %s", cmd.Data());
181 f = fopen(
"PROOF-INF/proofvers.txt",
"w");
183 fputs(gROOT->GetVersion(), f);
184 fputs(TString::Format(
"\n%s", gROOT->GetGitCommit()), f);
193 Info(
"Build",
"no PROOF-INF/BUILD.sh found for package %s", pack);
197 gSystem->ChangeDirectory(ocwd);
206 Int_t TPackMgr::Load(
const char *pack,
const char *opts)
208 TList *optls =
new TList;
209 optls->Add(
new TObjString(opts));
210 Int_t rc = Load(pack, optls);
220 Int_t TPackMgr::Load(
const char *pack, TList *optls)
226 if (fEnabledPackages && fEnabledPackages->FindObject(pack)) {
227 Log(TString::Format(
"error: TPackMgr::Load: package %s already loaded", pack));
234 TPackMgr *packmgr = 0;
235 if (!(packmgr = TPackMgr::GetPackMgr(pack,
nullptr))) {
237 Log(TString::Format(
"error: TPackMgr::Load: failure locating %s ...", pack));
241 return packmgr->Load(pack, optls);
245 TString pdir = TString::Format(
"%s/%s", fDir.Data(), pack);
248 TString deps = TString::Format(
"%s/PROOF-INF/depends", pdir.Data());
249 if (!gSystem->AccessPathName(deps)) {
250 TMacro mdeps(
"deps");
251 if (mdeps.ReadFile(deps) > 0) {
252 Log(TString::Format(
"info: TPackMgr::Load: checking dependencies for package %s ...", pack));
253 TIter nxl(mdeps.GetListOfLines());
255 while ((os = (TObjString *)nxl())) {
256 if (!TPackMgr::IsEnabled(os->GetName(),
this)) {
257 if (Load(os->GetName(), optls) < 0) {
259 Log(TString::Format(
"error: TPackMgr::Load: failure loading dep %s ...", os->GetName()));
268 Int_t chkveropt = kCheckROOT;
270 TParameter<Int_t> *pcv = (TParameter<Int_t> *) optls->FindObject(
"PROOF_Package_CheckVersion");
272 chkveropt = pcv->GetVal();
277 if (Build(pack, chkveropt) < 0) {
279 Log(TString::Format(
"error: TPackMgr::Load: package %s oes not build! ", pack));
283 TString ocwd = gSystem->WorkingDirectory();
284 gSystem->ChangeDirectory(pdir);
287 TLockPathGuard lp(&fLock, kTRUE);
290 if (!gSystem->AccessPathName(
"PROOF-INF/SETUP.C")) {
293 setup.Form(
"SETUP_%d_%x", gSystem->GetPid(), TString(pack).Hash());
295 TMacro setupmc(
"PROOF-INF/SETUP.C");
296 TObjString *setupline = setupmc.GetLineWith(
"SETUP(");
298 TString setupstring(setupline->GetString());
299 setupstring.ReplaceAll(
"SETUP(", TString::Format(
"%s(", setup.Data()));
300 setupline->SetString(setupstring);
303 Log(TString::Format(
"warning: macro '%s/PROOF-INF/SETUP.C' does not contain a SETUP()"
308 if (!setupmc.Load()) {
310 Log(TString::Format(
"error: macro '%s/PROOF-INF/SETUP.C' could not be loaded:"
311 " cannot continue", pack));
315 TFunction *fun = (TFunction *) gROOT->GetListOfGlobalFunctions()->FindObject(setup);
318 Log(TString::Format(
"error: function SETUP() not found in macro '%s/PROOF-INF/SETUP.C':"
319 " cannot continue", pack));
324 if (fun->GetNargs() == 0) {
327 if (optls && optls->GetSize() > 0) {
328 Log(TString::Format(
"warning: loaded SETUP() for '%s' does not take any argument:"
329 " the specified argument will be ignored", pack));
331 }
else if (fun->GetNargs() == 1) {
332 TMethodArg *arg = (TMethodArg *) fun->GetListOfMethodArgs()->First();
336 TString argsig(arg->GetTitle());
337 if (argsig.BeginsWith(
"TList")) {
338 callEnv.ResetParam();
339 callEnv.SetParam((Long_t) optls);
340 }
else if (argsig.BeginsWith(
"const char")) {
341 callEnv.ResetParam();
342 TObjString *os = optls ?
dynamic_cast<TObjString *
>(optls->First()) : 0;
344 callEnv.SetParam((Long_t) os->GetName());
346 if (optls && optls->First()) {
347 Log(TString::Format(
"warning: found object argument of type %s:"
348 " SETUP expects 'const char *': ignoring",
349 optls->First()->ClassName()));
351 callEnv.SetParam((Long_t) 0);
355 Log(TString::Format(
"error: unsupported SETUP signature: SETUP(%s)"
356 " cannot continue", arg->GetTitle()));
361 Log(
"error: cannot get information about the SETUP() argument:"
365 }
else if (fun->GetNargs() > 1) {
367 Log(
"error: function SETUP() can have at most a 'TList *' argument:"
372 Long_t setuprc = (rc == 0) ? 0 : -1;
374 callEnv.Execute(setuprc);
375 if (setuprc < 0) rc = -1;
381 gSystem->ChangeDirectory(ocwd);
385 gSystem->Symlink(pdir, pack);
389 gSystem->AddIncludePath(TString::Format(
"-I%s", pack));
392 gROOT->ProcessLine(TString::Format(
".I %s", pack));
394 TPair *pck = (optls && optls->GetSize() > 0) ?
new TPair(
new TObjString(pack), optls->Clone())
395 :
new TPair(
new TObjString(pack), 0);
396 if (!fEnabledPackages) {
397 fEnabledPackages =
new TList;
398 fEnabledPackages->SetOwner();
400 fEnabledPackages->Add(pck);
411 Int_t TPackMgr::Unload(
const char *pack)
415 if (fEnabledPackages && fEnabledPackages->GetSize() > 0) {
417 if (pack && strlen(pack) > 0) {
418 if ((ppack = (TPair *) fEnabledPackages->FindObject(pack))) {
421 TString aclicincpath = gSystem->GetIncludePath();
422 TString cintincpath = gInterpreter->GetIncludePath();
424 aclicincpath.Remove(aclicincpath.Length() - cintincpath.Length() - 1);
426 aclicincpath.ReplaceAll(TString(
" -I") + pack,
"");
427 gSystem->SetIncludePath(aclicincpath);
432 delete fEnabledPackages->Remove(ppack);
436 if (!gSystem->AccessPathName(pack))
437 if (gSystem->Unlink(pack) != 0) rc = -1;
442 TIter nxp(fEnabledPackages);
443 while ((ppack = (TPair *) nxp())) {
444 if (Unload(ppack->GetName()) != 0) rc = -1;
458 Bool_t TPackMgr::Has(
const char *pack)
461 TString pdir = TString::Format(
"%s/%s", fDir.Data(), pack);
464 TLockPathGuard lp(&fLock, kTRUE);
466 if (gSystem->AccessPathName(pdir, kReadPermission) ||
467 gSystem->AccessPathName(pdir +
"/PROOF-INF", kReadPermission))
478 Bool_t TPackMgr::IsInDir(
const char *path)
480 return strncmp(fDir.Data(), path, fDir.Length()) ? kFALSE : kTRUE ;
487 Int_t TPackMgr::GetPackDir(
const char *pack, TString &pdir)
491 if (strstr(pack,
".par")) pn.Remove(pn.Last(
'.'));
492 pdir.Form(
"%s/%s", fDir.Data(), pn.Data());
493 if (gSystem->AccessPathName(pdir, kReadPermission))
return -1;
501 void TPackMgr::GetEnabledPackages(TString &packlist)
504 if (!fEnabledPackages)
return;
506 TIter nxp(fEnabledPackages);
508 while ((pck = (TPair *)nxp())) {
509 if (packlist.Length() <= 0)
510 packlist = pck->GetName();
512 packlist += TString::Format(
";%s", pck->GetName());
521 Int_t TPackMgr::GetParPath(
const char *pack, TString &path)
524 const char *fm = (strstr(pack,
".par")) ?
"%s/%s" :
"%s/%s.par";
525 path.Form(fm, fDir.Data(), pack);
526 if (gSystem->AccessPathName(path, kReadPermission))
return -1;
534 Int_t TPackMgr::GetDownloadDir(TString &dldir)
536 dldir.Form(
"%s/downloaded", fDir.Data());
537 if (gSystem->AccessPathName(dldir, kReadPermission)) {
538 if (gSystem->mkdir(dldir, kTRUE) != 0)
return -1;
539 if (gSystem->AccessPathName(dldir, kReadPermission))
return -1;
548 void TPackMgr::Show(
const char *title)
550 if (fgGlobalPackMgrList && fgGlobalPackMgrList->GetSize() > 0) {
552 TIter nxpm(fgGlobalPackMgrList);
554 while ((pm = (TPackMgr *)nxpm())) {
555 pm->Show(TString::Format(
"*** Global Package cache %s %s:%s ***\n",
556 pm->GetName(), gSystem->HostName(), pm->GetTitle()));
560 if (title && strlen(title) > 0)
561 printf(
"%s\n", title);
563 printf(
"*** Package cache %s:%s ***\n", gSystem->HostName(), fDir.Data());
566 TLockPathGuard lp(&fLock, kTRUE);
567 gSystem->Exec(TString::Format(
"%s %s", kLS, fDir.Data()));
576 Int_t TPackMgr::Clean(
const char *pack)
579 TLockPathGuard lp(&fLock);
581 if (pack && strlen(pack)) {
583 rc = gSystem->Exec(TString::Format(
"%s %s/%s/*", kRM, fDir.Data(), pack));
593 Int_t TPackMgr::Remove(
const char *pack, Bool_t dolock)
596 if (dolock) fLock.Lock();
597 Int_t rc1 = 0, rc2 = 0, rc3 = 0;
598 if (pack && strlen(pack)) {
600 TString path = TString::Format(
"%s/downloaded/%s.par", fDir.Data(), pack);
601 gSystem->Exec(TString::Format(
"%s %s", kRM, path.Data()));
602 if (!gSystem->AccessPathName(path, kFileExists)) rc1 = -1;
603 path.ReplaceAll(
"/downloaded/",
"/");
604 gSystem->Exec(TString::Format(
"%s %s", kRM, path.Data()));
605 if (!gSystem->AccessPathName(path, kFileExists)) rc2 = -1;
606 path.Remove(path.Last(
'.'));
607 gSystem->Exec(TString::Format(
"%s %s", kRM, path.Data()));
608 if (!gSystem->AccessPathName(path, kFileExists)) rc3 = -1;
611 rc1 = gSystem->Exec(TString::Format(
"%s %s/*", kRM, fDir.Data()));
613 if (dolock) fLock.Unlock();
614 return (rc1 + rc2 + rc3);
621 TList *TPackMgr::GetList()
const
623 TList *plist =
new TList;
624 void *dir = gSystem->OpenDirectory(fDir);
626 TString pac(gSystem->GetDirEntry(dir));
627 while (pac.Length() > 0) {
628 if (pac.EndsWith(
".par")) {
629 pac.ReplaceAll(
".par",
"");
630 plist->Add(
new TObjString(pac.Data()));
632 pac = gSystem->GetDirEntry(dir);
635 gSystem->FreeDirectory(dir);
644 TList *TPackMgr::GetListOfEnabled()
const
646 TList *epl =
nullptr;
647 if (fEnabledPackages && fEnabledPackages->GetSize() > 0) {
649 TIter nxp(fEnabledPackages);
651 while ((o = nxp())) {
652 epl->Add(
new TObjString(o->GetName()));
662 void TPackMgr::ShowEnabled(
const char *title)
664 if (fgGlobalPackMgrList && fgGlobalPackMgrList->GetSize() > 0) {
666 TIter nxpm(fgGlobalPackMgrList);
668 while ((pm = (TPackMgr *)nxpm())) {
669 pm->ShowEnabled(TString::Format(
"*** Global Package cache %s %s:%s ***\n",
670 pm->GetName(), gSystem->HostName(), pm->GetTitle()));
674 if (!fEnabledPackages || fEnabledPackages->GetSize() <= 0)
return;
676 if (title && strlen(title) > 0)
677 printf(
"%s\n", title);
679 printf(
"*** Package enabled on %s ***\n", gSystem->HostName());
682 TIter next(fEnabledPackages);
683 while (TPair *pck = (TPair *) next()) {
684 printf(
"%s\n", pck->GetName());
692 TMD5 *TPackMgr::GetMD5(
const char *pack)
695 TLockPathGuard lp(&fLock, kTRUE);
697 const char *fm = (strstr(pack,
".par")) ?
"%s/%s" :
"%s/%s.par";
698 TString parfile = TString::Format(fm, fDir.Data(), pack);
700 return TMD5::FileChecksum(parfile);
708 TMD5 *TPackMgr::ReadMD5(
const char *pack)
711 if (pn.EndsWith(
".par")) pn.Remove(pn.Last(
'.'));
713 TString md5f = TString::Format(
"%s/%s/PROOF-INF/md5.txt", fDir.Data(), pn.Data());
714 TLockPathGuard lp(&fLock, kTRUE);
715 return TMD5::ReadChecksum(md5f);
723 Int_t TPackMgr::Unpack(
const char *pack, TMD5 *sum)
726 TString fn(pack), pn(pack);
727 if (!fn.EndsWith(
".par")) fn +=
".par";
728 if (pn.EndsWith(
".par")) pn.Remove(pn.Last(
'.'));
731 char *gunzip = gSystem->Which(gSystem->Getenv(
"PATH"), kGUNZIP, kExecutePermission);
735 cmd.Form(kUNTAR, gunzip, fDir.Data(), fn.Data(), fDir.Data());
736 rc = gSystem->Exec(cmd);
738 Error(
"Unpack",
"failure executing: %s (rc: %d)", cmd.Data(), rc);
741 Error(
"Unpack",
"%s not found", kGUNZIP);
745 if (gSystem->AccessPathName(TString::Format(
"%s/%s", fDir.Data(), pn.Data()), kWritePermission)) {
748 Error(
"Unpack",
"package %s did not unpack into %s", fn.Data(), pn.Data());
752 TString md5f = TString::Format(
"%s/%s/PROOF-INF/md5.txt", fDir.Data(), pn.Data());
753 TMD5::WriteChecksum(md5f, sum);
766 Int_t TPackMgr::Install(
const char *parpath, Bool_t rmold)
770 Info(
"Install",
"installing %s ...", parpath);
771 const char *par = gSystem->ExpandPathName(parpath);
774 if (gSystem->AccessPathName(par, kReadPermission)) {
775 Error(
"Install",
"%s is invalid", par);
778 TString parname = gSystem->BaseName(par);
779 TString pack = parname(0, parname.Last(
'.'));
780 TString dest = TString::Format(
"%s/%s", fDir.Data(), parname.Data());
781 TString psrc = par, ssrc;
782 TMD5 *sums = 0, *md5 = 0, *md5d = 0;
788 if (GetDownloadDir(dldir) != 0) {
789 Error(
"Install",
"could not create/get download directory");
793 TLockPathGuard lp(&fLock, kFALSE);
796 parsum.ReplaceAll(
".par",
".md5sum");
797 if (!gSystem->AccessPathName(parsum, kReadPermission)) {
798 ssrc.Form(
"%s/%s", dldir.Data(), gSystem->BaseName(parsum));
799 if (!TFile::Cp(parsum, ssrc)) {
800 Warning(
"Install",
"could not retrieve %s", parsum.Data());
802 md5 = TMD5::ReadChecksum(ssrc);
807 Bool_t parexists = (!gSystem->AccessPathName(dest)) ? kTRUE : kFALSE;
809 Bool_t install = kTRUE;
815 if (Remove(pack, kFALSE) < 0) {
816 Error(
"Install",
"could not remove existing version of '%s'", pack.Data());
823 TFile::EFileType ft = TFile::GetType(par);
824 if (ft == TFile::kWeb || ft == TFile::kNet) {
825 psrc.Form(
"%s/%s", dldir.Data(), parname.Data());
826 if (!TFile::Cp(par, psrc)) {
827 Error(
"Install",
"could not retrieve %s", par);
832 md5 = TMD5::FileChecksum(psrc);
835 sums = TMD5::FileChecksum(dest);
836 if (sums && md5 && (*sums != *md5)) install = kTRUE;
839 if (sums)
delete sums;
843 if (!TFile::Cp(psrc, dest)) {
844 Error(
"Install",
"could not copy %s to %s", psrc.Data(), dest.Data());
849 md5d = TMD5::FileChecksum(dest);
851 if (md5 && *md5 != *md5d)
852 Warning(
"Install",
"checksums do not match:\n\tdownloaded:\t%s\n\texpected:\t%s",
853 md5d->AsString(), md5->AsString());
854 if (Unpack(pack, md5d) != 0) {
855 Error(
"Install",
"could not unpack %s", dest.Data());
859 if (md5d)
delete md5d;
871 Int_t TPackMgr::RegisterGlobalPath(
const char *paths)
875 TString globpack(paths);
876 if (globpack.Length() > 0) {
879 while (globpack.Tokenize(ldir, from,
":")) {
880 if (gSystem->AccessPathName(ldir, kReadPermission)) {
881 ::Warning(
"TPackMgr::RegisterGlobalPath",
882 "directory for global packages %s does not"
883 " exist or is not readable", ldir.Data());
887 key.Form(
"G%d", ng++);
888 if (!fgGlobalPackMgrList) {
889 fgGlobalPackMgrList =
new THashList();
890 fgGlobalPackMgrList->SetOwner();
892 TPackMgr *pmgr =
new TPackMgr(ldir);
894 fgGlobalPackMgrList->Add(pmgr);
895 ::Info(
"TPackMgr::RegisterGlobalPath",
896 "manager for global packages directory %s added to the list",
911 TPackMgr *TPackMgr::GetPackMgr(
const char *pack, TPackMgr *packmgr)
913 if (packmgr && packmgr->Has(pack))
return packmgr;
915 if (fgGlobalPackMgrList && fgGlobalPackMgrList->GetSize() > 0) {
917 TIter nxpm(fgGlobalPackMgrList);
919 while ((pm = (TPackMgr *)nxpm())) {
920 if (pm->Has(pack))
return pm;
933 Int_t TPackMgr::FindParPath(TPackMgr *packmgr,
const char *pack, TString &par)
936 if (packmgr && packmgr->GetParPath(pack, par) == 0)
return 1;
939 if (fgGlobalPackMgrList && fgGlobalPackMgrList->GetSize() > 0) {
941 TIter nxpm(fgGlobalPackMgrList);
943 while ((pm = (TPackMgr *)nxpm())) {
944 if (pm->GetParPath(pack, par) == 0) {
950 if (par.Length() > 0)
return 0;
960 Bool_t TPackMgr::IsEnabled(
const char *pack, TPackMgr *packmgr)
962 if (packmgr && packmgr->IsPackageEnabled(pack))
return kTRUE;
964 if (fgGlobalPackMgrList && fgGlobalPackMgrList->GetSize() > 0) {
966 TIter nxpm(fgGlobalPackMgrList);
968 while ((pm = (TPackMgr *)nxpm())) {
969 if (pm->IsPackageEnabled(pack))
return kTRUE;