No description
Find a file
2026-04-10 07:15:57 +00:00
.gitignore better change file handling 2026-04-10 07:15:57 +00:00
config_selector.py better change file handling 2026-04-10 07:15:57 +00:00
ignored_files-example.yml better change file handling 2026-04-10 07:15:57 +00:00
ignored_files.yml better change file handling 2026-04-10 07:15:57 +00:00
README.md better change file handling 2026-04-10 07:15:57 +00:00

Drupal Configuration Selector

A Python utility to selectively copy configuration files from a source directory to a target directory based on file prefixes.

Overview

This script helps you manage and transfer specific Drupal configuration files by:

  • Reading a list of configuration file prefixes from a JSON file
  • Identifying matching files in a source directory
  • Copying selected files to a target directory
  • Providing a TUI (Text User Interface) to manage the selection process

Requirements

  • Python 3.6+
  • curses library (built into most Python installations on Linux/Mac)
  • PyYAML library (install with: pip install pyyaml)

Installation and Setup

The script operates in the current working directory where you run it. It will create the following subdirectories if they don't exist:

  • ingest/ - Drop your exported Drupal config archive here (named config*.tar.gz)
  • original_config/ - YAML files are extracted here automatically from the ingest archive
  • new_recipe_config/ - Matched files will be copied here (with UUID and _core removed)
  • changed_files/ - Files that changed between versions will be placed here
  • ignored_files.yml - Optional: List files to exclude from change tracking
  • deleted_files.csv - Tracks files that should be deleted

Usage

Ingest: export from Drupal into ingest/

  1. In the Drupal admin UI, open the full configuration export page: Configuration → Development → Configuration synchronization → Export, then use the Full archive export (direct URL path: admin/config/development/configuration/full/export).
  2. Download the generated archive (a .tar.gz of all site configuration).
  3. Place that file in the ingest/ directory under this tools working directory. The filename must match config*.tar.gz (for example config.tar.gz as downloaded, or a descriptive name like config-localhost_3001-2026-04-09.tar.gz).
  4. Run python3 config_selector.py (or python3 config_selector.py --force if original_config/ already has files and you want to replace them from the new archive).

Standard run (skip extraction if original_config/ already has files)

python3 config_selector.py

Force re-extraction from the ingest archive

Use --force when you have placed a new archive in ingest/ and want to replace the current original_config/ contents:

python3 config_selector.py --force

Workflow

  1. Follow Ingest above to place a full export config*.tar.gz in ingest/.
  2. Run the script. It extracts the archive into original_config/ automatically (skipped on subsequent runs unless --force is passed).
  3. The script will create a default config_prefixes.json in the current directory if it doesn't exist.
  4. Use the TUI to manage your file selections and copy files.

Hierarchical Navigation

The script organizes configuration files in a tree-like structure based on dot-separated prefixes:

  • Files like field.storage.node.comment.yml are split into segments: field > field.storage > field.storage.node > etc.
  • Use RIGHT ARROW to navigate deeper into a selected prefix
  • Use LEFT ARROW to go back up one level in the hierarchy
  • At each level, you see only the unique segments available at that level
  • Each segment shows the total count of files under it
  • Segments with children have a "▶" indicator
  • You can perform actions (add, delete, select files) at any level in the hierarchy

TUI Navigation

The Text User Interface provides the following controls:

  • UP/DOWN: Navigate through the list of prefixes
  • LEFT/RIGHT: Navigate through the hierarchy tree (drill down/go back)
  • SPACE: Toggle between matched and unmatched prefixes view
  • ENTER: Select individual files from the selected prefix
  • A: Add a new prefix (press ESC or Enter with empty input to cancel)
  • O: Choose a prefix from the list of unmatched prefixes
  • D: Delete the selected prefix (in matched view) or add the selected prefix (in unmatched view)
  • C: Copy all matched files to the new_recipe_config directory (with UUID and _core removal)
  • M: Compare committed recipe vs new_recipe_config, copy new/modified to changed_files/, list deletions
  • S: Save the current list of prefixes to the JSON file
  • Q: Quit the application

Individual File Selection

When you press ENTER on a prefix, a dialog opens that allows you to:

  • In matched view: Select individual files to remove from the matching set
  • In unmatched view: Select individual files to add to a matching prefix

Within the file selection dialog:

  • Use UP/DOWN to navigate between files
  • Press SPACE to toggle selection of a file
  • Press ENTER to confirm your selection
  • Press ESC to cancel

Configuration File

The script uses a JSON file to store prefixes. The default file is created at first run:

{
  "prefixes": [
    "put.your.prefixes.here"
  ]
}

You can modify this file directly or use the TUI to manage the prefixes.

File Comparison and Change Tracking

The script can compare configuration files between recipe versions:

  • M: Compare committed recipe to new_recipe_config/
    • Baseline: recipes/wisski_default_data_model/config/ (committed recipe)
    • New files: present in new_recipe_config/ but not in the committed recipe → copied to changed_files/ (same layout, including language/<lang>/…)
    • Modified files: same relative path in both, different content → copied to changed_files/
    • Deleted files: present in the committed recipe but missing from new_recipe_config/ → listed in deleted_files.csv
    • Each compare run clears changed_files/ first, then repopulates it
    • changed_files_manifest.csv lists every copied path with kind = new or modified

Files matched in ignored_files.yml are not copied to changed_files/ (whether new or modified).

This feature helps you track additions, updates, and removals relative to the committed recipe.

Ignoring Files from Change Tracking

You can create an ignored_files.yml file to prevent specific configuration files from being copied to the changed_files/ folder during comparison (for both new and modified paths). This is useful when certain files have intentional differences or should not be promoted from the export.

Example ignored_files.yml:

field:
  name: field.field.wisski_individual.bb48a22d36f1c15cd16b143d23466812.field__vf__title
  reason: because we need target id instead of uuid
another_category:
  name: some.other.config.file.yml
  reason: custom modification required

Files listed in this YAML will be excluded from the changed_files/ directory even if they are new or changed relative to the committed recipe.

Directory Structure

/your/working/directory/
├── config_selector.py                          # Main script
├── config_prefixes.json                        # Configuration prefixes list
├── ignored_files.yml                           # Optional: List of files to ignore from change tracking
├── ingest/                                     # Drop config*.tar.gz archives here
├── original_config/                            # Extracted source YAML files (auto-populated from ingest/)
├── new_recipe_config/                          # Target directory where matched files will be copied (cleaned)
├── recipes/wisski_default_data_model/config/   # Committed recipe config (used as baseline for comparison)
├── changed_files/                              # New + modified YAML vs committed recipe (cleared each compare)
├── changed_files_manifest.csv                  # relative_path + kind (new|modified) for changed_files/
├── new_recipe_not_in_original.csv              # Paths in new_recipe_config missing from original export
└── deleted_files.csv                           # Paths in committed recipe missing from new_recipe_config