1
2
3
4
5
6
7
8
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
145
146
147
148
149
150
151
152
153
154
155
156
|
require 'chef/chef_fs/knife'
class Chef
class Knife
class List < Chef::ChefFS::Knife
banner "knife list [-dfR1p] [PATTERN1 ... PATTERNn]"
category "path-based"
deps do
require 'chef/chef_fs/file_system'
require 'highline'
end
option :recursive,
:short => '-R',
:boolean => true,
:description => "List directories recursively"
option :bare_directories,
:short => '-d',
:boolean => true,
:description => "When directories match the pattern, do not show the directories' children"
option :local,
:long => '--local',
:boolean => true,
:description => "List local directory instead of remote"
option :flat,
:short => '-f',
:long => '--flat',
:boolean => true,
:description => "Show a list of filenames rather than the prettified ls-like output normally produced"
option :one_column,
:short => '-1',
:boolean => true,
:description => "Show only one column of results"
option :trailing_slashes,
:short => '-p',
:boolean => true,
:description => "Show trailing slashes after directories"
attr_accessor :exit_code
def run
patterns = name_args.length == 0 ? [""] : name_args
# Get the top-level matches
args = pattern_args_from(patterns)
all_results = parallelize(pattern_args_from(patterns)) do |pattern|
pattern_results = Chef::ChefFS::FileSystem.list(config[:local] ? local_fs : chef_fs, pattern).to_a
if pattern_results.first && !pattern_results.first.exists? && pattern.exact_path
ui.error "#{format_path(pattern_results.first)}: No such file or directory"
self.exit_code = 1
end
pattern_results
end.flatten(1).to_a
# Process directories
if !config[:bare_directories]
dir_results = parallelize(all_results.select { |result| result.dir? }) do |result|
add_dir_result(result)
end.flatten(1)
else
dir_results = []
end
# Process all other results
results = all_results.select { |result| result.exists? && (!result.dir? || config[:bare_directories]) }.to_a
# Flatten out directory results if necessary
if config[:flat]
dir_results.each do |result, children|
results += children
end
dir_results = []
end
# Sort by path for happy output
results = results.sort_by { |result| result.path }
dir_results = dir_results.sort_by { |result| result[0].path }
# Print!
if results.length == 0 && dir_results.length == 1
results = dir_results[0][1]
dir_results = []
end
print_result_paths results
printed_something = results.length > 0
dir_results.each do |result, children|
if printed_something
output ""
else
printed_something = true
end
output "#{format_path(result)}:"
print_results(children.map { |result| maybe_add_slash(result.name, result.dir?) }.sort, "")
end
exit self.exit_code if self.exit_code
end
def add_dir_result(result)
begin
children = result.children.sort_by { |child| child.name }
rescue Chef::ChefFS::FileSystem::NotFoundError => e
ui.error "#{format_path(e.entry)}: No such file or directory"
return []
end
result = [ [ result, children ] ]
if config[:recursive]
child_dirs = children.select { |child| child.dir? }
result += parallelize(child_dirs) { |child| add_dir_result(child) }.flatten(1).to_a
end
result
end
def print_result_paths(results, indent = "")
print_results(results.map { |result| maybe_add_slash(format_path(result), result.dir?) }, indent)
end
def print_results(results, indent)
return if results.length == 0
print_space = results.map { |result| result.length }.max + 2
if config[:one_column] || !stdout.isatty
columns = 0
else
columns = HighLine::SystemExtensions.terminal_size[0]
end
current_line = ''
results.each do |result|
if current_line.length > 0 && current_line.length + print_space > columns
output current_line.rstrip
current_line = ''
end
if current_line.length == 0
current_line << indent
end
current_line << result
current_line << (' ' * (print_space - result.length))
end
output current_line.rstrip if current_line.length > 0
end
def maybe_add_slash(path, is_dir)
if config[:trailing_slashes] && is_dir
"#{path}/"
else
path
end
end
end
end
end
|