Class: Roast::Helpers::PathResolver
- Inherits:
-
Object
- Object
- Roast::Helpers::PathResolver
- Defined in:
- lib/roast/helpers/path_resolver.rb
Overview
Utility class for resolving file paths with directory structure issues
Class Method Summary collapse
-
.resolve(path) ⇒ Object
Intelligently resolves a path considering possible directory structure issues.
Class Method Details
.resolve(path) ⇒ Object
Intelligently resolves a path considering possible directory structure issues
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
# File 'lib/roast/helpers/path_resolver.rb', line 9 def resolve(path) # Store original path for logging if needed original_path = path # Early return if the path is nil or empty return path if path.nil? || path.empty? # First try standard path expansion = File.(path) # Return early if the file exists at the expanded path return if File.exist?() # Get current directory and possible project root paths current_dir = Dir.pwd possible_roots = [ current_dir, File.(File.join(current_dir, "..")), File.(File.join(current_dir, "../..")), File.(File.join(current_dir, "../../..")), File.(File.join(current_dir, "../../../..")), File.(File.join(current_dir, "../../../../..")), ] # Check for directory name duplications anywhere in the path path_parts = .split(File::SEPARATOR).reject(&:empty?) # Try removing each duplicate segment individually and check if the resulting path exists path_parts.each_with_index do |part, i| next if i == 0 # Skip the first segment # Check if this segment appears earlier in the path next unless path_parts[0...i].include?(part) # Create a new path without this segment test_parts = path_parts.dup test_parts.delete_at(i) test_path = if original_path.start_with?("/") File.join("/", *test_parts) else File.join(test_parts) end # If this path exists, return it return test_path if File.exist?(test_path) # Also try removing all future occurrences of this segment name duplicate_indices = [] path_parts.each_with_index do |segment, idx| if idx > 0 && segment == part && idx >= i duplicate_indices << idx end end next if duplicate_indices.none? filtered_parts = path_parts.dup # Remove from end to beginning to keep indices valid duplicate_indices.reverse_each { |idx| filtered_parts.delete_at(idx) } test_path = if original_path.start_with?("/") File.join("/", *filtered_parts) else File.join(filtered_parts) end return test_path if File.exist?(test_path) end # Try detecting all duplicates at once seen_segments = {} duplicate_indices = [] path_parts.each_with_index do |part, i| if seen_segments[part] duplicate_indices << i else seen_segments[part] = true end end if duplicate_indices.any? # Try removing all duplicates unique_parts = path_parts.dup # Remove from end to beginning to keep indices valid duplicate_indices.reverse_each { |i| unique_parts.delete_at(i) } test_path = if original_path.start_with?("/") File.join("/", *unique_parts) else File.join(unique_parts) end return test_path if File.exist?(test_path) end # Try relative path resolution from various possible roots relative_path = path.sub(%r{^\./}, "") possible_roots.each do |root| # Try the path as-is from this root candidate = File.join(root, relative_path) return candidate if File.exist?(candidate) # Try with a leading slash removed if relative_path.start_with?("/") candidate = File.join(root, relative_path.sub(%r{^/}, "")) return candidate if File.exist?(candidate) end end # Try extracting the path after a potential project root if .include?("/src/") || .include?("/lib/") || .include?("/test/") # Potential project markers markers = ["/src/", "/lib/", "/test/", "/app/", "/config/"] markers.each do |marker| next unless .include?(marker) # Get the part after the marker parts = .split(marker, 2) next unless parts.size == 2 marker_dir = marker.gsub("/", "") relative_from_marker = parts[1] # Try each possible root with this marker possible_roots.each do |root| candidate = File.join(root, marker_dir, relative_from_marker) return candidate if File.exist?(candidate) end end end # Default to the original expanded path if all else fails end |