Implement --merge mode for selective regeneration #26

Closed
opened 2026-01-03 23:39:51 +00:00 by KofTwentyTwo · 1 comment
KofTwentyTwo commented 2026-01-03 23:39:51 +00:00 (Migrated from github.com)

Part of #12

User Story

As a qctl user, I want a --merge mode so that I can regenerate specific files from a template without overwriting my customizations.

Design

Use Cases

  1. Update boilerplate: Regenerate CI/CD configs after template update
  2. Add new feature: Add Docker support to existing project
  3. Fix generation error: Re-render specific file with corrected variables

Command Interface

# Regenerate only specified files
qctl qqq init qqq-web-api . --merge --include "Dockerfile,docker-compose.yml"

# Regenerate all except specified files
qctl qqq init qqq-web-api . --merge --exclude "src/**/*.java"

# Interactive mode: prompt for each conflicting file
qctl qqq init qqq-web-api . --merge --interactive

Merge Strategy

Flag Behavior
--merge Only render files that don't exist
--merge --include <glob> Render matching files (overwrite if exist)
--merge --exclude <glob> Render non-matching files only
--merge --interactive Prompt for each existing file

Interactive Prompt

File exists: pom.xml
  [o] Overwrite
  [s] Skip  
  [d] Diff (show changes)
  [a] Overwrite all remaining
  [n] Skip all remaining
  
Choice [s]: d

--- existing pom.xml
+++ template pom.xml
@@ -10,7 +10,7 @@
-    <version>1.0.0</version>
+    <version>${version}</version>

Choice [s]: o
Overwriting pom.xml...

Backup Strategy

Before overwriting, create backup:

pom.xml -> pom.xml.bak

Or with timestamp:

pom.xml -> pom.xml.2024-01-15T10-30-00.bak

Files to Create/Modify

File Action Description
MergeOptions.java Create Merge configuration record
MergeStrategy.java Create Handles file conflict resolution
FileDiffer.java Create Generates diffs for comparison
InitCommand.java Modify Add --merge, --include, --exclude, --interactive
TemplateEngine.java Modify Integrate merge strategy
ConsoleUI.java Modify Add interactive merge prompts

Implementation Tasks

  • Add --merge flag to InitCommand
  • Add --include and --exclude glob options
  • Add --interactive flag
  • Create MergeOptions record
  • Create MergeStrategy class with conflict detection
  • Implement file backup before overwrite
  • Implement glob pattern matching for include/exclude
  • Create FileDiffer using diff algorithm
  • Add interactive prompts to ConsoleUI
  • Handle directory conflicts (merge contents)
  • Skip binary files in diff display
  • Add --no-backup flag to disable backups
  • Add unit tests for merge scenarios
  • Document merge mode in help text

Acceptance Criteria

  • --merge skips existing files by default
  • --include selectively regenerates matching files
  • --exclude protects matching files
  • --interactive prompts for each conflict
  • Diff display shows meaningful changes
  • Backups created before overwrite
  • Glob patterns work correctly
  • Transforms execute only for included files
  • Works with --dry-run to preview merge
Part of #12 ## User Story As a **qctl user**, I want a `--merge` mode so that I can regenerate specific files from a template without overwriting my customizations. ## Design ### Use Cases 1. **Update boilerplate**: Regenerate CI/CD configs after template update 2. **Add new feature**: Add Docker support to existing project 3. **Fix generation error**: Re-render specific file with corrected variables ### Command Interface ```bash # Regenerate only specified files qctl qqq init qqq-web-api . --merge --include "Dockerfile,docker-compose.yml" # Regenerate all except specified files qctl qqq init qqq-web-api . --merge --exclude "src/**/*.java" # Interactive mode: prompt for each conflicting file qctl qqq init qqq-web-api . --merge --interactive ``` ### Merge Strategy | Flag | Behavior | |------|----------| | `--merge` | Only render files that don't exist | | `--merge --include <glob>` | Render matching files (overwrite if exist) | | `--merge --exclude <glob>` | Render non-matching files only | | `--merge --interactive` | Prompt for each existing file | ### Interactive Prompt ``` File exists: pom.xml [o] Overwrite [s] Skip [d] Diff (show changes) [a] Overwrite all remaining [n] Skip all remaining Choice [s]: d --- existing pom.xml +++ template pom.xml @@ -10,7 +10,7 @@ - <version>1.0.0</version> + <version>${version}</version> Choice [s]: o Overwriting pom.xml... ``` ### Backup Strategy Before overwriting, create backup: ``` pom.xml -> pom.xml.bak ``` Or with timestamp: ``` pom.xml -> pom.xml.2024-01-15T10-30-00.bak ``` ## Files to Create/Modify | File | Action | Description | |------|--------|-------------| | `MergeOptions.java` | Create | Merge configuration record | | `MergeStrategy.java` | Create | Handles file conflict resolution | | `FileDiffer.java` | Create | Generates diffs for comparison | | `InitCommand.java` | Modify | Add --merge, --include, --exclude, --interactive | | `TemplateEngine.java` | Modify | Integrate merge strategy | | `ConsoleUI.java` | Modify | Add interactive merge prompts | ## Implementation Tasks - [ ] Add `--merge` flag to `InitCommand` - [ ] Add `--include` and `--exclude` glob options - [ ] Add `--interactive` flag - [ ] Create `MergeOptions` record - [ ] Create `MergeStrategy` class with conflict detection - [ ] Implement file backup before overwrite - [ ] Implement glob pattern matching for include/exclude - [ ] Create `FileDiffer` using diff algorithm - [ ] Add interactive prompts to `ConsoleUI` - [ ] Handle directory conflicts (merge contents) - [ ] Skip binary files in diff display - [ ] Add `--no-backup` flag to disable backups - [ ] Add unit tests for merge scenarios - [ ] Document merge mode in help text ## Acceptance Criteria - [ ] `--merge` skips existing files by default - [ ] `--include` selectively regenerates matching files - [ ] `--exclude` protects matching files - [ ] `--interactive` prompts for each conflict - [ ] Diff display shows meaningful changes - [ ] Backups created before overwrite - [ ] Glob patterns work correctly - [ ] Transforms execute only for included files - [ ] Works with `--dry-run` to preview merge
KofTwentyTwo commented 2026-01-04 03:21:51 +00:00 (Migrated from github.com)

Implementation Complete

Merge mode has been implemented with the following features:

New CLI Options

  • --merge - Merge with existing directory (skip existing files by default)
  • --include=PATTERN - Glob patterns to overwrite matching files
  • --exclude=PATTERN - Glob patterns to protect files from overwriting
  • --interactive - Prompt for each conflicting file
  • --no-backup - Disable backup creation when overwriting

New Classes

  • MergeOptions - Configuration record for merge settings
  • MergeStrategy - Conflict resolution logic with interactive prompts
  • FileDiffer - Unified diff generation for conflict preview

Behavior

  1. With --merge alone: existing files are skipped, new files are created
  2. With --merge --include=*.java: Java files are overwritten, others skipped
  3. With --merge --interactive: Prompts for each conflict with diff view option
  4. Backups created with timestamp before overwriting (unless --no-backup)

Tests

Added 26 new tests covering all merge functionality.

Commit: abc118d

## Implementation Complete Merge mode has been implemented with the following features: ### New CLI Options - `--merge` - Merge with existing directory (skip existing files by default) - `--include=PATTERN` - Glob patterns to overwrite matching files - `--exclude=PATTERN` - Glob patterns to protect files from overwriting - `--interactive` - Prompt for each conflicting file - `--no-backup` - Disable backup creation when overwriting ### New Classes - **MergeOptions** - Configuration record for merge settings - **MergeStrategy** - Conflict resolution logic with interactive prompts - **FileDiffer** - Unified diff generation for conflict preview ### Behavior 1. With `--merge` alone: existing files are skipped, new files are created 2. With `--merge --include=*.java`: Java files are overwritten, others skipped 3. With `--merge --interactive`: Prompts for each conflict with diff view option 4. Backups created with timestamp before overwriting (unless `--no-backup`) ### Tests Added 26 new tests covering all merge functionality. Commit: abc118d
Sign in to join this conversation.