ace-support-core 0.29.3 → 0.29.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7092d5a5a2a6ba1607ece9d4276864f1c2120487e86fc122c4417e1f63d5c464
4
- data.tar.gz: b09155f148f14f5d542d1aaa55b2b5e6476ad1e3eee52ed221bd998284c1e641
3
+ metadata.gz: a6b708c53652bcab306f9ac32f767818083c2ec3d8d08c250765d333b27f7eee
4
+ data.tar.gz: 1761a2ed810b94d59636b52455ca38bef56eceb58b7b752ebeb4199fd7db35fd
5
5
  SHA512:
6
- metadata.gz: 37b188395cac1372478d0928bfbf5f7d8777c0f7da372f592636afc88cee8933591ca23e41c08a27f6f85d7601ea09c7215c8bc681d4ad5ed1929d64f24c9a7c
7
- data.tar.gz: 9b114626bd4b8394b85315bc09d6a3b77af5b6e606cc882ac212835a7137892931c8742fb8b89170544e0fdc147c399cb86247e546e40a08ea70ccfff4b05ac9
6
+ metadata.gz: 7ad2edbaca8fae8c51cfd934608b6e5b7c087764626515ddb1c0a4913d436a4b63f41d5ed07b6670f7c4d6f4d70eecbc01e5ccf0bd47f9ea3a3c8a9c582c8894
7
+ data.tar.gz: 2e968110a915140fb18dd5dc8de8044e19c80c6a1b71bc774b146f0b7dc23657873952fd748334906ceb7a188769e8379f441e5359ae79157bc16892b84049dd
@@ -0,0 +1,16 @@
1
+ # .ace Configuration
2
+
3
+ This directory contains local ACE configuration for your project.
4
+ These starter files are intentionally generic so you can tailor them to your own codebase.
5
+
6
+ ## First Steps
7
+
8
+ 1. Review `.ace/bundle/presets/project.md` and replace TODO placeholders.
9
+ 2. Optionally use `.ace/bundle/presets/project-base.md` for lightweight context loading.
10
+ 3. Run `ace-bundle project` to verify the preset loads successfully.
11
+ 4. Use `ace-task status` to inspect and manage your project task queue.
12
+
13
+ ## Notes
14
+
15
+ - Re-run `ace-config init --force` to refresh files from gem defaults.
16
+ - Keep project-specific guidance in your local `.ace/` files.
data/CHANGELOG.md CHANGED
@@ -7,6 +7,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.29.5] - 2026-03-31
11
+
12
+ ### Changed
13
+ - Migrated config CLI ownership to `ace-support-config` by removing `ace-framework` packaging/runtime surfaces from `ace-support-core` and updating package docs/default guidance to reference `ace-config`.
14
+
15
+ ## [0.29.4] - 2026-03-29
16
+
17
+ ### Changed
18
+ - Added a shipped `.ace-defaults/README.md` scaffold so `ace-framework init` generates `.ace/README.md` for newly initialized projects.
19
+ - Updated bootstrap configuration guidance and examples to current `ace-task` CLI usage and documented generated `project`/`project-base` presets.
20
+
10
21
  ## [0.29.3] - 2026-03-29
11
22
 
12
23
  ### Technical
data/README.md CHANGED
@@ -14,13 +14,13 @@
14
14
 
15
15
  > Works with: Claude Code, Codex CLI, OpenCode, Gemini CLI, pi-agent, and more.
16
16
 
17
- `ace-support-core` centralizes configuration loading, environment handling, and shared runtime behavior used by support libraries. It delegates config resolution through [ace-support-config](../ace-support-config) and exposes stable orchestration points that other `ace-support-*` gems build on. The `ace-framework` CLI manages per-package configuration setup.
17
+ `ace-support-core` centralizes configuration loading, environment handling, and shared runtime behavior used by support libraries. It delegates config resolution through [ace-support-config](../ace-support-config) and exposes stable orchestration points that other `ace-support-*` gems build on.
18
18
 
19
19
  ## How It Works
20
20
 
21
21
  1. Provide a shared bootstrap path for config, env, and runtime context so every `ace-support-*` gem starts from the same foundation.
22
22
  2. Delegate cascaded configuration resolution through [ace-support-config](../ace-support-config) so packages inherit project, user, and gem-level defaults automatically.
23
- 3. Expose the `ace-framework` CLI for initializing, diffing, and listing gem configurations across the workspace.
23
+ 3. Provide shared runtime/config primitives consumed by `ace-support-config`, which owns the `ace-config` CLI.
24
24
 
25
25
  ## Use Cases
26
26
 
@@ -31,4 +31,4 @@
31
31
  **Keep support libraries composable** - build package-specific features on top of stable core contracts that provide predictable runtime behavior.
32
32
 
33
33
  ---
34
- [Configuration overview](docs/config.md) | [`ace-framework` CLI reference](docs/config.md) | Part of [ACE](https://github.com/cs3b/ace)
34
+ [Configuration overview](docs/config.md) | [`ace-config` usage](../ace-support-config/docs/usage.md) | Part of [ACE](https://github.com/cs3b/ace)
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Ace
4
4
  module Core
5
- VERSION = '0.29.3'
5
+ VERSION = '0.29.5'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ace-support-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.29.3
4
+ version: 0.29.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michal Czyz
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2026-03-29 00:00:00.000000000 Z
10
+ date: 2026-04-01 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: ace-support-config
@@ -56,17 +56,16 @@ description: Foundational infrastructure gem providing configuration cascade res
56
56
  gem following ace-support-* pattern for infrastructure components.
57
57
  email:
58
58
  - mc@cs3b.com
59
- executables:
60
- - ace-framework
59
+ executables: []
61
60
  extensions: []
62
61
  extra_rdoc_files: []
63
62
  files:
63
+ - ".ace-defaults/README.md"
64
64
  - ".ace-defaults/core/settings.yml"
65
65
  - CHANGELOG.md
66
66
  - LICENSE
67
67
  - README.md
68
68
  - Rakefile
69
- - exe/ace-framework
70
69
  - lib/ace/core.rb
71
70
  - lib/ace/core/atoms/command_executor.rb
72
71
  - lib/ace/core/atoms/config_summary.rb
@@ -75,18 +74,14 @@ files:
75
74
  - lib/ace/core/atoms/glob_expander.rb
76
75
  - lib/ace/core/atoms/process_terminator.rb
77
76
  - lib/ace/core/atoms/template_parser.rb
78
- - lib/ace/core/cli.rb
79
77
  - lib/ace/core/cli/config_summary_mixin.rb
80
78
  - lib/ace/core/config_discovery.rb
81
79
  - lib/ace/core/errors.rb
82
- - lib/ace/core/models/config_templates.rb
83
80
  - lib/ace/core/molecules/env_loader.rb
84
81
  - lib/ace/core/molecules/file_aggregator.rb
85
82
  - lib/ace/core/molecules/frontmatter_free_policy.rb
86
83
  - lib/ace/core/molecules/output_formatter.rb
87
84
  - lib/ace/core/molecules/prompt_cache_manager.rb
88
- - lib/ace/core/organisms/config_diff.rb
89
- - lib/ace/core/organisms/config_initializer.rb
90
85
  - lib/ace/core/organisms/environment_manager.rb
91
86
  - lib/ace/core/version.rb
92
87
  homepage: https://github.com/cs3b/ace
data/exe/ace-framework DELETED
@@ -1,13 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
4
- require "ace/core"
5
- require "ace/core/cli"
6
-
7
- # Start FrameworkCLI (separate from Ace::Core::CLI module which is ace-support-cli infrastructure)
8
- begin
9
- Ace::Core::FrameworkCLI.start(ARGV)
10
- rescue Ace::Support::Cli::Error => e
11
- warn e.message
12
- exit(e.exit_code)
13
- end
data/lib/ace/core/cli.rb DELETED
@@ -1,192 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "optparse"
4
- require_relative "organisms/config_initializer"
5
- require_relative "organisms/config_diff"
6
- require_relative "models/config_templates"
7
-
8
- module Ace
9
- module Core
10
- # Framework CLI for ace-framework binary.
11
- # Uses a separate class name to avoid collision with Ace::Core::CLI module
12
- # (which provides shared CLI infrastructure).
13
- class FrameworkCLI
14
- def self.start(argv)
15
- new.run(argv)
16
- end
17
-
18
- def run(argv)
19
- return show_help if argv.empty?
20
-
21
- command = argv.shift
22
-
23
- case command
24
- when "init"
25
- run_init(argv)
26
- when "diff"
27
- run_diff(argv)
28
- when "list"
29
- run_list(argv)
30
- when "version", "--version"
31
- show_version
32
- when "help", "--help", "-h"
33
- show_help
34
- else
35
- puts "Unknown command: #{command}"
36
- puts ""
37
- show_help
38
- exit 1
39
- end
40
- end
41
-
42
- private
43
-
44
- def run_init(argv)
45
- options = {}
46
-
47
- parser = OptionParser.new do |opts|
48
- opts.banner = <<~BANNER.chomp
49
- NAME
50
- ace-framework init - Initialize configuration for ace-* gems
51
-
52
- USAGE
53
- ace-framework init [GEM] [OPTIONS]
54
-
55
- OPTIONS
56
- BANNER
57
- opts.on("--force", "Overwrite existing files") { options[:force] = true }
58
- opts.on("--dry-run", "Show what would be done") { options[:dry_run] = true }
59
- opts.on("--global", "Use ~/.ace instead of ./.ace") { options[:global] = true }
60
- opts.on("--verbose", "Show verbose output") { options[:verbose] = true }
61
- opts.on("-h", "--help", "Show this help") {
62
- puts opts
63
- exit
64
- }
65
- end
66
-
67
- parser.parse!(argv)
68
- gem_name = argv.shift
69
-
70
- initializer = ConfigInitializer.new(**options)
71
-
72
- if gem_name
73
- initializer.init_gem(gem_name)
74
- else
75
- initializer.init_all
76
- end
77
- end
78
-
79
- def run_diff(argv)
80
- options = {}
81
-
82
- parser = OptionParser.new do |opts|
83
- opts.banner = <<~BANNER.chomp
84
- NAME
85
- ace-framework diff - Compare configs with examples
86
-
87
- USAGE
88
- ace-framework diff [GEM] [OPTIONS]
89
-
90
- OPTIONS
91
- BANNER
92
- opts.on("--global", "Compare global configs") { options[:global] = true }
93
- opts.on("--local", "Compare local configs (default)") { options[:local] = true }
94
- opts.on("--file PATH", "Compare specific file") { |f| options[:file] = f }
95
- opts.on("--one-line", "One-line summary per file") { options[:one_line] = true }
96
- opts.on("-h", "--help", "Show this help") {
97
- puts opts
98
- exit
99
- }
100
- end
101
-
102
- parser.parse!(argv)
103
- gem_name = argv.shift
104
-
105
- differ = ConfigDiff.new(**options)
106
-
107
- if gem_name
108
- differ.diff_gem(gem_name)
109
- else
110
- differ.run
111
- end
112
- end
113
-
114
- def run_list(argv)
115
- verbose = false
116
-
117
- parser = OptionParser.new do |opts|
118
- opts.banner = <<~BANNER.chomp
119
- NAME
120
- ace-framework list - List available ace-* gems with example configs
121
-
122
- USAGE
123
- ace-framework list [OPTIONS]
124
-
125
- OPTIONS
126
- BANNER
127
- opts.on("--verbose", "Show detailed information") { verbose = true }
128
- opts.on("-h", "--help", "Show this help") {
129
- puts opts
130
- exit
131
- }
132
- end
133
-
134
- parser.parse!(argv)
135
-
136
- puts "Available ace-* gems with example configurations:\n\n"
137
-
138
- if ConfigTemplates.all_gems.empty?
139
- puts "No ace-* gems with example configurations found."
140
- return
141
- end
142
-
143
- ConfigTemplates.all_gems.each do |gem_name|
144
- info = ConfigTemplates.gem_info[gem_name]
145
- source_label = case info[:source]
146
- when :local then "[local]"
147
- when :gem then "[gem]"
148
- when :both then "[local+gem]"
149
- end
150
-
151
- puts " #{gem_name} #{source_label}"
152
-
153
- if verbose
154
- puts " Path: #{info[:path]}"
155
- puts " Gem: #{info[:gem_path]}" if info[:gem_path]
156
- example_dir = ConfigTemplates.example_dir_for(gem_name)
157
- if example_dir && File.exist?(example_dir)
158
- example_files = Dir.glob("#{example_dir}/**/*").reject { |f| File.directory?(f) }
159
- puts " Example files: #{example_files.size}"
160
- end
161
- end
162
- end
163
-
164
- puts "\nUse 'ace-framework init [GEM]' to initialize a specific gem's configuration"
165
- puts "Use 'ace-framework init' to initialize all configurations"
166
- end
167
-
168
- def show_version
169
- puts "ace-framework #{Ace::Core::VERSION}"
170
- end
171
-
172
- def show_help
173
- puts <<~HELP
174
- NAME
175
- ace-framework - Configuration management for ace-* gems
176
-
177
- USAGE
178
- ace-framework COMMAND [OPTIONS]
179
-
180
- COMMANDS
181
- init [GEM] Initialize configuration for specific gem or all
182
- diff [GEM] Compare configs with examples
183
- list List available ace-* gems with example configs
184
- version Show version
185
- help Show this help
186
-
187
- Run 'ace-framework COMMAND --help' for more information on a command.
188
- HELP
189
- end
190
- end
191
- end
192
- end
@@ -1,87 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "pathname"
4
- require "rubygems"
5
-
6
- module Ace
7
- module Core
8
- class ConfigTemplates
9
- class << self
10
- def all_gems
11
- gem_info.keys.sort
12
- end
13
-
14
- def gem_exists?(gem_name)
15
- gem_info.key?(gem_name)
16
- end
17
-
18
- def example_dir_for(gem_name)
19
- info = gem_info[gem_name]
20
- return nil unless info
21
-
22
- # Prefer local path for development
23
- path = (info[:source] == :gem) ? info[:path] : (info[:path] || info[:gem_path])
24
- resolve_defaults_dir(path)
25
- end
26
-
27
- def gem_info
28
- @gem_info ||= build_gem_info
29
- end
30
-
31
- def build_gem_info
32
- gems = {}
33
-
34
- # 1. Look in the parent directory (monorepo/development)
35
- parent_dir = File.expand_path("../../../../../../", __FILE__)
36
- Dir.glob("#{parent_dir}/ace-*").each do |dir|
37
- next unless File.directory?(dir)
38
- gem_name = File.basename(dir)
39
- if has_example_dir?(dir)
40
- gems[gem_name] = {source: :local, path: dir}
41
- end
42
- end
43
-
44
- # 2. Look for installed RubyGems
45
- begin
46
- Gem::Specification.each do |spec|
47
- next unless spec.name.start_with?("ace-")
48
-
49
- gem_path = spec.gem_dir
50
- if has_example_dir?(gem_path)
51
- if gems.key?(spec.name)
52
- gems[spec.name][:source] = :both
53
- gems[spec.name][:gem_path] = gem_path
54
- else
55
- gems[spec.name] = {source: :gem, path: gem_path}
56
- end
57
- end
58
- end
59
- rescue
60
- # If we can't access installed gems, just use local ones
61
- end
62
-
63
- gems
64
- end
65
-
66
- def docs_file_for(gem_name)
67
- info = gem_info[gem_name]
68
- return nil unless info
69
-
70
- # Prefer local path for development
71
- path = (info[:source] == :gem) ? info[:path] : (info[:path] || info[:gem_path])
72
- File.join(path, "docs", "config.md")
73
- end
74
-
75
- private
76
-
77
- def resolve_defaults_dir(gem_path)
78
- File.join(gem_path, ".ace-defaults")
79
- end
80
-
81
- def has_example_dir?(gem_dir)
82
- Dir.exist?(File.join(gem_dir, ".ace-defaults"))
83
- end
84
- end
85
- end
86
- end
87
- end
@@ -1,187 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "open3"
4
- require "pathname"
5
- require_relative "../models/config_templates"
6
-
7
- module Ace
8
- module Core
9
- class ConfigDiff
10
- def initialize(global: false, file: nil, one_line: false)
11
- @global = global
12
- @file = file
13
- @one_line = one_line
14
- @diffs = []
15
- end
16
-
17
- def run
18
- if @file
19
- diff_file(@file)
20
- else
21
- diff_all_configs
22
- end
23
-
24
- print_results
25
- end
26
-
27
- def diff_gem(gem_name)
28
- # Normalize gem name (support both "ace-bundle" and "bundle")
29
- gem_name = gem_name.start_with?("ace-") ? gem_name : "ace-#{gem_name}"
30
-
31
- unless ConfigTemplates.gem_exists?(gem_name)
32
- puts "Error: Gem '#{gem_name}' not found or has no example configurations"
33
- exit 1
34
- end
35
-
36
- diff_gem_configs(gem_name)
37
- print_results
38
- end
39
-
40
- private
41
-
42
- def config_directory
43
- @global ? File.expand_path("~/.ace") : ".ace"
44
- end
45
-
46
- def diff_all_configs
47
- ConfigTemplates.all_gems.each do |gem_name|
48
- diff_gem_configs(gem_name)
49
- end
50
- end
51
-
52
- def diff_gem_configs(gem_name)
53
- source_dir = ConfigTemplates.example_dir_for(gem_name)
54
-
55
- return unless source_dir && File.exist?(source_dir)
56
-
57
- Dir.glob("#{source_dir}/**/*").each do |source_file|
58
- next if File.directory?(source_file)
59
-
60
- relative_path = Pathname.new(source_file).relative_path_from(Pathname.new(source_dir))
61
- target_file = File.join(config_directory, relative_path.to_s)
62
-
63
- compare_files(source_file, target_file, gem_name)
64
- end
65
- end
66
-
67
- def diff_file(file_path)
68
- # Determine which gem this file belongs to
69
- if file_path.start_with?(config_directory)
70
- relative_path = Pathname.new(file_path).relative_path_from(Pathname.new(config_directory))
71
- parts = relative_path.to_s.split(File::SEPARATOR)
72
-
73
- if parts.any?
74
- config_subdir = parts.first
75
- gem_name = "ace-#{config_subdir}"
76
-
77
- if ConfigTemplates.gem_exists?(gem_name)
78
- source_dir = ConfigTemplates.example_dir_for(gem_name)
79
- relative_file = parts[1..-1].join(File::SEPARATOR)
80
- source_file = File.join(source_dir, relative_file)
81
-
82
- if File.exist?(source_file)
83
- compare_files(source_file, file_path, gem_name)
84
- else
85
- puts "No example file found for #{file_path}"
86
- end
87
- end
88
- end
89
- else
90
- puts "File #{file_path} is not in a configuration directory"
91
- end
92
- end
93
-
94
- def compare_files(source_file, target_file, gem_name)
95
- @diffs << if !File.exist?(target_file)
96
- {
97
- gem: gem_name,
98
- file: target_file,
99
- status: :missing,
100
- source: source_file
101
- }
102
- elsif files_differ?(source_file, target_file)
103
- {
104
- gem: gem_name,
105
- file: target_file,
106
- status: :different,
107
- source: source_file,
108
- diff_output: get_diff_output(source_file, target_file)
109
- }
110
- else
111
- {
112
- gem: gem_name,
113
- file: target_file,
114
- status: :same,
115
- source: source_file
116
- }
117
- end
118
- end
119
-
120
- def files_differ?(file1, file2)
121
- File.read(file1) != File.read(file2)
122
- rescue
123
- true
124
- end
125
-
126
- def get_diff_output(source_file, target_file)
127
- # Use system diff command
128
- output, _status = Open3.capture2("diff", "-u", target_file, source_file)
129
- output
130
- rescue
131
- "Unable to generate diff"
132
- end
133
-
134
- def print_results
135
- if @one_line
136
- print_one_line_summary
137
- else
138
- print_detailed_diffs
139
- end
140
- end
141
-
142
- def print_one_line_summary
143
- @diffs.each do |diff|
144
- case diff[:status]
145
- when :missing
146
- puts "MISSING: #{diff[:file]}"
147
- when :different
148
- puts "CHANGED: #{diff[:file]}"
149
- when :same
150
- puts "SAME: #{diff[:file]}" if @verbose
151
- end
152
- end
153
-
154
- puts "\nSummary:"
155
- puts " Missing: #{@diffs.count { |d| d[:status] == :missing }}"
156
- puts " Changed: #{@diffs.count { |d| d[:status] == :different }}"
157
- puts " Same: #{@diffs.count { |d| d[:status] == :same }}"
158
- end
159
-
160
- def print_detailed_diffs
161
- missing = @diffs.select { |d| d[:status] == :missing }
162
- changed = @diffs.select { |d| d[:status] == :different }
163
-
164
- if missing.any?
165
- puts "Missing configuration files:"
166
- missing.each do |diff|
167
- puts " #{diff[:file]}"
168
- puts " -> Example: #{diff[:source]}"
169
- end
170
- puts
171
- end
172
-
173
- if changed.any?
174
- puts "Changed configuration files:"
175
- changed.each do |diff|
176
- puts "\n#{diff[:file]}:"
177
- puts diff[:diff_output]
178
- end
179
- end
180
-
181
- if missing.empty? && changed.empty?
182
- puts "All configuration files match the examples."
183
- end
184
- end
185
- end
186
- end
187
- end
@@ -1,125 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "fileutils"
4
- require "pathname"
5
- require_relative "../models/config_templates"
6
-
7
- module Ace
8
- module Core
9
- class ConfigInitializer
10
- def initialize(force: false, dry_run: false, global: false, verbose: false)
11
- @force = force
12
- @dry_run = dry_run
13
- @global = global
14
- @verbose = verbose
15
- @copied_files = []
16
- @skipped_files = []
17
- end
18
-
19
- def init_all
20
- puts "Initializing all ace-* gem configurations..." if @verbose
21
-
22
- ConfigTemplates.all_gems.each do |gem_name|
23
- init_gem(gem_name)
24
- end
25
-
26
- print_summary
27
- end
28
-
29
- def init_gem(gem_name)
30
- gem_name = normalize_gem_name(gem_name)
31
-
32
- unless ConfigTemplates.gem_exists?(gem_name)
33
- puts "Warning: No configuration found for #{gem_name}"
34
- return
35
- end
36
-
37
- puts "\nInitializing #{gem_name}..." if @verbose
38
-
39
- source_dir = ConfigTemplates.example_dir_for(gem_name)
40
- target_dir = target_directory
41
-
42
- unless File.exist?(source_dir)
43
- puts "Warning: No .ace-defaults directory found for #{gem_name}"
44
- return
45
- end
46
-
47
- # Show config docs on first run if config is missing
48
- show_config_docs_if_needed(gem_name, target_dir)
49
-
50
- # Copy files from .ace-defaults to .ace
51
- copy_config_files(source_dir, target_dir, gem_name)
52
- end
53
-
54
- private
55
-
56
- def normalize_gem_name(name)
57
- # Handle both "ace-core" and "core" formats
58
- name.start_with?("ace-") ? name : "ace-#{name}"
59
- end
60
-
61
- def target_directory
62
- @global ? File.expand_path("~/.ace") : ".ace"
63
- end
64
-
65
- def show_config_docs_if_needed(gem_name, target_dir)
66
- # Check if any config files exist for this gem
67
- config_subdir = gem_name.sub("ace-", "")
68
-
69
- # Look for any existing config files in the expected location
70
- existing_configs = Dir.glob("#{target_dir}/#{config_subdir}/**/*").reject { |f| File.directory?(f) }
71
-
72
- # Only show docs if this is the first time (no existing config)
73
- if existing_configs.empty? && !@dry_run
74
- docs_file = ConfigTemplates.docs_file_for(gem_name)
75
- if File.exist?(docs_file)
76
- puts "\n#{File.read(docs_file)}\n"
77
- end
78
- end
79
- end
80
-
81
- def copy_config_files(source_dir, target_dir, gem_name)
82
- Dir.glob("#{source_dir}/**/*").each do |source_file|
83
- next if File.directory?(source_file)
84
-
85
- # Calculate relative path from source_dir
86
- relative_path = Pathname.new(source_file).relative_path_from(Pathname.new(source_dir))
87
-
88
- # Build target path - files already include their subdirectory
89
- target_file = File.join(target_dir, relative_path.to_s)
90
-
91
- copy_file(source_file, target_file)
92
- end
93
- end
94
-
95
- def copy_file(source, target)
96
- if File.exist?(target) && !@force
97
- @skipped_files << target
98
- puts " Skipped: #{target} (already exists)" if @verbose
99
- return
100
- end
101
-
102
- if @dry_run
103
- puts " Would copy: #{source} -> #{target}"
104
- else
105
- FileUtils.mkdir_p(File.dirname(target))
106
- FileUtils.cp(source, target)
107
- @copied_files << target
108
- puts " Copied: #{target}" if @verbose
109
- end
110
- end
111
-
112
- def print_summary
113
- return if @dry_run
114
-
115
- puts "\nConfiguration initialization complete:"
116
- puts " Files copied: #{@copied_files.size}"
117
- puts " Files skipped: #{@skipped_files.size}"
118
-
119
- if @skipped_files.any? && !@force
120
- puts "\nUse --force to overwrite existing files"
121
- end
122
- end
123
- end
124
- end
125
- end