mirror of
https://github.com/Combodo/iTop.git
synced 2026-02-13 07:24:13 +01:00
N.890.1 and N.890.2: build a new run time environment into a separate "build" directory, then commit it by the mean of quick and bullet proof file copies/moves. Not yet used in the setup.
SVN:trunk[4881]
This commit is contained in:
@@ -3267,8 +3267,8 @@ abstract class MetaModel
|
||||
{
|
||||
if (!method_exists($sClass, $actionHandler))
|
||||
{
|
||||
$aErrors[$sClass][] = "Unknown function '$sActionHandler' in transition [$sStateCode/$sStimulusCode] for state attribute '$sStateAttCode'";
|
||||
$aSugFix[$sClass][] = "Specify a function which prototype is in the form [public function $sActionHandler(\$sStimulusCode){return true;}]";
|
||||
$aErrors[$sClass][] = "Unknown function '$actionHandler' in transition [$sStateCode/$sStimulusCode] for state attribute '$sStateAttCode'";
|
||||
$aSugFix[$sClass][] = "Specify a function which prototype is in the form [public function $actionHandler(\$sStimulusCode){return true;}]";
|
||||
}
|
||||
}
|
||||
else // if(is_array($actionHandler))
|
||||
@@ -4597,7 +4597,7 @@ abstract class MetaModel
|
||||
|
||||
protected static $m_aExtensionClasses = array();
|
||||
|
||||
protected static function IncludeModule($sToInclude, $sModuleType = null)
|
||||
public static function IncludeModule($sToInclude, $sModuleType = null)
|
||||
{
|
||||
$sFirstChar = substr($sToInclude, 0, 1);
|
||||
$sSecondChar = substr($sToInclude, 1, 1);
|
||||
|
||||
@@ -1025,7 +1025,7 @@ class ApplicationInstaller
|
||||
// Record which modules are installed...
|
||||
$oProductionEnv = new RunTimeEnvironment($sTargetEnvironment);
|
||||
$oProductionEnv->InitDataModel($oConfig, true); // load data model and connect to the database
|
||||
if (!$oProductionEnv->RecordInstallation($oConfig, $sDataModelVersion, $aSelectedModuleCodes, $aSelectedExtensionCodes, $sModulesDir))
|
||||
if (!$oProductionEnv->RecordInstallation($oConfig, $sDataModelVersion, $aSelectedModuleCodes, $aSelectedExtensionCodes))
|
||||
{
|
||||
throw new Exception("Failed to record the installation information");
|
||||
}
|
||||
|
||||
@@ -93,13 +93,14 @@ class MFCompiler
|
||||
* @param string $sTargetDir The target directory where to put the resulting files
|
||||
* @param Page $oP For some output...
|
||||
* @param bool $bUseSymbolicLinks
|
||||
* @param bool $bSkipTempDir
|
||||
* @throws Exception
|
||||
* @return void
|
||||
*/
|
||||
public function Compile($sTargetDir, $oP = null, $bUseSymbolicLinks = false)
|
||||
public function Compile($sTargetDir, $oP = null, $bUseSymbolicLinks = false, $bSkipTempDir = false)
|
||||
{
|
||||
$sFinalTargetDir = $sTargetDir;
|
||||
if ($bUseSymbolicLinks)
|
||||
if ($bUseSymbolicLinks || $bSkipTempDir)
|
||||
{
|
||||
// Skip the creation of a temporary dictionary, not compatible with symbolic links
|
||||
$sTempTargetDir = $sFinalTargetDir;
|
||||
@@ -480,16 +481,16 @@ EOF;
|
||||
{
|
||||
$this->Log("Compilation of module $sModuleName in version $sModuleVersion produced not code at all. No file written.");
|
||||
}
|
||||
|
||||
|
||||
// files to include (PHP datamodels)
|
||||
foreach($oModule->GetFilesToInclude('business') as $sRelFileName)
|
||||
{
|
||||
$aDataModelFiles[] = "MetaModel::IncludeModule('".basename($sFinalTargetDir).'/'.$sRelativeDir.'/'.$sRelFileName."');";
|
||||
$aDataModelFiles[] = "MetaModel::IncludeModule(MODULESROOT.'/$sRelativeDir/$sRelFileName');";
|
||||
}
|
||||
// files to include (PHP webservices providers)
|
||||
foreach($oModule->GetFilesToInclude('webservices') as $sRelFileName)
|
||||
{
|
||||
$aWebservicesFiles[] = "MetaModel::IncludeModule('".basename($sFinalTargetDir).'/'.$sRelativeDir.'/'.$sRelFileName."');";
|
||||
$aWebservicesFiles[] = "MetaModel::IncludeModule(MODULESROOT.'/$sRelativeDir/$sRelFileName');";
|
||||
}
|
||||
} // foreach module
|
||||
|
||||
@@ -577,7 +578,7 @@ EOF;
|
||||
EOF
|
||||
;
|
||||
|
||||
$sPHPFileContent .= "\nMetaModel::IncludeModule('".basename($sFinalTargetDir)."/core/main.php');\n";
|
||||
$sPHPFileContent .= "\nMetaModel::IncludeModule(MODULESROOT.'/core/main.php');\n";
|
||||
$sPHPFileContent .= implode("\n", $aDataModelFiles);
|
||||
$sPHPFileContent .= implode("\n", $aWebservicesFiles);
|
||||
$sPHPFileContent .= "\nfunction GetModulesInfo()\n{\nreturn ".var_export($aModulesInfo, true).";\n}\n";
|
||||
|
||||
@@ -40,20 +40,55 @@ define ('DATAMODEL_MODULE', 'datamodel'); // Convention to store the version of
|
||||
|
||||
class RunTimeEnvironment
|
||||
{
|
||||
/**
|
||||
* The name of the environment that the caller wants to build
|
||||
* @var string sFinalEnv
|
||||
*/
|
||||
protected $sFinalEnv;
|
||||
|
||||
/**
|
||||
* Environment into which the build will be performed
|
||||
* @var string sTargetEnv
|
||||
*/
|
||||
protected $sTargetEnv;
|
||||
|
||||
|
||||
/**
|
||||
* Extensions map of the source environment
|
||||
* @var iTopExtensionsMap
|
||||
*/
|
||||
protected $oExtensionsMap;
|
||||
|
||||
public function __construct($sEnvironment = 'production')
|
||||
|
||||
/**
|
||||
* Toolset for building a run-time environment
|
||||
*
|
||||
* @param string $sEnvironment (e.g. 'test')
|
||||
* @param bool $bAutoCommit (make the target environment directly, or build a temporary one)
|
||||
*/
|
||||
public function __construct($sEnvironment = 'production', $bAutoCommit = true)
|
||||
{
|
||||
$this->sTargetEnv = $sEnvironment;
|
||||
$this->sFinalEnv = $sEnvironment;
|
||||
if ($bAutoCommit)
|
||||
{
|
||||
// Build directly onto the requested environment
|
||||
$this->sTargetEnv = $sEnvironment;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Build into a temporary target
|
||||
$this->sTargetEnv = $sEnvironment.'-build';
|
||||
}
|
||||
$this->oExtensionsMap = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the full path to the compiled code (do not use after commit)
|
||||
* @return string
|
||||
*/
|
||||
public function GetBuildDir()
|
||||
{
|
||||
return APPROOT.'env-'.$this->sTargetEnv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback function for logging the queries run by the setup.
|
||||
* According to the documentation the function must be defined before passing it to call_user_func...
|
||||
@@ -429,7 +464,7 @@ class RunTimeEnvironment
|
||||
}
|
||||
}
|
||||
while($bModuleAdded);
|
||||
|
||||
|
||||
$sDeltaFile = APPROOT.'data/'.$this->sTargetEnv.'.delta.xml';
|
||||
if (file_exists($sDeltaFile))
|
||||
{
|
||||
@@ -495,11 +530,12 @@ class RunTimeEnvironment
|
||||
// No delta was loaded, let's save the datamodel now
|
||||
$oFactory->SaveToFile(APPROOT.'data/datamodel-'.$this->sTargetEnv.'.xml');
|
||||
}
|
||||
|
||||
|
||||
$sTargetDir = APPROOT.'env-'.$this->sTargetEnv;
|
||||
self::MakeDirSafe($sTargetDir);
|
||||
$bSkipTempDir = ($this->sFinalEnv != $this->sTargetEnv); // No need for a temporary directory if sTargetEnv is already a temporary directory
|
||||
$oMFCompiler = new MFCompiler($oFactory);
|
||||
$oMFCompiler->Compile($sTargetDir, null, $bUseSymLinks);
|
||||
$oMFCompiler->Compile($sTargetDir, null, $bUseSymLinks, $bSkipTempDir);
|
||||
|
||||
$sCacheDir = APPROOT.'data/cache-'.$this->sTargetEnv;
|
||||
SetupUtils::builddir($sCacheDir);
|
||||
@@ -653,7 +689,7 @@ class RunTimeEnvironment
|
||||
$oConfig->Set('access_mode', $iPrevAccessMode);
|
||||
}
|
||||
|
||||
public function RecordInstallation(Config $oConfig, $sDataModelVersion, $aSelectedModuleCodes, $aSelectedExtensionCodes, $sModulesRelativePath, $sShortComment = null)
|
||||
public function RecordInstallation(Config $oConfig, $sDataModelVersion, $aSelectedModuleCodes, $aSelectedExtensionCodes, $sShortComment = null)
|
||||
{
|
||||
// Have it work fine even if the DB has been set in read-only mode for the users
|
||||
$iPrevAccessMode = $oConfig->Get('access_mode');
|
||||
@@ -698,7 +734,7 @@ class RunTimeEnvironment
|
||||
// Record installed modules and extensions
|
||||
//
|
||||
$aAvailableExtensions = array();
|
||||
$aAvailableModules = $this->AnalyzeInstallation($oConfig, APPROOT.$sModulesRelativePath);
|
||||
$aAvailableModules = $this->AnalyzeInstallation($oConfig, $this->GetBuildDir());
|
||||
foreach($aSelectedModuleCodes as $sModuleId)
|
||||
{
|
||||
$aModuleData = $aAvailableModules[$sModuleId];
|
||||
@@ -870,4 +906,122 @@ class RunTimeEnvironment
|
||||
}
|
||||
return $oLatestDM->Get('version');
|
||||
}
|
||||
|
||||
public function Commit()
|
||||
{
|
||||
if ($this->sFinalEnv != $this->sTargetEnv)
|
||||
{
|
||||
$this->CommitFile(
|
||||
APPROOT.'data/'.$this->sTargetEnv.'.delta.xml',
|
||||
APPROOT.'data/'.$this->sFinalEnv.'.delta.xml',
|
||||
false
|
||||
);
|
||||
$this->CommitFile(
|
||||
APPROOT.'data/datamodel-'.$this->sTargetEnv.'.xml',
|
||||
APPROOT.'data/datamodel-'.$this->sFinalEnv.'.xml'
|
||||
);
|
||||
$this->CommitFile(
|
||||
APPROOT.'data/datamodel-'.$this->sTargetEnv.'-with-delta.xml',
|
||||
APPROOT.'data/datamodel-'.$this->sFinalEnv.'-with-delta.xml',
|
||||
false
|
||||
);
|
||||
$this->CommitDir(
|
||||
APPROOT.'data/'.$this->sTargetEnv.'-modules/',
|
||||
APPROOT.'data/'.$this->sFinalEnv.'-modules/',
|
||||
false
|
||||
);
|
||||
$this->CommitDir(
|
||||
APPROOT.'data/cache-'.$this->sTargetEnv,
|
||||
APPROOT.'data/cache-'.$this->sFinalEnv,
|
||||
false
|
||||
);
|
||||
$this->CommitDir(
|
||||
APPROOT.'env-'.$this->sTargetEnv,
|
||||
APPROOT.'env-'.$this->sFinalEnv
|
||||
);
|
||||
|
||||
$sTargetConfig = APPCONF.$this->sTargetEnv.'/config-itop.php';
|
||||
$sFinalConfig = APPCONF.$this->sFinalEnv.'/config-itop.php';
|
||||
@chmod($sFinalConfig, 0770); // In case it exists: RWX for owner and group, nothing for others
|
||||
$this->CommitFile($sTargetConfig, $sFinalConfig);
|
||||
@chmod($sFinalConfig, 0440); // Read-only for owner and group, nothing for others
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Overwrite or create the destination file
|
||||
*
|
||||
* @param $sSource
|
||||
* @param $sDest
|
||||
* @param bool $bSourceMustExist
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function CommitFile($sSource, $sDest, $bSourceMustExist = true)
|
||||
{
|
||||
if (file_exists($sSource))
|
||||
{
|
||||
SetupUtils::builddir(dirname($sDest));
|
||||
if (file_exists($sDest))
|
||||
{
|
||||
$bRes = @unlink($sDest);
|
||||
if (!$bRes)
|
||||
{
|
||||
throw new Exception('Commit - Failed to cleanup destination file: '.$sDest);
|
||||
}
|
||||
}
|
||||
rename($sSource, $sDest);
|
||||
}
|
||||
else
|
||||
{
|
||||
// The file does not exist
|
||||
if ($bSourceMustExist)
|
||||
{
|
||||
throw new Exception('Commit - Missing file: '.$sSource);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Align the destination with the source... make sure there is NO file
|
||||
if (file_exists($sDest))
|
||||
{
|
||||
$bRes = @unlink($sDest);
|
||||
if (!$bRes)
|
||||
{
|
||||
throw new Exception('Commit - Failed to cleanup destination file: '.$sDest);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Overwrite or create the destination directory
|
||||
*
|
||||
* @param $sSource
|
||||
* @param $sDest
|
||||
* @param bool $bSourceMustExist
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function CommitDir($sSource, $sDest, $bSourceMustExist = true)
|
||||
{
|
||||
if (file_exists($sSource))
|
||||
{
|
||||
SetupUtils::movedir($sSource, $sDest);
|
||||
}
|
||||
else
|
||||
{
|
||||
// The file does not exist
|
||||
if ($bSourceMustExist)
|
||||
{
|
||||
throw new Exception('Commit - Missing directory: '.$sSource);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Align the destination with the source... make sure there is NO file
|
||||
if (file_exists($sDest))
|
||||
{
|
||||
SetupUtils::rrmdir($sDest);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // End of class
|
||||
|
||||
Reference in New Issue
Block a user