Skip to content

Commit

Permalink
Merge pull request #2088 from drush-ops/fix-config-import-partial
Browse files Browse the repository at this point in the history
Fix #2069. config-import --partial works at too low a level.
  • Loading branch information
weitzman committed Mar 21, 2016
2 parents 0f911f9 + f4cc045 commit 6ad39a8
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 46 deletions.
88 changes: 44 additions & 44 deletions commands/core/config.drush.inc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* Provides Configuration Management commands.
*/

use Drupal\config\StorageReplaceDataWrapper;
use Drush\Log\LogLevel;
use Drupal\Core\Config\StorageComparer;
use Drupal\Core\Config\ConfigImporter;
Expand Down Expand Up @@ -570,6 +571,7 @@ function drush_config_get_storage_filters() {
function drush_config_import($source = NULL) {
global $config_directories;

// Determine source directory.
if ($target = drush_get_option('source')) {
$source_dir = $target;
}
Expand All @@ -588,56 +590,62 @@ function drush_config_import($source = NULL) {
$source_dir = config_get_config_directory($source);
}

// Retrieve a list of differences between the active and source configuration (if any).
$source_storage = new FileStorage($source_dir);
// Determine $source_storage in partial and non-partial cases.
/** @var \Drupal\Core\Config\StorageInterface $active_storage */
$active_storage = Drupal::service('config.storage');
if (drush_get_option('partial')) {
$source_storage = new StorageReplaceDataWrapper($active_storage);
$file_storage = new FileStorage($source_dir);
foreach ($file_storage->listAll() as $name) {
$data = $file_storage->read($name);
$source_storage->replaceData($name, $data);
}
}
else {
$source_storage = new FileStorage($source_dir);
}

// If our configuration storage is being filtered, then attach all filters
// to the source storage object. We will use the filtered values uniformly
// for comparison, full imports, and partial imports.
$storage_filters = drush_config_get_storage_filters();
if (!empty($storage_filters)) {
$source_storage = new StorageWrapper($source_storage, $storage_filters);
}
if (drush_get_option('partial', FALSE)) {
// With partial imports, the comparison must only be made against configs
// that exist in the source directory.
$temp_active_storage = new FileStorage(drush_tempdir());
foreach ($source_storage->listAll() as $name) {
// Copy active storage to our temporary active store.
if ($existing = $active_storage->read($name)) {
$temp_active_storage->write($name, $existing);
}
}
$active_storage = $temp_active_storage;
}
$config_comparer = new StorageComparer($source_storage, $active_storage, Drupal::service('config.manager'));
if (!$config_comparer->createChangelist()->hasChanges()) {

/** @var \Drupal\Core\Config\ConfigManagerInterface $config_manager */
$config_manager = Drupal::service('config.manager');
$storage_comparer = new StorageComparer($source_storage, $active_storage, $config_manager);


if (!$storage_comparer->createChangelist()->hasChanges()) {
return drush_log(dt('There are no changes to import.'), LogLevel::OK);
}

if (drush_get_option('preview', 'list') == 'list') {
$change_list = array();
foreach ($config_comparer->getAllCollectionNames() as $collection) {
$change_list[$collection] = $config_comparer->getChangelist(NULL, $collection);
foreach ($storage_comparer->getAllCollectionNames() as $collection) {
$change_list[$collection] = $storage_comparer->getChangelist(NULL, $collection);
}
_drush_print_config_changes_table($change_list);
}
else {
$destination_dir = drush_tempdir();
drush_invoke_process('@self', 'config-export', array(), array('destination' => $destination_dir));
// @todo Can DiffFormatter produce a CLI pretty diff?
drush_shell_exec('diff -x %s -u %s %s', '*.git', $destination_dir, $source_dir);
// Copy active storage to the temporary directory.
$temp_dir = drush_tempdir();
$temp_storage = new FileStorage($temp_dir);
$source_dir_storage = new FileStorage($source_dir);
foreach ($source_dir_storage->listAll() as $name) {
if ($data = $active_storage->read($name)) {
$temp_storage->write($name, $data);
}
}
drush_shell_exec('diff -x %s -u %s %s', '*.git', $temp_dir, $source_dir);
$output = drush_shell_exec_output();
drush_print(implode("\n", $output));
}

if (drush_confirm(dt('Import the listed configuration changes?'))) {
if (drush_get_option('partial')) {
// Partial imports require different processing.
return drush_op('_drush_config_import_partial', $source_storage);
}
return drush_op('_drush_config_import', $config_comparer);
return drush_op('_drush_config_import', $storage_comparer);
}
}

Expand All @@ -660,7 +668,6 @@ function _drush_config_import(StorageComparer $storage_comparer) {
else{
try {
$config_importer->import();
drush_drupal_cache_clear_all();
drush_log('The configuration was imported successfully.', LogLevel::SUCCESS);
}
catch (ConfigException $e) {
Expand All @@ -678,24 +685,13 @@ function _drush_config_import(StorageComparer $storage_comparer) {
}
}

/**
* Imports a partial set of configurations.
*/
function _drush_config_import_partial(FileStorage $source) {
/** @var \Drupal\Core\Config\StorageInterface $active_storage */
$active_storage = Drupal::service('config.storage');
foreach ($source->listAll() as $name) {
$active_storage->write($name, $source->read($name));
}
}

/**
* Edit command callback.
*/
function drush_config_edit($config_name = '') {
// Identify and validate input.
if ($config_name) {
$config = Drupal::configFactory()->getEditable($config_name);
$config = Drupal::configFactory()->get($config_name);
if ($config->isNew()) {
return drush_set_error(dt('Config !name does not exist', array('!name' => $config_name)));
}
Expand All @@ -708,7 +704,7 @@ function drush_config_edit($config_name = '') {
}
else {
$config_name = $config_names[$choice];
$config = Drupal::configFactory()->getEditable($config_name);
$config = Drupal::configFactory()->get($config_name);
}
}

Expand All @@ -719,16 +715,20 @@ function drush_config_edit($config_name = '') {
$temp_storage = new FileStorage(drush_tempdir());
$temp_storage->write($config_name, $contents);

// $filepath = drush_save_data_to_temp_file();
$exec = drush_get_editor();
drush_shell_exec_interactive($exec, $temp_storage->getFilePath($config_name));

// Perform import operation if user did not immediately exit editor.
if (!drush_get_option('bg', FALSE)) {
$new_data = $temp_storage->read($config_name);
$temp_storage->delete($config_name);
$config->setData($new_data);
$config->save();
$new_storage = new StorageReplaceDataWrapper($active_storage);
$new_storage->replaceData($config_name, $new_data);
/** @var \Drupal\Core\Config\ConfigManagerInterface $config_manager */
$config_manager = Drupal::service('config.manager');
$storage_comparer = new StorageComparer($new_storage, $active_storage, $config_manager);
$storage_comparer->createChangelist();
return drush_op('_drush_config_import', $storage_comparer);
}
}

Expand Down
14 changes: 12 additions & 2 deletions tests/configTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ function testConfigList() {
function testConfigExportImport() {
$options = $this->options();
// Get path to sync dir.
$this->drush('core-status', array(), $options + array('format' => 'json'));
$this->drush('core-status', array('config-sync'), $options + array('format' => 'json'));
$sync = $this->webroot() . '/' . $this->getOutputFromJSON('config-sync');
$system_site_yml = $sync . '/system.site.yml';
$core_extension_yml = $sync . '/core.extension.yml';
Expand All @@ -54,7 +54,7 @@ function testConfigExportImport() {
$this->drush('config-export', array(), $options);
$this->assertFileExists($system_site_yml);

// Test import by finish the round trip.
// Test import by finishing the round trip.
$contents = file_get_contents($system_site_yml);
$contents = preg_replace('/front: .*/', 'front: unish', $contents);
$contents = file_put_contents($system_site_yml, $contents);
Expand All @@ -63,6 +63,16 @@ function testConfigExportImport() {
$page = $this->getOutputFromJSON('system.site:page');
$this->assertContains('unish', $page->front, 'Config was successfully imported.');

// Similar, but this time via --partial option.
$contents = file_get_contents($system_site_yml);
$contents = preg_replace('/front: .*/', 'front: unish partial', $contents);
$partial_path = UNISH_SANDBOX . '/system.site.yml';
$contents = file_put_contents($partial_path, $contents);
$this->drush('config-import', array(), $options + array('partial' => $partial_path));
$this->drush('config-get', array('system.site', 'page'), $options + array('format' => 'json'));
$page = $this->getOutputFromJSON('system.site:page');
$this->assertContains('unish partial', $page->front, '--partial was successfully imported.');

$this->drush('pm-enable', array('tracker'), $options);
$ignored_modules = array('skip-modules' => 'tracker');

Expand Down

0 comments on commit 6ad39a8

Please sign in to comment.