ukiryu 0.1.1 → 0.1.3
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 +4 -4
- data/.github/workflows/release.yml +58 -14
- data/.gitignore +3 -0
- data/.rubocop_todo.yml +170 -79
- data/Gemfile +1 -1
- data/README.adoc +1603 -576
- data/docs/.gitignore +1 -0
- data/docs/Gemfile +10 -0
- data/docs/INDEX.adoc +261 -0
- data/docs/_config.yml +180 -0
- data/docs/advanced/custom-tool-classes.adoc +581 -0
- data/docs/advanced/index.adoc +20 -0
- data/docs/features/configuration.adoc +657 -0
- data/docs/features/index.adoc +31 -0
- data/docs/features/platform-support.adoc +488 -0
- data/docs/getting-started/core-concepts.adoc +666 -0
- data/docs/getting-started/index.adoc +36 -0
- data/docs/getting-started/installation.adoc +216 -0
- data/docs/getting-started/quick-start.adoc +258 -0
- data/docs/guides/env-var-sets.adoc +388 -0
- data/docs/guides/index.adoc +20 -0
- data/docs/interfaces/cli.adoc +609 -0
- data/docs/interfaces/index.adoc +153 -0
- data/docs/interfaces/ruby-api.adoc +538 -0
- data/docs/lychee.toml +49 -0
- data/docs/reference/configuration-options.adoc +720 -0
- data/docs/reference/error-codes.adoc +634 -0
- data/docs/reference/index.adoc +20 -0
- data/docs/reference/ruby-api.adoc +1217 -0
- data/docs/understanding/index.adoc +20 -0
- data/lib/ukiryu/cli.rb +43 -58
- data/lib/ukiryu/cli_commands/base_command.rb +16 -27
- data/lib/ukiryu/cli_commands/cache_command.rb +100 -0
- data/lib/ukiryu/cli_commands/commands_command.rb +8 -8
- data/lib/ukiryu/cli_commands/commands_command.rb.fixed +1 -1
- data/lib/ukiryu/cli_commands/config_command.rb +49 -7
- data/lib/ukiryu/cli_commands/definitions_command.rb +254 -0
- data/lib/ukiryu/cli_commands/describe_command.rb +13 -7
- data/lib/ukiryu/cli_commands/describe_command.rb.fixed +1 -1
- data/lib/ukiryu/cli_commands/docs_command.rb +148 -0
- data/lib/ukiryu/cli_commands/exec_inline_command.rb.fixed +1 -1
- data/lib/ukiryu/cli_commands/extract_command.rb +2 -2
- data/lib/ukiryu/cli_commands/info_command.rb +7 -7
- data/lib/ukiryu/cli_commands/lint_command.rb +167 -0
- data/lib/ukiryu/cli_commands/list_command.rb +6 -6
- data/lib/ukiryu/cli_commands/opts_command.rb +2 -2
- data/lib/ukiryu/cli_commands/opts_command.rb.fixed +1 -1
- data/lib/ukiryu/cli_commands/register_command.rb +144 -0
- data/lib/ukiryu/cli_commands/resolve_command.rb +124 -0
- data/lib/ukiryu/cli_commands/run_command.rb +38 -14
- data/lib/ukiryu/cli_commands/run_file_command.rb +2 -2
- data/lib/ukiryu/cli_commands/system_command.rb +50 -32
- data/lib/ukiryu/cli_commands/validate_command.rb +452 -51
- data/lib/ukiryu/cli_commands/which_command.rb +5 -5
- data/lib/ukiryu/command_builder.rb +81 -23
- data/lib/ukiryu/config/env_provider.rb +3 -3
- data/lib/ukiryu/config/env_schema.rb +6 -6
- data/lib/ukiryu/config.rb +11 -11
- data/lib/ukiryu/definition/definition_cache.rb +238 -0
- data/lib/ukiryu/definition/definition_composer.rb +257 -0
- data/lib/ukiryu/definition/definition_linter.rb +460 -0
- data/lib/ukiryu/definition/definition_validator.rb +320 -0
- data/lib/ukiryu/definition/discovery.rb +239 -0
- data/lib/ukiryu/definition/documentation_generator.rb +429 -0
- data/lib/ukiryu/definition/lint_issue.rb +168 -0
- data/lib/ukiryu/definition/loader.rb +139 -0
- data/lib/ukiryu/definition/metadata.rb +159 -0
- data/lib/ukiryu/definition/source.rb +87 -0
- data/lib/ukiryu/definition/sources/file.rb +138 -0
- data/lib/ukiryu/definition/sources/string.rb +88 -0
- data/lib/ukiryu/definition/validation_result.rb +158 -0
- data/lib/ukiryu/definition/version_resolver.rb +194 -0
- data/lib/ukiryu/definition.rb +40 -0
- data/lib/ukiryu/errors.rb +6 -0
- data/lib/ukiryu/execution_context.rb +11 -11
- data/lib/ukiryu/executor.rb +6 -0
- data/lib/ukiryu/extractors/extractor.rb +6 -5
- data/lib/ukiryu/extractors/help_parser.rb +13 -19
- data/lib/ukiryu/logger.rb +3 -1
- data/lib/ukiryu/models/command_definition.rb +3 -3
- data/lib/ukiryu/models/command_info.rb +1 -1
- data/lib/ukiryu/models/components.rb +1 -3
- data/lib/ukiryu/models/env_var_definition.rb +11 -3
- data/lib/ukiryu/models/flag_definition.rb +15 -0
- data/lib/ukiryu/models/option_definition.rb +7 -7
- data/lib/ukiryu/models/platform_profile.rb +6 -3
- data/lib/ukiryu/models/routing.rb +1 -1
- data/lib/ukiryu/models/tool_definition.rb +2 -4
- data/lib/ukiryu/models/tool_metadata.rb +6 -6
- data/lib/ukiryu/models/validation_result.rb +1 -1
- data/lib/ukiryu/models/version_compatibility.rb +6 -3
- data/lib/ukiryu/models/version_detection.rb +10 -1
- data/lib/ukiryu/{registry.rb → register.rb} +54 -38
- data/lib/ukiryu/register_auto_manager.rb +268 -0
- data/lib/ukiryu/schema_validator.rb +31 -10
- data/lib/ukiryu/shell/base.rb +18 -0
- data/lib/ukiryu/shell/bash.rb +19 -1
- data/lib/ukiryu/shell/cmd.rb +11 -1
- data/lib/ukiryu/shell/powershell.rb +11 -1
- data/lib/ukiryu/shell.rb +1 -1
- data/lib/ukiryu/tool.rb +107 -95
- data/lib/ukiryu/tool_index.rb +22 -22
- data/lib/ukiryu/tools/base.rb +12 -25
- data/lib/ukiryu/tools/generator.rb +7 -7
- data/lib/ukiryu/tools.rb +3 -3
- data/lib/ukiryu/type.rb +20 -5
- data/lib/ukiryu/version.rb +1 -1
- data/lib/ukiryu/version_detector.rb +21 -2
- data/lib/ukiryu.rb +6 -3
- data/ukiryu-proposal.md +41 -41
- data/ukiryu.gemspec +1 -0
- metadata +64 -8
- data/.gitmodules +0 -3
|
@@ -9,21 +9,29 @@ module Ukiryu
|
|
|
9
9
|
# @example
|
|
10
10
|
# env_var = EnvVarDefinition.new(
|
|
11
11
|
# name: 'DISPLAY',
|
|
12
|
-
# env_var: 'DISPLAY',
|
|
13
12
|
# value: '',
|
|
14
13
|
# platforms: [:linux, :macos]
|
|
15
14
|
# )
|
|
16
15
|
class EnvVarDefinition < Lutaml::Model::Serializable
|
|
17
16
|
attribute :name, :string
|
|
18
|
-
attribute :env_var, :string
|
|
19
17
|
attribute :value, :string
|
|
18
|
+
attribute :from, :string
|
|
20
19
|
attribute :platforms, :string, collection: true, default: []
|
|
20
|
+
attribute :description, :string
|
|
21
21
|
|
|
22
22
|
yaml do
|
|
23
23
|
map_element 'name', to: :name
|
|
24
|
-
map_element 'env_var', to: :env_var
|
|
25
24
|
map_element 'value', to: :value
|
|
25
|
+
map_element 'from', to: :from
|
|
26
26
|
map_element 'platforms', to: :platforms
|
|
27
|
+
map_element 'description', to: :description
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Get platforms as symbol array
|
|
31
|
+
#
|
|
32
|
+
# @return [Array<Symbol>] platforms as symbols
|
|
33
|
+
def platforms_sym
|
|
34
|
+
@platforms_sym ||= platforms&.map(&:to_sym) || []
|
|
27
35
|
end
|
|
28
36
|
end
|
|
29
37
|
end
|
|
@@ -18,16 +18,24 @@ module Ukiryu
|
|
|
18
18
|
class FlagDefinition < Lutaml::Model::Serializable
|
|
19
19
|
attribute :name, :string
|
|
20
20
|
attribute :cli, :string
|
|
21
|
+
attribute :cli_short, :string
|
|
21
22
|
attribute :default, :boolean, default: false
|
|
22
23
|
attribute :description, :string
|
|
23
24
|
attribute :platforms, :string, collection: true, default: []
|
|
25
|
+
attribute :position_constraint, :string
|
|
26
|
+
attribute :position_after, :string
|
|
27
|
+
attribute :conflicts_with, :string, collection: true, default: []
|
|
24
28
|
|
|
25
29
|
yaml do
|
|
26
30
|
map_element 'name', to: :name
|
|
27
31
|
map_element 'cli', to: :cli
|
|
32
|
+
map_element 'cli_short', to: :cli_short
|
|
28
33
|
map_element 'default', to: :default
|
|
29
34
|
map_element 'description', to: :description
|
|
30
35
|
map_element 'platforms', to: :platforms
|
|
36
|
+
map_element 'position_constraint', to: :position_constraint
|
|
37
|
+
map_element 'position_after', to: :position_after
|
|
38
|
+
map_element 'conflicts_with', to: :conflicts_with
|
|
31
39
|
end
|
|
32
40
|
|
|
33
41
|
# Get the effective default value
|
|
@@ -54,6 +62,13 @@ module Ukiryu
|
|
|
54
62
|
@name_sym ||= name.to_sym
|
|
55
63
|
end
|
|
56
64
|
|
|
65
|
+
# Get position_constraint as symbol (cached)
|
|
66
|
+
#
|
|
67
|
+
# @return [Symbol, nil] the position constraint as symbol, or nil if not set
|
|
68
|
+
def position_constraint_sym
|
|
69
|
+
@position_constraint_sym ||= position_constraint&.to_sym
|
|
70
|
+
end
|
|
71
|
+
|
|
57
72
|
private
|
|
58
73
|
|
|
59
74
|
# Get platforms as cached symbol array
|
|
@@ -13,14 +13,14 @@ module Ukiryu
|
|
|
13
13
|
# name: 'quality',
|
|
14
14
|
# cli: '-q',
|
|
15
15
|
# type: 'integer',
|
|
16
|
-
#
|
|
16
|
+
# assignment_delimiter: 'space',
|
|
17
17
|
# description: 'JPEG quality'
|
|
18
18
|
# )
|
|
19
19
|
class OptionDefinition < Lutaml::Model::Serializable
|
|
20
20
|
attribute :name, :string
|
|
21
21
|
attribute :cli, :string
|
|
22
22
|
attribute :type, :string, default: 'string'
|
|
23
|
-
attribute :
|
|
23
|
+
attribute :assignment_delimiter, :string, default: 'auto'
|
|
24
24
|
attribute :separator, :string
|
|
25
25
|
attribute :default, :string
|
|
26
26
|
# Array for numeric range [min, max]
|
|
@@ -36,7 +36,7 @@ module Ukiryu
|
|
|
36
36
|
map_element 'name', to: :name
|
|
37
37
|
map_element 'cli', to: :cli
|
|
38
38
|
map_element 'type', to: :type
|
|
39
|
-
map_element '
|
|
39
|
+
map_element 'assignment_delimiter', to: :assignment_delimiter
|
|
40
40
|
map_element 'separator', to: :separator
|
|
41
41
|
map_element 'default', to: :default
|
|
42
42
|
map_element 'range', to: :range
|
|
@@ -63,11 +63,11 @@ module Ukiryu
|
|
|
63
63
|
type == 'boolean'
|
|
64
64
|
end
|
|
65
65
|
|
|
66
|
-
# Get
|
|
66
|
+
# Get assignment delimiter as symbol
|
|
67
67
|
#
|
|
68
|
-
# @return [Symbol] the
|
|
69
|
-
def
|
|
70
|
-
@
|
|
68
|
+
# @return [Symbol] the assignment delimiter
|
|
69
|
+
def assignment_delimiter_sym
|
|
70
|
+
@assignment_delimiter_sym ||= assignment_delimiter.to_sym
|
|
71
71
|
end
|
|
72
72
|
|
|
73
73
|
# Hash-like access for Type validation compatibility
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require 'lutaml/model'
|
|
4
4
|
require_relative 'command_definition'
|
|
5
|
+
require_relative 'env_var_definition'
|
|
5
6
|
require_relative 'routing'
|
|
6
7
|
require_relative 'exit_codes'
|
|
7
8
|
|
|
@@ -23,9 +24,10 @@ module Ukiryu
|
|
|
23
24
|
attribute :option_style, :string, default: 'single_dash_space'
|
|
24
25
|
attribute :commands, CommandDefinition, collection: true, initialize_empty: true
|
|
25
26
|
attribute :inherits, :string
|
|
26
|
-
attribute :routing_data, :hash, default: {}
|
|
27
|
-
attribute :version_requirement, :string
|
|
28
|
-
attribute :exit_codes, ExitCodes
|
|
27
|
+
attribute :routing_data, :hash, default: {} # Raw routing from YAML
|
|
28
|
+
attribute :version_requirement, :string # Semantic version requirement (e.g., ">= 2.30")
|
|
29
|
+
attribute :exit_codes, ExitCodes # Exit code definitions for this profile
|
|
30
|
+
attribute :env_var_sets, :hash, default: {} # Reusable env var sets (e.g., "headless")
|
|
29
31
|
|
|
30
32
|
yaml do
|
|
31
33
|
map_element 'name', to: :name
|
|
@@ -38,6 +40,7 @@ module Ukiryu
|
|
|
38
40
|
map_element 'routing', to: :routing_data
|
|
39
41
|
map_element 'version_requirement', to: :version_requirement
|
|
40
42
|
map_element 'exit_codes', to: :exit_codes
|
|
43
|
+
map_element 'env_var_sets', to: :env_var_sets
|
|
41
44
|
end
|
|
42
45
|
|
|
43
46
|
# Get the routing table as a Routing model
|
|
@@ -26,7 +26,7 @@ module Ukiryu
|
|
|
26
26
|
attribute :profiles, PlatformProfile, collection: true
|
|
27
27
|
attribute :version_detection, VersionDetection
|
|
28
28
|
attribute :search_paths, SearchPaths
|
|
29
|
-
attribute :components, Components
|
|
29
|
+
attribute :components, Components # Register of reusable definitions
|
|
30
30
|
|
|
31
31
|
yaml do
|
|
32
32
|
map_element 'ukiryu_schema', to: :ukiryu_schema
|
|
@@ -129,9 +129,7 @@ module Ukiryu
|
|
|
129
129
|
# Get the self URI
|
|
130
130
|
#
|
|
131
131
|
# @return [String, nil] the self URI
|
|
132
|
-
|
|
133
|
-
@self_uri
|
|
134
|
-
end
|
|
132
|
+
attr_reader :self_uri
|
|
135
133
|
|
|
136
134
|
# Check if a specific schema version is specified
|
|
137
135
|
#
|
|
@@ -9,11 +9,11 @@ module Ukiryu
|
|
|
9
9
|
# without loading the full profile definition
|
|
10
10
|
|
|
11
11
|
attr_reader :name, :version, :display_name, :implements, :homepage,
|
|
12
|
-
:description, :aliases, :tool_name, :
|
|
12
|
+
:description, :aliases, :tool_name, :register_path, :default_command
|
|
13
13
|
|
|
14
14
|
def initialize(name:, version:, display_name: nil, implements: nil,
|
|
15
15
|
homepage: nil, description: nil, aliases: nil,
|
|
16
|
-
tool_name: nil,
|
|
16
|
+
tool_name: nil, register_path: nil, default_command: nil)
|
|
17
17
|
@name = name
|
|
18
18
|
@version = version
|
|
19
19
|
@display_name = display_name
|
|
@@ -22,7 +22,7 @@ module Ukiryu
|
|
|
22
22
|
@description = description
|
|
23
23
|
@aliases = Array(aliases || [])
|
|
24
24
|
@tool_name = tool_name || name
|
|
25
|
-
@
|
|
25
|
+
@register_path = register_path
|
|
26
26
|
@default_command = default_command
|
|
27
27
|
end
|
|
28
28
|
|
|
@@ -62,9 +62,9 @@ module Ukiryu
|
|
|
62
62
|
#
|
|
63
63
|
# @param hash [Hash] the YAML profile hash
|
|
64
64
|
# @param tool_name [String] the tool name
|
|
65
|
-
# @param
|
|
65
|
+
# @param register_path [String] the register path
|
|
66
66
|
# @return [ToolMetadata] the metadata object
|
|
67
|
-
def self.from_hash(hash, tool_name:,
|
|
67
|
+
def self.from_hash(hash, tool_name:, register_path: nil)
|
|
68
68
|
new(
|
|
69
69
|
name: tool_name,
|
|
70
70
|
version: hash['version'],
|
|
@@ -75,7 +75,7 @@ module Ukiryu
|
|
|
75
75
|
aliases: hash['aliases'],
|
|
76
76
|
default_command: hash['default_command'],
|
|
77
77
|
tool_name: tool_name,
|
|
78
|
-
|
|
78
|
+
register_path: register_path
|
|
79
79
|
)
|
|
80
80
|
end
|
|
81
81
|
end
|
|
@@ -52,7 +52,10 @@ module Ukiryu
|
|
|
52
52
|
# @param requirement [String] the version requirement (e.g., ">= 2.30")
|
|
53
53
|
# @return [VersionCompatibility] the compatibility result
|
|
54
54
|
def self.check(installed_version, requirement)
|
|
55
|
-
|
|
55
|
+
if !requirement || requirement.empty?
|
|
56
|
+
return new(installed_version: installed_version, required_version: requirement, compatible: true,
|
|
57
|
+
reason: nil)
|
|
58
|
+
end
|
|
56
59
|
|
|
57
60
|
parser = RequirementParser.new(requirement)
|
|
58
61
|
compatible = parser.satisfied_by?(installed_version)
|
|
@@ -112,9 +115,9 @@ module Ukiryu
|
|
|
112
115
|
|
|
113
116
|
case constraint[:operator]
|
|
114
117
|
when '>', '>='
|
|
115
|
-
compare_versions(v, req_v)
|
|
118
|
+
compare_versions(v, req_v).positive? || (constraint[:operator] == '>=' && v == req_v)
|
|
116
119
|
when '<', '<='
|
|
117
|
-
compare_versions(v, req_v)
|
|
120
|
+
compare_versions(v, req_v).negative? || (constraint[:operator] == '<=' && v == req_v)
|
|
118
121
|
when '==', '='
|
|
119
122
|
v == req_v
|
|
120
123
|
when '!='
|
|
@@ -6,21 +6,30 @@ module Ukiryu
|
|
|
6
6
|
module Models
|
|
7
7
|
# Version detection configuration
|
|
8
8
|
#
|
|
9
|
-
# @example
|
|
9
|
+
# @example Command-based version detection (GNU tools)
|
|
10
10
|
# vd = VersionDetection.new(
|
|
11
11
|
# command: '--version',
|
|
12
12
|
# pattern: '(\d+\.\d+)',
|
|
13
13
|
# modern_threshold: '7.0'
|
|
14
14
|
# )
|
|
15
|
+
#
|
|
16
|
+
# @example Man-page based version detection (BSD/system tools)
|
|
17
|
+
# vd = VersionDetection.new(
|
|
18
|
+
# command: ['man', 'find'],
|
|
19
|
+
# pattern: 'macOS ([\d.]+)',
|
|
20
|
+
# source: 'man'
|
|
21
|
+
# )
|
|
15
22
|
class VersionDetection < Lutaml::Model::Serializable
|
|
16
23
|
attribute :command, :string, collection: true, default: []
|
|
17
24
|
attribute :pattern, :string
|
|
18
25
|
attribute :modern_threshold, :string
|
|
26
|
+
attribute :source, :string, default: 'command' # 'command' or 'man'
|
|
19
27
|
|
|
20
28
|
yaml do
|
|
21
29
|
map_element 'command', to: :command
|
|
22
30
|
map_element 'pattern', to: :pattern
|
|
23
31
|
map_element 'modern_threshold', to: :modern_threshold
|
|
32
|
+
map_element 'source', to: :source
|
|
24
33
|
end
|
|
25
34
|
|
|
26
35
|
# Hash-like access for Base.detect_version compatibility
|
|
@@ -5,41 +5,43 @@ require_relative 'models/tool_metadata'
|
|
|
5
5
|
require_relative 'models/validation_result'
|
|
6
6
|
require_relative 'tool_index'
|
|
7
7
|
require_relative 'schema_validator'
|
|
8
|
+
require_relative 'register_auto_manager'
|
|
8
9
|
|
|
9
10
|
module Ukiryu
|
|
10
|
-
# YAML profile
|
|
11
|
+
# YAML profile register loader
|
|
11
12
|
#
|
|
12
|
-
# Provides access to tool definitions from YAML profiles in a
|
|
13
|
+
# Provides access to tool definitions from YAML profiles in a register directory.
|
|
13
14
|
# Supports lazy loading: metadata can be loaded without full profile parsing.
|
|
14
15
|
#
|
|
15
16
|
# Features:
|
|
16
17
|
# - Cached version listings to avoid repeated glob operations
|
|
17
|
-
# - Automatic cache invalidation when
|
|
18
|
-
|
|
18
|
+
# - Automatic cache invalidation when register path changes
|
|
19
|
+
# - Automatic register cloning to ~/.ukiryu/register if not configured
|
|
20
|
+
class Register
|
|
19
21
|
class << self
|
|
20
|
-
# Set the default
|
|
22
|
+
# Set the default register path
|
|
21
23
|
#
|
|
22
|
-
# @param path [String] the default
|
|
24
|
+
# @param path [String] the default register path
|
|
23
25
|
|
|
24
|
-
# Get the default
|
|
26
|
+
# Get the default register path
|
|
25
27
|
#
|
|
26
|
-
# @return [String, nil] the default
|
|
27
|
-
attr_accessor :
|
|
28
|
+
# @return [String, nil] the default register path
|
|
29
|
+
attr_accessor :default_register_path
|
|
28
30
|
|
|
29
31
|
# Reset the version cache (mainly for testing)
|
|
30
32
|
def reset_version_cache
|
|
31
33
|
@version_cache = nil
|
|
32
|
-
@
|
|
34
|
+
@register_cache_key = nil
|
|
33
35
|
end
|
|
34
36
|
|
|
35
37
|
# Get all available tool names
|
|
36
38
|
#
|
|
37
39
|
# @return [Array<String>] list of tool names
|
|
38
40
|
def tools
|
|
39
|
-
|
|
40
|
-
return [] unless
|
|
41
|
+
register_path = effective_register_path
|
|
42
|
+
return [] unless register_path
|
|
41
43
|
|
|
42
|
-
tools_dir = File.join(
|
|
44
|
+
tools_dir = File.join(register_path, 'tools')
|
|
43
45
|
return [] unless Dir.exist?(tools_dir)
|
|
44
46
|
|
|
45
47
|
# List all directories in tools/
|
|
@@ -53,20 +55,20 @@ module Ukiryu
|
|
|
53
55
|
# Get available versions for a tool (cached)
|
|
54
56
|
#
|
|
55
57
|
# @param name [String, Symbol] the tool name
|
|
56
|
-
# @param
|
|
58
|
+
# @param register_path [String, nil] the register path
|
|
57
59
|
# @return [Hash] mapping of version filename to Gem::Version
|
|
58
|
-
def list_versions(name,
|
|
59
|
-
|
|
60
|
-
return {} unless
|
|
60
|
+
def list_versions(name, register_path: nil)
|
|
61
|
+
register_path ||= effective_register_path
|
|
62
|
+
return {} unless register_path
|
|
61
63
|
|
|
62
64
|
# Initialize cache
|
|
63
65
|
@version_cache ||= {}
|
|
64
|
-
@
|
|
66
|
+
@register_cache_key ||= register_path
|
|
65
67
|
|
|
66
|
-
# Clear cache if
|
|
67
|
-
if @
|
|
68
|
+
# Clear cache if register path changed
|
|
69
|
+
if @register_cache_key != register_path
|
|
68
70
|
@version_cache.clear
|
|
69
|
-
@
|
|
71
|
+
@register_cache_key = register_path
|
|
70
72
|
end
|
|
71
73
|
|
|
72
74
|
# Check cache
|
|
@@ -74,7 +76,7 @@ module Ukiryu
|
|
|
74
76
|
return @version_cache[cache_key].dup if @version_cache[cache_key]
|
|
75
77
|
|
|
76
78
|
# Build version list
|
|
77
|
-
versions = scan_tool_versions(name,
|
|
79
|
+
versions = scan_tool_versions(name, register_path)
|
|
78
80
|
@version_cache[cache_key] = versions
|
|
79
81
|
|
|
80
82
|
versions.dup
|
|
@@ -88,16 +90,16 @@ module Ukiryu
|
|
|
88
90
|
# @param name [String, Symbol] the tool name or interface name
|
|
89
91
|
# @param options [Hash] loading options
|
|
90
92
|
# @option options [String] :version specific version to load
|
|
91
|
-
# @option options [String] :
|
|
93
|
+
# @option options [String] :register_path path to register
|
|
92
94
|
# @return [ToolMetadata, nil] the tool metadata or nil if not found
|
|
93
95
|
def load_tool_metadata(name, options = {})
|
|
94
|
-
|
|
96
|
+
register_path = options[:register_path] || effective_register_path
|
|
95
97
|
|
|
96
98
|
# First try exact name match
|
|
97
|
-
yaml_content = load_tool_yaml(name, options.merge(
|
|
99
|
+
yaml_content = load_tool_yaml(name, options.merge(register_path: register_path))
|
|
98
100
|
if yaml_content
|
|
99
101
|
hash = YAML.safe_load(yaml_content, permitted_classes: [Symbol])
|
|
100
|
-
return ToolMetadata.from_hash(hash, tool_name: name.to_s,
|
|
102
|
+
return ToolMetadata.from_hash(hash, tool_name: name.to_s, register_path: register_path) if hash
|
|
101
103
|
end
|
|
102
104
|
|
|
103
105
|
# If not found, try interface-based discovery using ToolIndex
|
|
@@ -110,12 +112,12 @@ module Ukiryu
|
|
|
110
112
|
# @param name [String, Symbol] the tool name
|
|
111
113
|
# @param options [Hash] loading options
|
|
112
114
|
# @option options [String] :version specific version to load
|
|
113
|
-
# @option options [String] :
|
|
115
|
+
# @option options [String] :register_path path to register
|
|
114
116
|
# @return [String, nil] the YAML content or nil if not found
|
|
115
117
|
def load_tool_yaml(name, options = {})
|
|
116
|
-
|
|
118
|
+
register_path = options[:register_path] || effective_register_path
|
|
117
119
|
|
|
118
|
-
return nil unless
|
|
120
|
+
return nil unless register_path
|
|
119
121
|
|
|
120
122
|
# Convert to string for path operations
|
|
121
123
|
name_str = name.to_s
|
|
@@ -123,16 +125,16 @@ module Ukiryu
|
|
|
123
125
|
# Try version-specific directory first
|
|
124
126
|
version = options[:version]
|
|
125
127
|
if version
|
|
126
|
-
file = File.join(
|
|
128
|
+
file = File.join(register_path, 'tools', name_str, "#{version}.yaml")
|
|
127
129
|
return File.read(file) if File.exist?(file)
|
|
128
130
|
end
|
|
129
131
|
|
|
130
132
|
# Use cached version list if available
|
|
131
|
-
versions = list_versions(name_str,
|
|
133
|
+
versions = list_versions(name_str, register_path: register_path)
|
|
132
134
|
|
|
133
135
|
if versions.empty?
|
|
134
136
|
# Try the old format (single file per tool)
|
|
135
|
-
file = File.join(
|
|
137
|
+
file = File.join(register_path, 'tools', "#{name_str}.yaml")
|
|
136
138
|
return File.read(file) if File.exist?(file)
|
|
137
139
|
|
|
138
140
|
return nil
|
|
@@ -153,7 +155,7 @@ module Ukiryu
|
|
|
153
155
|
# @param name [String, Symbol] the tool name
|
|
154
156
|
# @param options [Hash] validation options
|
|
155
157
|
# @option options [String] :version specific version to validate
|
|
156
|
-
# @option options [String] :
|
|
158
|
+
# @option options [String] :register_path path to register
|
|
157
159
|
# @option options [String] :schema_path path to schema file
|
|
158
160
|
# @return [ValidationResult] the validation result
|
|
159
161
|
def validate_tool(name, options = {})
|
|
@@ -171,10 +173,10 @@ module Ukiryu
|
|
|
171
173
|
end
|
|
172
174
|
end
|
|
173
175
|
|
|
174
|
-
# Validate all tool profiles in the
|
|
176
|
+
# Validate all tool profiles in the register
|
|
175
177
|
#
|
|
176
178
|
# @param options [Hash] validation options
|
|
177
|
-
# @option options [String] :
|
|
179
|
+
# @option options [String] :register_path path to register
|
|
178
180
|
# @option options [String] :schema_path path to schema file
|
|
179
181
|
# @return [Array<ValidationResult>] list of validation results
|
|
180
182
|
def validate_all_tools(options = {})
|
|
@@ -185,13 +187,27 @@ module Ukiryu
|
|
|
185
187
|
|
|
186
188
|
private
|
|
187
189
|
|
|
190
|
+
# Get the effective register path
|
|
191
|
+
#
|
|
192
|
+
# Returns the manually set path if available, otherwise uses
|
|
193
|
+
# RegisterAutoManager to get or create the default path.
|
|
194
|
+
#
|
|
195
|
+
# @return [String, nil] the register path, or nil if unavailable
|
|
196
|
+
def effective_register_path
|
|
197
|
+
# If manually set, use that
|
|
198
|
+
return @default_register_path if @default_register_path
|
|
199
|
+
|
|
200
|
+
# Otherwise, use RegisterAutoManager (auto-clone if needed)
|
|
201
|
+
RegisterAutoManager.register_path
|
|
202
|
+
end
|
|
203
|
+
|
|
188
204
|
# Scan tool versions and sort by Gem::Version
|
|
189
205
|
#
|
|
190
206
|
# @param name [String] the tool name
|
|
191
|
-
# @param
|
|
207
|
+
# @param register_path [String] the register path
|
|
192
208
|
# @return [Hash] mapping of version filename to Gem::Version
|
|
193
|
-
def scan_tool_versions(name,
|
|
194
|
-
pattern = File.join(
|
|
209
|
+
def scan_tool_versions(name, register_path)
|
|
210
|
+
pattern = File.join(register_path, 'tools', name.to_s, '*.yaml')
|
|
195
211
|
files = Dir.glob(pattern)
|
|
196
212
|
|
|
197
213
|
# Sort files by Gem::Version for proper version ordering
|