N°8760: revert dry removal audit and use real file deletion again

code formatting
This commit is contained in:
odain
2025-12-04 16:51:02 +01:00
parent ae980e365d
commit 9f3d7d2c36
20 changed files with 121 additions and 126 deletions

View File

@@ -462,7 +462,6 @@ abstract class MetaModel
return call_user_func([$sClass, 'GetClassDescription'], $sClass);
}
/**
* @param string $sClass
*

View File

@@ -26,23 +26,12 @@ use Composer\Semver\VersionParser;
*/
class InstalledVersions
{
/**
* @var string|null if set (by reflection by Composer), this should be set to the path where this class is being copied to
* @internal
*/
private static $selfDir = null;
/**
* @var mixed[]|null
* @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}|array{}|null
*/
private static $installed;
/**
* @var bool
*/
private static $installedIsLocalDir;
/**
* @var bool|null
*/
@@ -320,24 +309,6 @@ class InstalledVersions
{
self::$installed = $data;
self::$installedByVendor = array();
// when using reload, we disable the duplicate protection to ensure that self::$installed data is
// always returned, but we cannot know whether it comes from the installed.php in __DIR__ or not,
// so we have to assume it does not, and that may result in duplicate data being returned when listing
// all installed packages for example
self::$installedIsLocalDir = false;
}
/**
* @return string
*/
private static function getSelfDir()
{
if (self::$selfDir === null) {
self::$selfDir = strtr(__DIR__, '\\', '/');
}
return self::$selfDir;
}
/**
@@ -354,9 +325,7 @@ class InstalledVersions
$copiedLocalDir = false;
if (self::$canGetVendors) {
$selfDir = self::getSelfDir();
foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
$vendorDir = strtr($vendorDir, '\\', '/');
if (isset(self::$installedByVendor[$vendorDir])) {
$installed[] = self::$installedByVendor[$vendorDir];
} elseif (is_file($vendorDir.'/composer/installed.php')) {
@@ -364,14 +333,11 @@ class InstalledVersions
$required = require $vendorDir.'/composer/installed.php';
self::$installedByVendor[$vendorDir] = $required;
$installed[] = $required;
if (self::$installed === null && $vendorDir.'/composer' === $selfDir) {
if (strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
self::$installed = $required;
self::$installedIsLocalDir = true;
$copiedLocalDir = true;
}
}
if (self::$installedIsLocalDir && $vendorDir.'/composer' === $selfDir) {
$copiedLocalDir = true;
}
}
}

View File

@@ -3,7 +3,7 @@
'name' => 'combodo/itop',
'pretty_version' => 'dev-develop',
'version' => 'dev-develop',
'reference' => '19d062aa830b6d6c7d17ac4046fc9ee2c5e3fab1',
'reference' => '469afdb2f9aea1b6e078a2a5bb12f09a969d60e0',
'type' => 'project',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
@@ -22,7 +22,7 @@
'combodo/itop' => array(
'pretty_version' => 'dev-develop',
'version' => 'dev-develop',
'reference' => '19d062aa830b6d6c7d17ac4046fc9ee2c5e3fab1',
'reference' => '469afdb2f9aea1b6e078a2a5bb12f09a969d60e0',
'type' => 'project',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),

View File

@@ -2,13 +2,13 @@
namespace Combodo\iTop\Setup\FeatureRemoval;
use iTopExtensionsMap;
use MetaModel;
use RunTimeEnvironment;
use SetupUtils;
class DryRemovalRuntimeEnvironment extends RunTimeEnvironment
{
const DRY_REMOVAL_AUDIT_ENV = "extension-removal";
public const DRY_REMOVAL_AUDIT_ENV = "extension-removal";
protected array $aExtensionsByCode;
private bool $bExtensionMapModified = false;
@@ -37,18 +37,49 @@ class DryRemovalRuntimeEnvironment extends RunTimeEnvironment
$sEnv = $this->sFinalEnv;
$this->aExtensionsByCode = $aExtensionCodesToRemove;
SetupUtils::rrmdir(APPROOT."/data/$sEnv-modules");
SetupUtils::copydir(APPROOT."/data/$sSourceEnv-modules", APPROOT."/data/".$this->sFinalEnv."-modules");
//SetupUtils::rrmdir(APPROOT."/data/$sEnv-modules");
$this->Cleanup();
SetupUtils::copydir(APPROOT."/data/$sSourceEnv-modules", APPROOT."/data/$sEnv-modules");
/*$oDryRemovalConfig = clone(MetaModel::GetConfig());
if (count($aExtensionCodesToRemove) > 0) {
$this->RemoveExtensionsLocally($aExtensionCodesToRemove);
}
$oDryRemovalConfig = clone(MetaModel::GetConfig());
$oDryRemovalConfig->ChangeModulesPath($sSourceEnv, $this->sFinalEnv);
$this->WriteConfigFileSafe($oDryRemovalConfig);*/
$this->WriteConfigFileSafe($oDryRemovalConfig);
}
private function RemoveExtensionsLocally(array $aExtensionCodes): void
{
$oExtensionsMap = new \iTopExtensionsMap($this->sFinalEnv);
foreach ($aExtensionCodes as $sCode) {
/** @var \iTopExtension $oExtension */
$oExtension = $oExtensionsMap->Get($sCode);
if (!is_null($oExtension)) {
$sDir = $oExtension->sSourceDir;
\IssueLog::Info(__METHOD__.": remove extension locally", null, [$oExtension->sCode => $sDir]);
SetupUtils::rrmdir($sDir);
} else {
\IssueLog::Warning(__METHOD__." cannot find extensions", null, ['env' => $this->sFinalEnv, 'code' => $sCode]);
}
}
}
public function Cleanup()
{
$sEnv = $this->sFinalEnv;
SetupUtils::rrmdir(APPROOT."/data/$sEnv-modules");
SetupUtils::rrmdir(APPROOT."/data/cache-$sEnv");
SetupUtils::rrmdir(APPROOT."/env-$sEnv");
SetupUtils::rrmdir(APPROOT."/conf/$sEnv");
@unlink(APPROOT."/data/datamodel-$sEnv.xml");
}
/**
* @return \iTopExtensionsMap|null
*/
protected function GetExtensionMap(): ?iTopExtensionsMap
/*protected function GetExtensionMap(): ?iTopExtensionsMap
{
if (is_null(parent::GetExtensionMap())) {
return null;
@@ -62,5 +93,5 @@ class DryRemovalRuntimeEnvironment extends RunTimeEnvironment
}
return parent::GetExtensionMap();
}
}
}*/
}

View File

@@ -35,7 +35,7 @@ class ModelReflectionSerializer
$iRes = 0;
exec(sprintf("$sPHPExec %s/get_model_reflection.php --env='%s'", __DIR__, $sEnv), $sOutput, $iRes);
if ($iRes != 0) {
\IssueLog::Error("Cannot get classes", null, ['code' => $iRes, "output" => $sOutput]);
\IssueLog::Error("Cannot get classes", null, ['env' => $sEnv, 'code' => $iRes, "output" => $sOutput]);
throw new CoreException("Cannot get classes");
}
@@ -52,4 +52,4 @@ class ModelReflectionSerializer
return $aClasses;
}
}
}

View File

@@ -11,7 +11,7 @@ require_once APPROOT.'setup/feature_removal/ModelReflectionSerializer.php';
class SetupAudit
{
//file used when present to trigger audit exception when testing specific setups
const GETISSUE_ERROR_MSG_FILE_FORTESTONLY = '.setup_audit_error_msg.txt';
public const GETISSUE_ERROR_MSG_FILE_FORTESTONLY = '.setup_audit_error_msg.txt';
private string $sEnvBeforeExtensionRemoval;
private string $sEnvAfterExtensionRemoval;
@@ -123,4 +123,4 @@ class SetupAudit
return $oSet->Count();
}
}
}

View File

@@ -2,9 +2,7 @@
require_once(dirname(__DIR__, 2).'/approot.inc.php');
require_once(APPROOT.'application/application.inc.php');
$sEnv = null;
if (isset($argv)) {
foreach ($argv as $iArg => $sArg) {
if (preg_match('/^--env=(.*)$/', $sArg, $aMatches)) {
@@ -22,11 +20,12 @@ $sConfFile = utils::GetConfigFilePath($sEnv);
try {
MetaModel::Startup($sConfFile, false /* $bModelOnly */, true /* $bAllowCache */, false /* $bTraceSourceFiles */, $sEnv);
}
catch (\Throwable $e) {
} catch (\Throwable $e) {
echo $e->getMessage();
echo $e->getTraceAsString();
\SetupLog::Error("Cannot read model from provided environment", null,
\SetupLog::Error(
"Cannot read model from provided environment",
null,
[
'env' => $sEnv,
'error' => $e->getMessage(),
@@ -39,4 +38,4 @@ catch (\Throwable $e) {
$aClasses = MetaModel::GetClasses();
echo json_encode($aClasses);
echo json_encode($aClasses);

View File

@@ -2173,4 +2173,4 @@ class SetupInfo
{
return (array_key_exists($sModuleId, self::$aSelectedModules));
}
}
}

View File

@@ -681,4 +681,4 @@ class Step3 extends WizardStep
}
}
End of the example */
End of the example */

View File

@@ -2127,9 +2127,7 @@ class WizStepSummary extends WizardStep
//$oSetupAudit->AuditExtensionsCleanupRules(true);
//}
*/
}
catch(MissingDependencyException $e)
{
} catch (MissingDependencyException $e) {
$this->bDependencyCheck = false;
$this->sDependencyIssue = $e->getHtmlDesc();
}
@@ -2596,4 +2594,4 @@ class WizStepDone extends WizardStep
$oPage->add(file_get_contents($sBackupFile));
}
}
}
}

View File

@@ -64,7 +64,7 @@ abstract class ItopCustomDatamodelTestCase extends ItopDataTestCase
protected function setUp(): void
{
static::LoadRequiredItopFiles();
static::LoadRequiredItopFiles();
if (is_null($this->oEnvironment)) {
$this->oEnvironment = new UnitTestRunTimeEnvironment($this->GetTestEnvironment());
}
@@ -133,7 +133,6 @@ abstract class ItopCustomDatamodelTestCase extends ItopDataTestCase
// Note: To improve performances, we compile all XML deltas from test cases derived from this class and make a single environment where everything will be ran at once.
// This requires XML deltas to be compatible, but it is a known and accepted trade-off. See PR #457
if (false === $this->IsEnvironmentReady()) {
$this->debug("Preparing custom environment '$sTestEnv' with the following datamodel files:");
foreach ($this->oEnvironment->GetCustomDatamodelFiles() as $sCustomDatamodelFile) {
$this->debug(" - $sCustomDatamodelFile");
@@ -190,8 +189,10 @@ abstract class ItopCustomDatamodelTestCase extends ItopDataTestCase
CMDBSource::Query("CREATE TABLE $sNewDB.priv_module_install SELECT * FROM $sPreviousDB.priv_module_install");
$this->debug("Custom environment '$sTestEnv' is ready!");
} else {
$this->debug("Custom environment '$sTestEnv' READY BUILT:");
}
parent::PrepareEnvironment();
}
}
}

View File

@@ -46,11 +46,6 @@ class UnitTestRunTimeEnvironment extends RunTimeEnvironment
*/
protected $aAdditionExtensionFoldersByCode = null;
public function GetEnvironment(): string
{
return $this->sFinalEnv;
}
public function CompileFrom($sSourceEnv, $bUseSymLinks = null)
{
$sDestModulesDir = APPROOT.'data/'.$this->sTargetEnv.'-modules/';

View File

@@ -26,4 +26,4 @@ class ModelSerializationTest extends ItopDataTestCase
$this->expectExceptionMessage("Cannot get classes");
ModelReflectionSerializer::GetInstance()->GetModelFromEnvironment('gabuzomeu');
}
}
}

View File

@@ -10,7 +10,7 @@ use Exception;
class SetupAuditTest extends ItopCustomDatamodelTestCase
{
const ENVT = 'php-unit-extensionremoval-tests';
public const ENVT = 'php-unit-extensionremoval-tests';
public function GetDatamodelDeltaAbsPath(): string
{
@@ -115,4 +115,4 @@ class SetupAuditTest extends ItopCustomDatamodelTestCase
$this->expectExceptionMessage('FinalClassFeature1Module1MyFinalClassFromLocation');
$oSetupAudit->GetIssues(true);
}
}
}

View File

@@ -1,4 +1,5 @@
<?php
//// PHP Data Model definition file
//
//// WARNING - WARNING - WARNING
@@ -12,4 +13,4 @@
//// The recommended way to define new classes (for iTop 2.0) is via the XML definition.
//// This file remains in the module's template only for the cases where there is:
//// - either no new class or menu defined in the XML file
//// - or no XML file at all supplied by the module
//// - or no XML file at all supplied by the module

View File

@@ -1,4 +1,5 @@
<?php
/*
* @copyright Copyright (C) 2010-2021 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
@@ -11,7 +12,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'finalclass_ext1_module1/6.6.6',
array(
[
// Identification
//
'label' => 'Ext For Test',
@@ -19,32 +20,32 @@ SetupWebPage::AddModule(
// Setup
//
'dependencies' => array(
'itop-structure/3.2.0',
),
'dependencies' => [
'itop-structure/3.2.0',
],
'mandatory' => false,
'visible' => true,
'installer' => '',
// Components
//
'datamodel' => array(
'datamodel' => [
'model.finalclass_ext1_module1.php',
),
'webservice' => array(),
'data.struct' => array(// add your 'structure' definition XML files here,
),
'data.sample' => array(// add your sample data XML files here,
),
],
'webservice' => [],
'data.struct' => [// add your 'structure' definition XML files here,
],
'data.sample' => [// add your sample data XML files here,
],
// Documentation
//
'doc.manual_setup' => '', // hyperlink to manual setup documentation, if any
'doc.more_information' => '', // hyperlink to more information, if any
'doc.more_information' => '', // hyperlink to more information, if any
// Default settings
//
'settings' => array(// Module specific settings go here, if any
),
)
);
'settings' => [// Module specific settings go here, if any
],
]
);

View File

@@ -1,4 +1,5 @@
<?php
//// PHP Data Model definition file
//
//// WARNING - WARNING - WARNING
@@ -12,4 +13,4 @@
//// The recommended way to define new classes (for iTop 2.0) is via the XML definition.
//// This file remains in the module's template only for the cases where there is:
//// - either no new class or menu defined in the XML file
//// - or no XML file at all supplied by the module
//// - or no XML file at all supplied by the module

View File

@@ -1,4 +1,5 @@
<?php
/*
* @copyright Copyright (C) 2010-2021 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
@@ -11,7 +12,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'finalclass_ext2_module1/6.6.6',
array(
[
// Identification
//
'label' => 'Ext For Test',
@@ -19,32 +20,32 @@ SetupWebPage::AddModule(
// Setup
//
'dependencies' => array(
'itop-structure/3.2.0',
),
'dependencies' => [
'itop-structure/3.2.0',
],
'mandatory' => false,
'visible' => true,
'installer' => '',
// Components
//
'datamodel' => array(
'datamodel' => [
'model.finalclass_ext2_module1.php',
),
'webservice' => array(),
'data.struct' => array(// add your 'structure' definition XML files here,
),
'data.sample' => array(// add your sample data XML files here,
),
],
'webservice' => [],
'data.struct' => [// add your 'structure' definition XML files here,
],
'data.sample' => [// add your sample data XML files here,
],
// Documentation
//
'doc.manual_setup' => '', // hyperlink to manual setup documentation, if any
'doc.more_information' => '', // hyperlink to more information, if any
'doc.more_information' => '', // hyperlink to more information, if any
// Default settings
//
'settings' => array(// Module specific settings go here, if any
),
)
);
'settings' => [// Module specific settings go here, if any
],
]
);

View File

@@ -1,4 +1,5 @@
<?php
//// PHP Data Model definition file
//
//// WARNING - WARNING - WARNING
@@ -12,4 +13,4 @@
//// The recommended way to define new classes (for iTop 2.0) is via the XML definition.
//// This file remains in the module's template only for the cases where there is:
//// - either no new class or menu defined in the XML file
//// - or no XML file at all supplied by the module
//// - or no XML file at all supplied by the module

View File

@@ -1,4 +1,5 @@
<?php
/*
* @copyright Copyright (C) 2010-2021 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
@@ -11,7 +12,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'nominal_ext1_module1/6.6.6',
array(
[
// Identification
//
'label' => 'Ext For Test',
@@ -19,32 +20,32 @@ SetupWebPage::AddModule(
// Setup
//
'dependencies' => array(
'itop-structure/3.2.0',
),
'dependencies' => [
'itop-structure/3.2.0',
],
'mandatory' => false,
'visible' => true,
'installer' => '',
// Components
//
'datamodel' => array(
'datamodel' => [
'model.nominal_ext1_module1.php',
),
'webservice' => array(),
'data.struct' => array(// add your 'structure' definition XML files here,
),
'data.sample' => array(// add your sample data XML files here,
),
],
'webservice' => [],
'data.struct' => [// add your 'structure' definition XML files here,
],
'data.sample' => [// add your sample data XML files here,
],
// Documentation
//
'doc.manual_setup' => '', // hyperlink to manual setup documentation, if any
'doc.more_information' => '', // hyperlink to more information, if any
'doc.more_information' => '', // hyperlink to more information, if any
// Default settings
//
'settings' => array(// Module specific settings go here, if any
),
)
);
'settings' => [// Module specific settings go here, if any
],
]
);