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
|
# File 'lib/clacky/tools/glob.rb', line 36
def execute(pattern:, base_path: ".", limit: 10, working_dir: nil)
if pattern.nil? || pattern.strip.empty?
return { error: "Pattern cannot be empty" }
end
pattern = pattern.start_with?("~") ? File.expand_path(pattern) : pattern
base_path = expand_path(base_path, working_dir: working_dir)
unless Dir.exist?(base_path)
return { error: "Base path does not exist: #{base_path}" }
end
if Clacky::Utils::FileIgnoreHelper.dangerous_root?(base_path)
return {
error: "Refusing to recursively glob from broad path '#{base_path}'. " \
"Narrow base_path to a specific subdirectory, " \
"or use '.' to search the working directory."
}
end
begin
expanded_path = base_path
skipped = {
binary: 0,
too_large: 0,
ignored: 0
}
effective_pattern = if !File.absolute_path?(pattern) &&
!pattern.include?("/") &&
!pattern.start_with?("**")
"**/#{pattern}"
else
pattern
end
fnmatch_flags = File::FNM_PATHNAME | File::FNM_DOTMATCH
matches = []
walk_status = {}
Clacky::Utils::FileIgnoreHelper.walk_files(expanded_path, skipped: skipped, status: walk_status) do |file|
relative = file[(expanded_path.length + 1)..]
unless File.fnmatch(effective_pattern, relative, fnmatch_flags)
next
end
if Clacky::Utils::FileProcessor.binary_file_path?(file) &&
!Clacky::Utils::FileProcessor.glob_allowed_binary?(file)
skipped[:binary] += 1
next
end
if File.size(file) > MAX_FILE_SIZE
skipped[:too_large] += 1
next
end
matches << file
end
matches = matches.sort_by { |path| -File.mtime(path).to_i }
total_matches = matches.length
matches = matches.take(limit)
matches = matches.map { |path| File.expand_path(path) }
walk_truncated = walk_status[:truncated] == true
{
matches: matches,
total_matches: total_matches,
returned: matches.length,
truncated: total_matches > limit || walk_truncated,
truncation_reason: walk_status[:truncation_reason],
skipped_files: skipped,
error: nil
}
rescue StandardError => e
{ error: "Failed to glob files: #{e.message}" }
end
end
|