diff --git a/cache.inc.php b/cache.inc.php index 6fce811..041223c 100644 --- a/cache.inc.php +++ b/cache.inc.php @@ -289,7 +289,11 @@ class ConfigCacheFileMap function update(array $added, array $removed) { foreach($added as $file) - $this->file2deps[$file] = []; + { + //TODO: are we sure about this check? + if(isset($this->file2deps[$file])) + $this->file2deps[$file] = []; + } foreach($removed as $file) unset($this->file2deps[$file]); } @@ -361,6 +365,8 @@ class ConfigCacheUpdateParams function splitFilesByChunks(int $max_workers, bool $sort = true) : array { $flat = $this->affected_files->getFlatArray(); + if(!$flat) + return array(); if($sort) usort($flat, fn($a, $b) => $a[1] <=> $b[1]); diff --git a/config.inc.php b/config.inc.php index 4789c16..77ef68c 100644 --- a/config.inc.php +++ b/config.inc.php @@ -75,13 +75,19 @@ class ConfigManager } function getFileMap() : ConfigCacheFileMap + { + return $this->_getFileMap(null); + } + + private function _getFileMap(?ConfigDirFiles $files = null) : ConfigCacheFileMap { if($this->file_map === null) { $map = $this->_tryLoadMap(); if($map === null) - $map = $this->_makeMap($this->scanFiles(extension: '.js')); + $map = self::_makeMap($files ?? $this->scanFiles(extension: '.js')); $this->file_map = $map; + $this->_saveFileMap(); } return $this->file_map; } @@ -103,7 +109,7 @@ class ConfigManager $added_files = []; $removed_files = []; - $fs_cache_map = $this->_checkFileMap( + $this->_checkFileMap( $update_mode, $input_files, $added_files, @@ -113,7 +119,6 @@ class ConfigManager $affected_files = $this->_getAffectedFiles( $update_mode, $result_bundle_file, - $fs_cache_map, $input_files, $removed_files ); @@ -121,6 +126,8 @@ class ConfigManager //NOTE: at this poine taking into account only config files $affected_files->filter(fn($file) => str_ends_with($file, '.conf.js')); + config_log("Affected files: {$affected_files->count()}"); + $update_params = new ConfigCacheUpdateParams( globals: $this->globals, affected_files: $affected_files, @@ -131,6 +138,8 @@ class ConfigManager $this->cache->clear(); + $fs_cache_map = $this->getFileMap(); + //TODO: traverse all affected files and update file map foreach($affected_files as $file) { @@ -141,39 +150,27 @@ class ConfigManager if($affected_files->count() > 0 || $added_files || $removed_files) { $fs_cache_map->update($added_files, $removed_files); - $this->_saveMap($fs_cache_map); + $this->_saveFileMap(); } return $update_result; } - private function _checkFileMap(ConfigUpdateMode $update_mode, ConfigDirFiles $input_files, array &$added_files, array &$removed_files) : ConfigCacheFileMap + private function _checkFileMap(ConfigUpdateMode $update_mode, ConfigDirFiles $input_files, array &$added_files, array &$removed_files) { - $fs_cache_map = $this->file_map; - //NOTE: if there's no map so far we need to create one - if($fs_cache_map === null) - { - //let's re-use the input files - if($update_mode === ConfigUpdateMode::Full || $update_mode === ConfigUpdateMode::RelativeToBundle) - $tmp_files = $input_files; - else - $tmp_files = $this->scanFiles(extension: '.js'); - - $fs_cache_map = $this->_makeMap($tmp_files); - $this->file_map = $fs_cache_map; - } + $fs_cache_map = $this->_getFileMap($update_mode != ConfigUpdateMode::ChangedOnly ? $input_files : null); if($update_mode === ConfigUpdateMode::Full || $update_mode === ConfigUpdateMode::RelativeToBundle) { list($added_files, $removed_files) = $fs_cache_map->compare($input_files->getAllFiles()); config_log("File map added: ".count($added_files).", removed: ".count($removed_files)); } - - return $fs_cache_map; } - private function _getAffectedFiles(ConfigUpdateMode $update_mode, ?string $result_bundle_file, ConfigCacheFileMap $fs_cache_map, ConfigDirFiles $input_files, array $removed_files) : ConfigDirFiles + private function _getAffectedFiles(ConfigUpdateMode $update_mode, ?string $result_bundle_file, ConfigDirFiles $input_files, array $removed_files) : ConfigDirFiles { + $fs_cache_map = $this->getFileMap(); + $affected_files = null; if($update_mode === ConfigUpdateMode::Full) @@ -185,7 +182,7 @@ class ConfigManager if($result_bundle_file === null) throw new Exception("result_bundle_file argument is required"); - $affected_files = $this->newDirFiles(); + $affected_files = ConfigDirFiles::makeFor($this); foreach($input_files->getMap() as $base_dir => $files) { @@ -217,17 +214,26 @@ class ConfigManager } } } - else - throw new Exception("Unknown update mode: {$update_mode->value}"); + else if($update_mode === ConfigUpdateMode::ChangedOnly) + { + $affected_files = ConfigDirFiles::makeFor($this); + + foreach($input_files as $file) + { + $affected_files->addFile($file, unique: true); + + if(!str_ends_with($file, '.conf.js')) + { + $affected_by_file = $fs_cache_map->getAffectedFiles($file); + foreach($affected_by_file as $dep) + $affected_files->addFile($dep, unique: true); + } + } + } return $affected_files; } - function newDirFiles() : ConfigDirFiles - { - return new ConfigDirFiles([], $this->globals->base_dirs); - } - function parseFile(string $file) : ConfigParseResult { return config_parse($this->globals->base_dirs, $file); @@ -250,18 +256,17 @@ class ConfigManager return ConfigCacheFileMap::unserialize(ensure_read($this->_getMapPath())); } - private function _makeMap(ConfigDirFiles $files) : ConfigCacheFileMap + private static function _makeMap(ConfigDirFiles $files) : ConfigCacheFileMap { config_log("Creating file map"); $map = new ConfigCacheFileMap(); $map->update($files->getAllFiles(), []); - $this->_saveMap($map); return $map; } - private function _saveMap(ConfigCacheFileMap $map) + private function _saveFileMap() { - ensure_write($this->_getMapPath(), ConfigCacheFileMap::serialize($map)); + ensure_write($this->_getMapPath(), ConfigCacheFileMap::serialize($this->getFileMap())); } } diff --git a/scan.inc.php b/scan.inc.php index 90f502f..bc16376 100644 --- a/scan.inc.php +++ b/scan.inc.php @@ -22,6 +22,11 @@ class ConfigDirFiles implements \ArrayAccess, \Countable, \Iterator $this->base_dirs = $base_dirs; } + static function makeFor(ConfigManager $mgr) : ConfigDirFiles + { + return new ConfigDirFiles([], $mgr->getGlobals()->base_dirs); + } + function clear() { $this->base_dir2files = array();