From f54f3535a31e94cc9691844564a628361de8877b Mon Sep 17 00:00:00 2001
From: Fons Rademakers <Fons.Rademakers@cern.ch>
Date: Thu, 15 May 2008 16:16:03 +0000
Subject: [PATCH] From Andreas: New class providing package management
 functionality like the AliEn Package Management System. Allows to setup
 software packages on a local desktop like in the GRID environment and to
 execute the contained programs. Registered Dependencies are automatically
 resolved and missing packages are automatically installed. Currently there is
 no support for 'source' packages. The desired platform has to be specified in
 the constructor. The default constructor takes packages from the global
 package section in AliEn. If you want to install a user package, you have to
 set the AliEn package directory to your local package directory using     
 package->SetAliEnMainPackageDir("/alice/cern.ch/user/..../packages")

git-svn-id: http://root.cern.ch/svn/root/trunk@23863 27541ba8-7e3a-0410-8455-c3a389f83636
---
 net/alien/inc/LinkDef.h         |   1 +
 net/alien/inc/TAlienPackage.h   | 107 +++++++
 net/alien/src/TAlienPackage.cxx | 523 ++++++++++++++++++++++++++++++++
 3 files changed, 631 insertions(+)
 create mode 100644 net/alien/inc/TAlienPackage.h
 create mode 100644 net/alien/src/TAlienPackage.cxx

diff --git a/net/alien/inc/LinkDef.h b/net/alien/inc/LinkDef.h
index a069accc5ff..8949432c5e7 100644
--- a/net/alien/inc/LinkDef.h
+++ b/net/alien/inc/LinkDef.h
@@ -17,4 +17,5 @@
 #pragma link C++ class TAlienDirectoryEntry;
 #pragma link C++ class TAlienSystem;
 #pragma link C++ class TAlienJobStatusList;
+#pragma link C++ class TAlienPackage;
 #endif
diff --git a/net/alien/inc/TAlienPackage.h b/net/alien/inc/TAlienPackage.h
new file mode 100644
index 00000000000..132d33ff64c
--- /dev/null
+++ b/net/alien/inc/TAlienPackage.h
@@ -0,0 +1,107 @@
+// @(#)root/alien:$Id$
+// Author: Lucia Jancurova/Andreas-Joachim Peters 1/10/2007
+
+/*************************************************************************
+ * Copyright (C) 1995-2008, Rene Brun and Fons Rademakers.               *
+ * All rights reserved.                                                  *
+ *                                                                       *
+ * For the licensing terms see $ROOTSYS/LICENSE.                         *
+ * For the list of contributors see $ROOTSYS/README/CREDITS.             *
+ *************************************************************************/
+
+#ifndef ROOT_TAlienPackage
+#define ROOT_TAlienPackage
+
+#ifndef ROOT_Rtypes
+#include "Rtypes.h"
+#endif
+#ifndef ROOT_TList
+#include "TList.h"
+#endif
+#ifndef ROOT_TGrid
+#include "TGrid.h"
+#endif
+
+//////////////////////////////////////////////////////////////////////////
+//                                                                      //
+// TAlienPackage                                                        //
+//                                                                      //
+// Class providing package management functionality like the AliEn      //
+// Package Management System.                                           //
+// Allows to setup software packages on a local desktop like in the     //
+// GRID environment.                                                    //
+//                                                                      //
+//////////////////////////////////////////////////////////////////////////
+
+class TAlienPackage {
+
+private:
+   TString fName;                   // package principal name
+   TString fVersion;                // package version
+   TString fPlatform;               // package platform
+   TString fInstallationDirectory;  // installation directory
+   TString fAliEnMainPackageDir;    // path to alien packages in the AliEn FC
+   TString fPostInstallCommand;     // command to execute for postinstall
+   TString fEnableCommand;          // command to enable the package
+   TList  *fInstallList;            // package list with names of dependency packages
+   TList  *fPackages;               // package list TPackage with this and dependency packages
+   Int_t  fDebugLevel;              // internal debug level
+   Bool_t fEnabled;                 // true if package is enabled for execution
+
+   Bool_t PostInstall (TString name, TString version);                                 // runs the postinstall procedure for this package
+   Bool_t InstallSinglePackage (TString name, TString version, Bool_t isDep = kFALSE); // installs the defined package without dependencies
+   Bool_t InstallAllPackages (); // installs the defined package + all dependency packages
+
+ public:
+   TAlienPackage ();
+
+   TAlienPackage(const char *name,
+                 const char *version,
+                 const char *platform,
+                 const char *installationdirectory = "/var/tmp/alien/packages");
+
+   virtual ~ TAlienPackage ();
+
+   Bool_t Enable();            // install/enable the defined package
+   const char *GetEnable();    // return shell command to enable package
+   Bool_t Exec(const char *cmdline);  // execute <cmd> with this package
+   Bool_t UnInstall();         // uninstall the defined package
+   Bool_t ReInstall();         // reinstall the defined package
+   Bool_t CheckDependencies(); // get all the dependencies of a package
+
+   Bool_t IsDirectory(const char *dir1, const char *str);  // check for <str> in GRID directory <dir1>
+   Bool_t CheckDirectories(TString name, TString version); // check that the defined package is existing as an alien package directory
+
+   void SetName(const TString & theValue) { fName = theValue; }
+   // set the name of the package
+   TString GetName() const { return fName; }
+   // get the name of the package
+   void SetVersion(const TString & theValue) { fVersion = theValue; }
+   // set the version of the package
+   TString GetVersion() const { return fVersion; }
+   // get the version of the package
+   void SetPlatform(const TString & theValue) { fPlatform = theValue; }
+   // set the platform for the package
+   TString GetPlatform() const { return fPlatform; }
+   // get the platform for the package
+   void SetInstallationDirectory(const TString & theValue) { fInstallationDirectory = theValue; }
+   // set the installation directory
+   TString GetInstallationDirectory() const { return fInstallationDirectory; }
+   // get the installation directory
+   void SetAliEnMainPackageDir(const TString & theValue) { fAliEnMainPackageDir = theValue; }
+   // set the alien path to look for the named package
+   TString GetAliEnMainPackageDir() const { return fAliEnMainPackageDir; }
+   // get the alien path to look for the named package
+   void SetInstallList(TList * theValue) { fInstallList = theValue; }
+   // set the install(dependency) package list
+   TList *GetInstallList() const { return fInstallList; }
+   // get the install(dependency) package list;
+   void SetDebugLevel(Int_t & theValue) { fDebugLevel = theValue; }
+   // set the internal debug level
+   Int_t GetDebugLevel() { return fDebugLevel; }
+   // get the internal debug level
+
+   ClassDef (TAlienPackage, 0);   // Alien package interface
+};
+
+#endif
diff --git a/net/alien/src/TAlienPackage.cxx b/net/alien/src/TAlienPackage.cxx
new file mode 100644
index 00000000000..306e15ba12f
--- /dev/null
+++ b/net/alien/src/TAlienPackage.cxx
@@ -0,0 +1,523 @@
+// @(#)root/alien:$Id$
+// Author: Lucia Jancurova/Andreas-Joachim Peters 1/10/2007
+
+/*************************************************************************
+ * Copyright (C) 1995-2008, Rene Brun and Fons Rademakers.               *
+ * All rights reserved.                                                  *
+ *                                                                       *
+ * For the licensing terms see $ROOTSYS/LICENSE.                         *
+ * For the list of contributors see $ROOTSYS/README/CREDITS.             *
+ *************************************************************************/
+
+#include "Riostream.h"
+#include "TSystem.h"
+#include "TGridResult.h"
+#include "TFile.h"
+#include "TObjString.h"
+#include "TObjArray.h"
+#include "TError.h"
+#include "TAlienPackage.h"
+
+//////////////////////////////////////////////////////////////////////////
+//                                                                      //
+// TAlienPackage                                                        //
+//                                                                      //
+// Class providing package management functionality like the AliEn      //
+// Package Management System.                                           //
+// Allows to setup software packages on a local desktop like in the     //
+// GRID environment and to execute the contained programs.              //
+// Registered Dependencies are automatically resolved and missing       //
+// packages are automatically installed.                                //
+// Currently there is no support for 'source' packages.                 //
+// The desired platform has to be specified in the constructor.         //
+// The default constructor takes packages from the global package       //
+// section in AliEn. If you want to install a user package, you have to //
+// set the AliEn package directory to your local package directory using//
+// 'package->SetAliEnMainPackageDir("/alice/cern.ch/user/..../packages")//
+//                                                                      //
+// ---------------------------------------------------------------------/////////////////////////
+// Examples of use:                                                                            //
+// root [0] TAlienPackage* package = new TAlienPackage("AliRoot","v4-07-Rev-01","Linux-i686"); //
+// root [1] package->Exec("aliroot -b -q ")                                                    //
+//                                                                                             //
+// root [0] TAlienPackage* package = new TAlienPackage("ROOT","v5-16-00","Linux-i686");        //
+// root [1] package->Exec("root -b -q ")                                                       //
+/////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+ClassImp (TAlienPackage)
+
+//______________________________________________________________________________
+TAlienPackage::TAlienPackage() : fInstallList (0), fPackages (0), fDebugLevel (0)
+{
+   // Default constructor of a AliEn package constructing a ROOT:v5-16-00 for Linux-i686.
+
+   fName = "ROOT";
+   fVersion = "v5-16-00";
+   fPlatform = "Linux-i686";
+   fAliEnMainPackageDir = "/alice/packages";
+   fInstallationDirectory = "/var/tmp/alien/packages";
+   fPostInstallCommand = "post_install";
+   fEnableCommand = "";
+
+   if (gDebug > 0)
+      Info ("TAlienPackage",
+            "\tPackage=%s Version=%s Platform=%s Installdir=%s AlienInstalldir=%s PostInstall=%s",
+            fName.Data (), fVersion.Data (), fPlatform.Data (),
+            fInstallationDirectory.Data (), fAliEnMainPackageDir.Data (),
+            fPostInstallCommand.Data ());
+   if (!gGrid)
+      gGrid = TGrid::Connect ("alien://");
+
+   if (!fInstallList)
+      fInstallList = new TList ();
+   if (!fPackages)
+      fPackages = new TList ();
+
+   fEnabled = kFALSE;
+   fPackages->SetOwner (kFALSE);
+}
+
+//______________________________________________________________________________
+TAlienPackage::TAlienPackage(const char *name, const char *version,
+                             const char *platform,
+                             const char *installationdirectory) :
+   fInstallList (0), fPackages (0), fDebugLevel (0)
+{
+   // Constructor of a AliEn package.
+
+   fName = name;
+
+   fVersion = version;
+
+   fAliEnMainPackageDir = "/alice/packages";
+   fInstallationDirectory = installationdirectory;
+   fPostInstallCommand = "post_install";
+   fEnableCommand = "";
+   fPlatform = platform;
+   fEnabled = kFALSE;
+
+   if (gDebug > 0)
+      Info ("TAlienPackage",
+            "\tPackage=%s Version=%s Platform=%s Installdir=%s AlienInstalldir=%s PostInstall=%s",
+            name, version, platform, installationdirectory,
+            fAliEnMainPackageDir.Data (), fPostInstallCommand.Data ());
+
+   if (!gGrid)
+      gGrid = TGrid::Connect ("alien://");
+
+   if (!fInstallList)
+      fInstallList = new TList ();
+
+   if (!fPackages)
+      fPackages = new TList ();
+   fPackages->SetOwner (kFALSE);
+}
+
+//______________________________________________________________________________
+TAlienPackage::~TAlienPackage()
+{
+   // Destructor.
+
+   if (GetDebugLevel () > 2)
+      Info ("~TAlienPackage", "\tDestr: Package=%s Version=%s Platform=%s",
+            fName.Data (), fVersion.Data (), fPlatform.Data ());
+   SafeDelete (fInstallList);
+}
+
+//______________________________________________________________________________
+Bool_t TAlienPackage::Enable()
+{
+   // Install/enable an AliEn package on the local computer.
+
+   fInstallList->Clear ();
+   if (GetDebugLevel () > 1)
+      Info ("Install", "\t\tInstalling Package=%s Version=%s Platform=%s",
+            fName.Data (), fVersion.Data (), fPlatform.Data ());
+
+   if (CheckDirectories (fName, fVersion) == kFALSE)
+      return kFALSE;
+
+   if (CheckDependencies () == kFALSE)
+      return kFALSE;
+
+   if (InstallAllPackages () == kFALSE)
+      return kFALSE;
+
+   gSystem->Exec(Form("mkdir -p %s/%s/%s/%s ; touch  %s/%s/%s/%s/.safeguard",
+                 fInstallationDirectory.Data (), fName.Data (), fVersion.Data (),
+                 fVersion.Data (), fInstallationDirectory.Data (), fName.Data (),
+                 fVersion.Data (), fVersion.Data ()));
+
+   fEnabled = kTRUE;
+   return kTRUE;
+}
+
+//______________________________________________________________________________
+const char *TAlienPackage::GetEnable ()
+{
+   // Return shell command to enable package.
+
+   fEnableCommand =
+      Form ("%s/%s/%s/.alienEnvironment %s/%s/%s ",
+            fInstallationDirectory.Data (), fName.Data (), fVersion.Data (),
+            fInstallationDirectory.Data (), fName.Data (), fVersion.Data ());
+   return fEnableCommand.Data ();
+}
+
+//______________________________________________________________________________
+Bool_t TAlienPackage::UnInstall ()
+{
+   // Uninstall a package e.g. remove it from the local disk.
+
+   gSystem->Exec(Form
+            ("test -e %s/%s/%s/%s/.safeguard && rm -rf %s/%s/%s",
+             fInstallationDirectory.Data (), fName.Data (), fVersion.Data (),
+             fVersion.Data (), fInstallationDirectory.Data (), fName.Data (),
+             fVersion.Data ()));
+   fEnabled = kFALSE;
+   return kTRUE;
+}
+
+//______________________________________________________________________________
+Bool_t TAlienPackage::IsDirectory (const char *dir1, const char *str)
+{
+   // Check that <str> is listed in GRID directory <dir1>.
+
+   TGridResult *result = gGrid->Ls (dir1);
+   Int_t i = 0;
+   while (result->GetFileName (i)) {
+      if (TString (result->GetFileName (i)) == str) {
+         return kTRUE;
+      }
+      i++;
+   }
+
+   return kFALSE;
+}
+
+//______________________________________________________________________________
+Bool_t TAlienPackage::CheckDirectories (TString name, TString version)
+{
+   // Check the name and version directory of package/version given.
+
+   TString s(GetAliEnMainPackageDir());
+
+   if ((IsDirectory (s.Data (), name.Data ())) == kTRUE) {
+      if (GetDebugLevel () > 1)
+         Info ("CheckDirectories", "\t%s/%s exists.", s.Data (), name.Data ());
+
+      s += "/" + name;
+      if ((IsDirectory (s, version.Data ())) == kTRUE) {
+         if (GetDebugLevel () > 1)
+            Info ("CheckDirectories", "\t%s/%s exist.", s.Data (), version.Data ());
+
+         s += "/" + version;
+         if ((IsDirectory (s, GetPlatform ().Data ())) == kTRUE) {
+            if (GetDebugLevel () > 1)
+               Info ("CheckDirectories", "\t%s/%s exist.", s.Data (), GetPlatform ().Data ());
+            return kTRUE;
+         } else {
+            Error ("CheckDirectories", "\t%s/%s does not exist.", s.Data (), GetPlatform ().Data ());
+         }
+      } else {
+         Error ("CheckDirectories", "\t%s/%s does not exist.", s.Data (), version.Data ());
+      }
+   }  else {
+      Info ("CheckDirectories", "\t%s/%s exists.", s.Data (), name.Data ());
+   }
+
+   return kFALSE;
+}
+
+//______________________________________________________________________________
+Bool_t TAlienPackage::ReInstall ()
+{
+   // Reinstalls a package e.g. uninstall + install.
+
+   if (UnInstall () == kFALSE)
+      return kFALSE;
+
+   if (Enable () == kFALSE)
+      return kFALSE;
+   return kTRUE;
+}
+
+//______________________________________________________________________________
+Bool_t TAlienPackage::PostInstall (TString name, TString version)
+{
+   // Execute post_install procedure for a package.
+
+   TGridResult *result =
+      gGrid->Command (Form
+               ("showTagValue -z %s/%s/%s PackageDef",
+                fAliEnMainPackageDir.Data (), name.Data (), version.Data ()));
+   TString post_install (result->GetKey (0, "post_install"));
+
+   if (post_install.IsNull () == kTRUE) {
+      if (GetDebugLevel () > 0)
+         Info ("PostInstall",
+               "\tNo post install procedure defined in AliEn.");
+      return kTRUE;
+   }
+
+   if (GetDebugLevel () > 0)
+      Info ("PostInstall",
+            "\tDownloading PostInstall for Package=%s Version=%s",
+            name.Data (), version.Data ());
+
+   if (!TFile::Cp(Form("alien://%s", post_install.Data ()),
+                  Form("%s/%s/%s/%s", fInstallationDirectory.Data (), name.Data (),
+                  version.Data (), fPostInstallCommand.Data ()))) {
+      Error ("PostInstall", "\tCannot download the PostInstall script %s!", post_install.Data ());
+      return kFALSE;
+   }
+
+   gSystem->ChangeDirectory (Form
+                       ("%s/%s/%s", fInstallationDirectory.Data (),
+                        name.Data (), version.Data ()));
+   gSystem->Exec (Form ("chmod +x %s", fPostInstallCommand.Data ()));
+   gSystem->Exec (Form ("./%s %s/%s/%s", fPostInstallCommand.Data (),
+             fInstallationDirectory.Data (), name.Data (), version.Data ()));
+
+   if (GetDebugLevel () > 1)
+      Info ("PostInstall",
+            "\tExecuted PostInstall for Package=%s Version=%s ", name.Data (),
+            version.Data ());
+   return kTRUE;
+}
+
+//______________________________________________________________________________
+Bool_t TAlienPackage::Exec (const char *cmdline)
+{
+   // Execute package command.
+
+   TString fullline = "";
+
+   if (!fEnabled) {
+      if (!Enable ())
+         return kFALSE;
+   }
+
+   for (Int_t j = 0; j < fPackages->GetEntries (); j++) {
+      TAlienPackage *package = (TAlienPackage *) fPackages->At (j);
+      fullline += package->GetEnable ();
+      fullline += " ";
+   }
+
+   fullline += cmdline;
+
+   Info("Exec", "\t\tExecuting Package=%s Version=%s \"%s\"", fName.Data (),
+        fVersion.Data (), fullline.Data ());
+
+   gSystem->Exec(fullline.Data());
+   return kTRUE;
+}
+
+//______________________________________________________________________________
+Bool_t TAlienPackage::CheckDependencies ()
+{
+   // Check the dependency packages of this package.
+
+   TString path (Form("%s/%s/%s", fAliEnMainPackageDir.Data (), fName.Data (),
+             fVersion.Data ()));
+
+   TGridResult *result =
+      gGrid->Command (Form ("showTagValue -z %s PackageDef", path.Data ()));
+
+   TString strDep (result->GetKey (0, "dependencies"));
+
+   if (strDep.IsNull () == kTRUE) {
+      if (GetDebugLevel () > 0)
+         Info ("CheckDepencencies", "\tFound no dependencies ... ");
+      TObjString *strObj =
+         new TObjString (Form ("%s::%s", fName.Data (), fVersion.Data ()));
+      fInstallList->Add (strObj);
+      return kTRUE;
+   }
+
+   TObjArray *strDeps = strDep.Tokenize (",");
+
+   if (GetDebugLevel () > 0)
+      Info ("CheckDepencencies", "\tFound %d dependencies ... ",
+            strDeps->GetEntries ());
+
+   for (Int_t i = 0; i < strDeps->GetEntries (); i++) {
+      TObjString *strObj = (TObjString *) strDeps->At (i);
+      TObjArray *strDepsPackgAndVer = strObj->GetString ().Tokenize ("@");
+      TObjString *strObj2 = (TObjString *) strDepsPackgAndVer->At (1);
+
+      if (GetDebugLevel () > 2)
+         Info ("CheckDependencies", "\t[%d] Dep. Package=%s", i,
+               strObj2->GetString ().Data ());
+      fInstallList->Add (strObj2);
+   }
+
+   TObjString *strObj = new TObjString (Form ("%s::%s", fName.Data (), fVersion.Data ()));
+   fInstallList->Add (strObj);
+
+   for (Int_t j = 0; j < fInstallList->GetEntries (); j++) {
+      TObjString *strObj = (TObjString *) fInstallList->At (j);
+      TObjArray *strDepsPackgOrVer = strObj->GetString ().Tokenize ("::");
+      TObjString *strObjPackage = (TObjString *) strDepsPackgOrVer->At (0);
+      TObjString *strObjVersion = (TObjString *) strDepsPackgOrVer->At (1);
+
+      if (GetDebugLevel () > 2)
+         Info ("CheckDepencencies", "\t[%d] Name=%s Version=%s", j,
+               strObjPackage->GetString ().Data (),
+               strObjVersion->GetString ().Data ());
+
+      if (CheckDirectories(strObjPackage->GetString (), strObjVersion->GetString ()) == kFALSE)
+         return kFALSE;
+   }
+
+   return kTRUE;
+}
+
+//______________________________________________________________________________
+Bool_t TAlienPackage::InstallSinglePackage(TString name, TString version, Bool_t isDep)
+{
+   // Install a single package.
+
+   Info ("InstallSinglePackage", "\t%s %s", name.Data (), version.Data ());
+   // install a package without dependencies
+   TString s1 (Form ("%s/%s/%s/%s", fAliEnMainPackageDir.Data (), name.Data (),
+           version.Data (), fPlatform.Data ()));
+   TString s2 (Form ("%s(%s)", name.Data (), version.Data ()));
+   TString s3 (Form ("%s/%s/%s/%s", fInstallationDirectory.Data (), name.Data (),
+           version.Data (), version.Data ()));
+   TString s4 (Form ("%s/%s/%s/%s/%s", fInstallationDirectory.Data (), name.Data (),
+           version.Data (), version.Data (), fPlatform.Data ()));
+   TString s5 (Form ("%s/%s/%s/%s", fInstallationDirectory.Data (), name.Data (),
+           version.Data (), fPlatform.Data ()));
+   TString s6 (Form ("%s/%s", fAliEnMainPackageDir.Data (), name.Data ()));
+   TString s7 (Form ("%s/%s/%s", fInstallationDirectory.Data (), name.Data (),
+           version.Data ()));
+   TString s8 (Form ("%s/%s/%s/%s/.safeguard", fInstallationDirectory.Data (),
+           name.Data (), version.Data (), version.Data ()));
+
+   if (gSystem->AccessPathName (s8.Data ()) == 0) {
+      if (isDep == kFALSE) {
+         if (GetDebugLevel () > 0) {
+            Warning ("InstallSinglePackage",
+                     "\tPackage=%s exists in /%s directory.",
+                     s2.Data (), s3.Data ());
+            Warning ("InstallSinglePackage",
+                     "\tYou might use function UnInstall() before Enable(), or do ReInstall() !!!!");
+         }
+         return kTRUE;
+      } else {
+         return kTRUE;
+      }
+   }
+
+   if (GetDebugLevel () > 1)
+      Info ("InstallSinglePackage", "\tCopying from alien://%s to %s ",
+            s1.Data (), s5.Data ());
+
+   gSystem->Exec (Form ("mkdir -p %s", s3.Data ()));
+
+   if (gSystem->AccessPathName (s3.Data ())) {
+      Error ("InstallSinglePackage", "\tCouldn't create directory %s !",
+             s3.Data ());
+      return kFALSE;
+   }
+
+   if (!TFile::Cp (Form ("alien://%s", s1.Data ()), Form ("%s", s5.Data ()))) {
+      Error ("InstallSinglePackage", "\tCouldn't copy alien://%s -> %s",
+             s1.Data (), s5.Data ());
+      return kFALSE;
+   }
+
+   if (GetDebugLevel () > 2)
+      Info ("InstallSinglePackage", "\tEntering directory %s ", s7.Data ());
+
+   if (!gSystem->ChangeDirectory (Form ("%s", s7.Data ()))) {
+      Error ("InstallSinglePackage", "\tCannot change into directory %s",
+             s7.Data ());
+      return kFALSE;
+   }
+
+   if (GetDebugLevel () > 2)
+      Info ("InstallSinglePackage", "\tUnpacking the package %s ...",
+            s2.Data ());
+
+   gSystem->Exec (Form ("tar -xzf %s", fPlatform.Data ()));
+
+   if (GetDebugLevel () > 2)
+      Info ("InstallSinglePackage", "\tUnpacking the package %s DONE ...",
+            s2.Data ());
+
+   gSystem->Exec (Form ("rm -f %s", fPlatform.Data ()));
+
+   if (GetDebugLevel () > 2)
+      Info ("InstallSinglePackage",
+            "\tCopying PostInstall alien://%s/%s -> %s", s6.Data (),
+            fPostInstallCommand.Data (), s7.Data ());
+
+   if (!PostInstall (name, version)) {
+      Error ("InstallSinglePackage",
+             "\tPostInstall procedure failed for package %s failed!",
+             s2.Data ());
+      return kFALSE;
+   }
+
+   return kTRUE;
+}
+
+//______________________________________________________________________________
+Bool_t TAlienPackage::InstallAllPackages ()
+{
+   // Installs a package and all its direct dependencies.
+
+   Bool_t isDep = kFALSE;
+
+   Info ("InstallAllPackages", "\tPackage=%s Version=%s", fName.Data (),
+         fVersion.Data ());
+
+   for (Int_t j = 0; j < fPackages->GetEntries (); j++) {
+      TAlienPackage *package = (TAlienPackage *) fPackages->At (j);
+      if (package && (package != this))
+         delete package;
+   }
+
+   fPackages->Clear ();
+
+   for (Int_t j = 0; j < fInstallList->GetEntries (); j++) {
+      TObjString *strObj = (TObjString *) fInstallList->At (j);
+
+      TObjArray *strDepsPackgOrVer = strObj->GetString ().Tokenize ("::");
+      TObjString *strObjPackage = (TObjString *) strDepsPackgOrVer->At (0);
+      TObjString *strObjVersion = (TObjString *) strDepsPackgOrVer->At (1);
+      if (GetDebugLevel () > 1)
+         Info ("InstallAllPackages", "\tPackage=%s Version=%s",
+               strObjPackage->GetString ().Data (),
+               strObjVersion->GetString ().Data ());
+
+      if (j < (fInstallList->GetEntries () - 1))
+         isDep = kTRUE;
+      else
+         isDep = kFALSE;
+
+      if (j == (fInstallList->GetEntries () - 1)) {
+         if (InstallSinglePackage(strObjPackage->GetString (), strObjVersion->GetString (), isDep) == kFALSE)
+            return kFALSE;
+         fPackages->Add ((TObject *) this);
+      } else {
+         TAlienPackage *newpackage = new TAlienPackage(strObjPackage->GetName(),
+                                                       strObjVersion->GetName(),
+                                                       fPlatform.Data());
+         if (newpackage) {
+            if (!newpackage->Enable ())
+               return kFALSE;
+         } else {
+            return kFALSE;
+         }
+
+         fPackages->Add ((TObject *) newpackage);
+      }
+   }
+
+   return kTRUE;
+}
-- 
GitLab