Class: Ukiryu::ToolIndex Private

Inherits:
Object
  • Object
show all
Defined in:
lib/ukiryu/tool_index.rb

Overview

This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.

Index for fast tool lookup by interface and alias

This class maintains cached mappings for:

  • Interfaces to tools (multiple tools can implement one interface)

  • Aliases to tool names

  • Register change detection via mtime

Built once and cached for the lifetime of the process. Thread-safe for concurrent access.

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(register_path: nil) ⇒ ToolIndex

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Initialize the index

Parameters:

  • register_path (String, nil) (defaults to: nil)

    the path to the tool register



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/ukiryu/tool_index.rb', line 51

def initialize(register_path: nil)
  @register_path = register_path || Ukiryu::Register.default_register_path
  @mutex = Mutex.new

  Logger.debug('ToolIndex#initialize called', category: :executable)
  Logger.debug("param register_path = #{register_path.inspect}", category: :executable)
  Logger.debug("Ukiryu::Register.default_register_path = #{Ukiryu::Register.default_register_path.inspect}",
               category: :executable)
  Logger.debug("@register_path = #{@register_path.inspect}", category: :executable)

  @interface_to_tools = {} # interface => [tool_names]
  @alias_to_tool = {}      # alias => [tool_names] (multiple tools can share an alias)
  @compatibility_cache = {} # tool_name => tool_definition (for platform compatibility checks)
  @built = false
  @cache_key = nil # Register state for change detection
end

Class Method Details

.all_toolsHash{Symbol => Array<String>}

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Get all tools in the index (class method delegating to instance)

Returns:

  • (Hash{Symbol => Array<String>})

    mapping of interface to tool names



43
44
45
# File 'lib/ukiryu/tool_index.rb', line 43

def all_tools
  instance.all_tools
end

.instanceToolIndex

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Get the singleton instance (thread-safe)

Returns:



27
28
29
30
31
# File 'lib/ukiryu/tool_index.rb', line 27

def instance
  @mutex.synchronize do
    @instance ||= new
  end
end

.resetObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Reset the index (mainly for testing)



34
35
36
37
38
# File 'lib/ukiryu/tool_index.rb', line 34

def reset
  @mutex.synchronize do
    @instance = nil
  end
end

Instance Method Details

#all_toolsHash{Symbol => Array<String>}

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Get all tools in the index

Returns:

  • (Hash{Symbol => Array<String>})

    mapping of interface to tool names



173
174
175
176
177
# File 'lib/ukiryu/tool_index.rb', line 173

def all_tools
  build_index_if_needed

  @interface_to_tools.dup
end

#find_all_by_interface(interface_name) ⇒ Array<String>

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Find all tools that implement an interface

Parameters:

  • interface_name (Symbol)

    the interface to look up

Returns:

  • (Array<String>)

    list of tool names implementing this interface



94
95
96
97
98
99
100
# File 'lib/ukiryu/tool_index.rb', line 94

def find_all_by_interface(interface_name)
  build_index_if_needed

  @mutex.synchronize do
    @interface_to_tools[interface_name] || []
  end
end

#find_by_alias(alias_name) ⇒ String?

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Find tool by alias

When multiple tools have the same alias, returns the one most compatible with the current platform/shell.

Parameters:

  • alias_name (String)

    the alias to look up

Returns:

  • (String, nil)

    the tool name or nil if not found



109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/ukiryu/tool_index.rb', line 109

def find_by_alias(alias_name)
  build_index_if_needed

  @mutex.synchronize do
    candidates = @alias_to_tool[alias_name.to_sym]
    return nil unless candidates

    # If only one tool has this alias, return it directly
    return candidates.first if candidates.one?

    # Multiple tools have this alias - select by platform compatibility
    runtime = Ukiryu::Runtime.instance
    platform = runtime.platform
    shell = runtime.shell

    candidates.find do |tool_name|
      tool_compatible?(tool_name, platform: platform, shell: shell)
    end || candidates.first
  end
end

#find_by_interface(interface_name) ⇒ ToolMetadata?

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Find tool metadata by interface name Returns the first available tool for this interface

Parameters:

  • interface_name (Symbol)

    the interface to look up

Returns:

  • (ToolMetadata, nil)

    the tool metadata or nil if not found



73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/ukiryu/tool_index.rb', line 73

def find_by_interface(interface_name)
  build_index_if_needed

  @mutex.synchronize do
    tool_names = @interface_to_tools[interface_name]
    return nil unless tool_names

    # Try each tool implementing this interface until we find one that loads
    tool_names.each do |tool_name|
       = (tool_name)
      return  if 
    end

    nil
  end
end

#load_tool_definition_for_compatibility(tool_name) ⇒ Object?

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Load tool definition for compatibility checking Caches loaded definitions to avoid redundant parsing

Parameters:

  • tool_name (String, Symbol)

    the tool name

Returns:

  • (Object, nil)

    the tool definition model



157
158
159
160
161
162
163
164
165
166
167
168
# File 'lib/ukiryu/tool_index.rb', line 157

def load_tool_definition_for_compatibility(tool_name)
  # Use a simple cache for compatibility checks
  @compatibility_cache ||= {}
  cache_key = tool_name.to_sym

  @compatibility_cache[cache_key] ||= begin
    yaml_content = load_yaml_for_tool(tool_name)
    return nil unless yaml_content

    Ukiryu::Models::ToolDefinition.from_yaml(yaml_content)
  end
end

#register_path=(new_path) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Update the register path

Parameters:

  • new_path (String)

    the new register path



194
195
196
197
198
199
200
201
202
203
204
205
# File 'lib/ukiryu/tool_index.rb', line 194

def register_path=(new_path)
  @mutex.synchronize do
    return if @register_path == new_path

    @register_path = new_path
    @built = false # Rebuild index with new path
    @cache_key = nil
    @interface_to_tools = {}
    @alias_to_tool = {}
    @compatibility_cache = {}
  end
end

#stale?Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Check if the index needs rebuilding due to register changes

Returns:

  • (Boolean)

    true if rebuild is needed



182
183
184
185
186
187
188
189
# File 'lib/ukiryu/tool_index.rb', line 182

def stale?
  @mutex.synchronize do
    return true unless @built

    current_cache_key = build_cache_key
    @cache_key != current_cache_key
  end
end

#tool_compatible?(tool_name, platform:, shell:) ⇒ Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Check if a tool is compatible with the given platform and shell

Parameters:

  • tool_name (String, Symbol)

    the tool name

  • platform (Symbol)

    the platform (:macos, :linux, :windows)

  • shell (Symbol)

    the shell (:bash, :zsh, :fish, etc.)

Returns:

  • (Boolean)

    true if tool has a compatible profile



136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/ukiryu/tool_index.rb', line 136

def tool_compatible?(tool_name, platform:, shell:)
  # Load tool definition to check profiles
  tool_def = load_tool_definition_for_compatibility(tool_name)
  return false unless tool_def

  # Check if any profile matches platform/shell
  tool_def.profiles&.any? do |profile|
    profile_platforms = profile.platforms ? profile.platforms.map(&:to_sym) : []
    profile_shells = profile.shells ? profile.shells.map(&:to_sym) : []

    # Empty platforms/shells means universal compatibility
    (profile_platforms.empty? || profile_platforms.include?(platform)) &&
      (profile_shells.empty? || profile_shells.include?(shell))
  end || false
end