knife-essentials 0.8.3 → 0.8.4
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.
- data/lib/chef/knife/diff_essentials.rb +2 -2
- data/lib/chef/knife/download_essentials.rb +5 -1
- data/lib/chef/knife/list_essentials.rb +2 -1
- data/lib/chef/knife/upload_essentials.rb +5 -1
- data/lib/chef_fs/command_line.rb +94 -63
- data/lib/chef_fs/file_system.rb +113 -93
- data/lib/chef_fs/file_system/base_fs_object.rb +91 -37
- data/lib/chef_fs/file_system/chef_repository_file_system_cookbooks_dir.rb +14 -1
- data/lib/chef_fs/file_system/chef_server_root_dir.rb +2 -1
- data/lib/chef_fs/file_system/cookbook_file.rb +7 -1
- data/lib/chef_fs/file_system/cookbooks_dir.rb +13 -6
- data/lib/chef_fs/file_system/environments_dir.rb +59 -0
- data/lib/chef_fs/file_system/multiplexed_dir.rb +1 -1
- data/lib/chef_fs/file_system/nodes_dir.rb +1 -0
- data/lib/chef_fs/file_system/operation_not_allowed_error.rb +29 -0
- data/lib/chef_fs/file_system/operation_skipped_error.rb +29 -0
- data/lib/chef_fs/knife.rb +29 -21
- data/lib/chef_fs/version.rb +1 -1
- data/spec/chef_fs/diff_spec.rb +30 -30
- data/spec/chef_fs/file_system/cookbooks_dir_spec.rb +5 -1
- data/spec/integration/chef_repo_path_spec.rb +705 -0
- data/spec/integration/chef_repository_file_system_spec.rb +82 -713
- data/spec/integration/chefignore_spec.rb +258 -0
- data/spec/integration/diff_spec.rb +151 -0
- data/spec/integration/download_spec.rb +403 -0
- data/spec/integration/list_spec.rb +21 -21
- data/spec/integration/upload_spec.rb +407 -0
- data/spec/support/integration_helper.rb +9 -4
- data/spec/support/knife_support.rb +14 -2
- metadata +12 -3
@@ -37,8 +37,8 @@ class Chef
|
|
37
37
|
|
38
38
|
# Get the matches (recursively)
|
39
39
|
patterns.each do |pattern|
|
40
|
-
ChefFS::CommandLine.
|
41
|
-
|
40
|
+
ChefFS::CommandLine.diff_print(pattern, chef_fs, local_fs, config[:recurse] ? nil : 1, output_mode, proc { |entry| format_path(entry.path) } ) do |diff|
|
41
|
+
stdout.print diff
|
42
42
|
end
|
43
43
|
end
|
44
44
|
end
|
@@ -42,8 +42,12 @@ class Chef
|
|
42
42
|
exit 1
|
43
43
|
end
|
44
44
|
|
45
|
+
error = false
|
45
46
|
pattern_args.each do |pattern|
|
46
|
-
ChefFS::FileSystem.copy_to(pattern, chef_fs, local_fs, config[:recurse] ? nil : 1, config, ui)
|
47
|
+
error ||= ChefFS::FileSystem.copy_to(pattern, chef_fs, local_fs, config[:recurse] ? nil : 1, config, ui, proc { |entry| format_path(entry.path) })
|
48
|
+
end
|
49
|
+
if error
|
50
|
+
exit 1
|
47
51
|
end
|
48
52
|
end
|
49
53
|
end
|
@@ -6,7 +6,7 @@ class Chef
|
|
6
6
|
remove_const(:List) if const_defined?(:List) && List.name == 'Chef::Knife::List' # override Chef's version
|
7
7
|
class List < ::ChefFS::Knife
|
8
8
|
ChefFS = ::ChefFS
|
9
|
-
banner "knife list [-
|
9
|
+
banner "knife list [-dfR1p] [PATTERN1 ... PATTERNn]"
|
10
10
|
|
11
11
|
common_options
|
12
12
|
|
@@ -23,6 +23,7 @@ class Chef
|
|
23
23
|
:boolean => true,
|
24
24
|
:description => "List local directory instead of remote"
|
25
25
|
option :flat,
|
26
|
+
:short => '-f',
|
26
27
|
:long => '--flat',
|
27
28
|
:boolean => true,
|
28
29
|
:description => "Show a list of filenames rather than the prettified ls-like output normally produced"
|
@@ -42,8 +42,12 @@ class Chef
|
|
42
42
|
exit 1
|
43
43
|
end
|
44
44
|
|
45
|
+
error = false
|
45
46
|
pattern_args.each do |pattern|
|
46
|
-
ChefFS::FileSystem.copy_to(pattern, local_fs, chef_fs, config[:recurse] ? nil : 1, config, ui)
|
47
|
+
error ||= ChefFS::FileSystem.copy_to(pattern, local_fs, chef_fs, config[:recurse] ? nil : 1, config, ui, proc { |entry| format_path(entry.path) })
|
48
|
+
end
|
49
|
+
if error
|
50
|
+
exit 1
|
47
51
|
end
|
48
52
|
end
|
49
53
|
end
|
data/lib/chef_fs/command_line.rb
CHANGED
@@ -20,10 +20,85 @@ require 'chef_fs/file_system'
|
|
20
20
|
|
21
21
|
module ChefFS
|
22
22
|
module CommandLine
|
23
|
-
|
23
|
+
|
24
|
+
def self.diff_print(pattern, a_root, b_root, recurse_depth, output_mode, format_path = nil)
|
25
|
+
if format_path.nil?
|
26
|
+
format_path = proc { |entry| entry.path_for_printing }
|
27
|
+
end
|
28
|
+
|
29
|
+
get_content = (output_mode != :name_only && output_mode != :name_status)
|
30
|
+
diff(pattern, a_root, b_root, recurse_depth, get_content) do |type, old_entry, new_entry, old_value, new_value|
|
31
|
+
old_path = format_path.call(old_entry)
|
32
|
+
new_path = format_path.call(new_entry)
|
33
|
+
|
34
|
+
if get_content && old_value && new_value
|
35
|
+
result = ''
|
36
|
+
result << "diff --knife #{old_path} #{new_path}\n"
|
37
|
+
if old_value == :none
|
38
|
+
result << "new file\n"
|
39
|
+
old_path = "/dev/null"
|
40
|
+
old_value = ''
|
41
|
+
end
|
42
|
+
if new_value == :none
|
43
|
+
result << "deleted file\n"
|
44
|
+
new_path = "/dev/null"
|
45
|
+
new_value = ''
|
46
|
+
end
|
47
|
+
result << diff_text(old_path, new_path, old_value, new_value)
|
48
|
+
yield result
|
49
|
+
else
|
50
|
+
case type
|
51
|
+
when :common_subdirectories
|
52
|
+
if output_mode != :name_only && output_mode != :name_status
|
53
|
+
yield "Common subdirectories: #{new_path}\n"
|
54
|
+
end
|
55
|
+
when :directory_to_file
|
56
|
+
if output_mode == :name_only
|
57
|
+
yield "#{new_path}\n"
|
58
|
+
elsif output_mode == :name_status
|
59
|
+
yield "T\t#{new_path}\n"
|
60
|
+
else
|
61
|
+
yield "File #{old_path} is a directory while file #{new_path} is a regular file\n"
|
62
|
+
end
|
63
|
+
when :file_to_directory
|
64
|
+
if output_mode == :name_only
|
65
|
+
yield "#{new_path}\n"
|
66
|
+
elsif output_mode == :name_status
|
67
|
+
yield "T\t#{new_path}\n"
|
68
|
+
else
|
69
|
+
yield "File #{old_path} is a regular file while file #{new_path} is a directory\n"
|
70
|
+
end
|
71
|
+
when :deleted
|
72
|
+
if output_mode == :name_only
|
73
|
+
yield "#{new_path}\n"
|
74
|
+
elsif output_mode == :name_status
|
75
|
+
yield "D\t#{new_path}\n"
|
76
|
+
else
|
77
|
+
yield "Only in #{format_path.call(old_entry.parent)}: #{old_entry.name}\n"
|
78
|
+
end
|
79
|
+
when :added
|
80
|
+
if output_mode == :name_only
|
81
|
+
yield "#{new_path}\n"
|
82
|
+
elsif output_mode == :name_status
|
83
|
+
yield "A\t#{new_path}\n"
|
84
|
+
else
|
85
|
+
yield "Only in #{format_path.call(new_entry.parent)}: #{new_entry.name}\n"
|
86
|
+
end
|
87
|
+
when :modified
|
88
|
+
if output_mode == :name_only
|
89
|
+
yield "#{new_path}\n"
|
90
|
+
elsif output_mode == :name_status
|
91
|
+
yield "M\t#{new_path}\n"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def self.diff(pattern, a_root, b_root, recurse_depth, get_content)
|
24
99
|
found_result = false
|
25
100
|
ChefFS::FileSystem.list_pairs(pattern, a_root, b_root) do |a, b|
|
26
|
-
existed = diff_entries(a, b, recurse_depth,
|
101
|
+
existed = diff_entries(a, b, recurse_depth, get_content) do |diff|
|
27
102
|
yield diff
|
28
103
|
end
|
29
104
|
found_result = true if existed
|
@@ -34,18 +109,16 @@ module ChefFS
|
|
34
109
|
end
|
35
110
|
|
36
111
|
# Diff two known entries (could be files or dirs)
|
37
|
-
def self.diff_entries(old_entry, new_entry, recurse_depth,
|
112
|
+
def self.diff_entries(old_entry, new_entry, recurse_depth, get_content)
|
38
113
|
# If both are directories
|
39
114
|
if old_entry.dir?
|
40
115
|
if new_entry.dir?
|
41
116
|
if recurse_depth == 0
|
42
|
-
|
43
|
-
yield "Common subdirectories: #{old_entry.path}\n"
|
44
|
-
end
|
117
|
+
yield [ :common_subdirectories, old_entry, new_entry ]
|
45
118
|
else
|
46
119
|
ChefFS::FileSystem.child_pairs(old_entry, new_entry).each do |old_child,new_child|
|
47
120
|
diff_entries(old_child, new_child,
|
48
|
-
recurse_depth ? recurse_depth - 1 : nil,
|
121
|
+
recurse_depth ? recurse_depth - 1 : nil, get_content) do |diff|
|
49
122
|
yield diff
|
50
123
|
end
|
51
124
|
end
|
@@ -53,45 +126,21 @@ module ChefFS
|
|
53
126
|
|
54
127
|
# If old is a directory and new is a file
|
55
128
|
elsif new_entry.exists?
|
56
|
-
|
57
|
-
yield "#{new_entry.path_for_printing}\n"
|
58
|
-
elsif output_mode == :name_status
|
59
|
-
yield "T\t#{new_entry.path_for_printing}\n"
|
60
|
-
else
|
61
|
-
yield "File #{new_entry.path_for_printing} is a directory while file #{new_entry.path_for_printing} is a regular file\n"
|
62
|
-
end
|
129
|
+
yield [ :directory_to_file, old_entry, new_entry ]
|
63
130
|
|
64
131
|
# If old is a directory and new does not exist
|
65
132
|
elsif new_entry.parent.can_have_child?(old_entry.name, old_entry.dir?)
|
66
|
-
|
67
|
-
yield "#{new_entry.path_for_printing}\n"
|
68
|
-
elsif output_mode == :name_status
|
69
|
-
yield "D\t#{new_entry.path_for_printing}\n"
|
70
|
-
else
|
71
|
-
yield "Only in #{old_entry.parent.path_for_printing}: #{old_entry.name}\n"
|
72
|
-
end
|
133
|
+
yield [ :deleted, old_entry, new_entry ]
|
73
134
|
end
|
74
135
|
|
75
136
|
# If new is a directory and old is a file
|
76
137
|
elsif new_entry.dir?
|
77
138
|
if old_entry.exists?
|
78
|
-
|
79
|
-
yield "#{new_entry.path_for_printing}\n"
|
80
|
-
elsif output_mode == :name_status
|
81
|
-
yield "T\t#{new_entry.path_for_printing}\n"
|
82
|
-
else
|
83
|
-
yield "File #{old_entry.path_for_printing} is a regular file while file #{old_entry.path_for_printing} is a directory\n"
|
84
|
-
end
|
139
|
+
yield [ :file_to_directory, old_entry, new_entry ]
|
85
140
|
|
86
141
|
# If new is a directory and old does not exist
|
87
142
|
elsif old_entry.parent.can_have_child?(new_entry.name, new_entry.dir?)
|
88
|
-
|
89
|
-
yield "#{new_entry.path_for_printing}\n"
|
90
|
-
elsif output_mode == :name_status
|
91
|
-
yield "A\t#{new_entry.path_for_printing}\n"
|
92
|
-
else
|
93
|
-
yield "Only in #{new_entry.parent.path_for_printing}: #{new_entry.name}\n"
|
94
|
-
end
|
143
|
+
yield [ :added, old_entry, new_entry ]
|
95
144
|
end
|
96
145
|
|
97
146
|
# Neither is a directory, so they are diffable with file diff
|
@@ -107,6 +156,7 @@ module ChefFS
|
|
107
156
|
else
|
108
157
|
old_exists = true
|
109
158
|
end
|
159
|
+
|
110
160
|
if new_value == :none
|
111
161
|
new_exists = false
|
112
162
|
elsif new_value.nil?
|
@@ -124,18 +174,8 @@ module ChefFS
|
|
124
174
|
return true
|
125
175
|
end
|
126
176
|
|
127
|
-
if
|
128
|
-
|
129
|
-
elsif output_mode == :name_status
|
130
|
-
if old_value == :none || (old_value == nil && !old_entry.exists?)
|
131
|
-
yield "A\t#{new_entry.path_for_printing}\n"
|
132
|
-
elsif new_value == :none
|
133
|
-
yield "D\t#{new_entry.path_for_printing}\n"
|
134
|
-
else
|
135
|
-
yield "M\t#{new_entry.path_for_printing}\n"
|
136
|
-
end
|
137
|
-
else
|
138
|
-
# If we haven't read the values yet, get them now.
|
177
|
+
if get_content
|
178
|
+
# If we haven't read the values yet, get them now so that they can be diffed
|
139
179
|
begin
|
140
180
|
old_value = old_entry.read if old_value.nil?
|
141
181
|
rescue ChefFS::FileSystem::NotFoundError
|
@@ -146,23 +186,14 @@ module ChefFS
|
|
146
186
|
rescue ChefFS::FileSystem::NotFoundError
|
147
187
|
new_value = :none
|
148
188
|
end
|
189
|
+
end
|
149
190
|
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
old_path = "/dev/null"
|
157
|
-
old_value = ''
|
158
|
-
end
|
159
|
-
if new_value == :none
|
160
|
-
result << "deleted file\n"
|
161
|
-
new_path = "/dev/null"
|
162
|
-
new_value = ''
|
163
|
-
end
|
164
|
-
result << diff_text(old_path, new_path, old_value, new_value)
|
165
|
-
yield result
|
191
|
+
if old_value == :none || (old_value == nil && !old_entry.exists?)
|
192
|
+
yield [ :added, old_entry, new_entry, old_value, new_value ]
|
193
|
+
elsif new_value == :none
|
194
|
+
yield [ :deleted, old_entry, new_entry, old_value, new_value ]
|
195
|
+
else
|
196
|
+
yield [ :modified, old_entry, new_entry, old_value, new_value ]
|
166
197
|
end
|
167
198
|
end
|
168
199
|
end
|
data/lib/chef_fs/file_system.rb
CHANGED
@@ -17,6 +17,8 @@
|
|
17
17
|
#
|
18
18
|
|
19
19
|
require 'chef_fs/path_utils'
|
20
|
+
require 'chef_fs/file_system/operation_skipped_error'
|
21
|
+
require 'chef_fs/file_system/operation_not_allowed_error'
|
20
22
|
|
21
23
|
module ChefFS
|
22
24
|
module FileSystem
|
@@ -112,16 +114,20 @@ module ChefFS
|
|
112
114
|
# puts message
|
113
115
|
# end
|
114
116
|
#
|
115
|
-
def self.copy_to(pattern, src_root, dest_root, recurse_depth, options, ui)
|
117
|
+
def self.copy_to(pattern, src_root, dest_root, recurse_depth, options, ui, format_path)
|
116
118
|
found_result = false
|
119
|
+
error = false
|
117
120
|
list_pairs(pattern, src_root, dest_root) do |src, dest|
|
118
121
|
found_result = true
|
119
|
-
new_dest_parent = get_or_create_parent(dest, options, ui)
|
120
|
-
copy_entries(src, dest, new_dest_parent, recurse_depth, options, ui)
|
122
|
+
new_dest_parent = get_or_create_parent(dest, options, ui, format_path)
|
123
|
+
child_error = copy_entries(src, dest, new_dest_parent, recurse_depth, options, ui, format_path)
|
124
|
+
error ||= child_error
|
121
125
|
end
|
122
126
|
if !found_result && pattern.exact_path
|
123
127
|
ui.error "#{pattern}: No such file or directory on remote or local"
|
128
|
+
error = true
|
124
129
|
end
|
130
|
+
error
|
125
131
|
end
|
126
132
|
|
127
133
|
# Yield entries for children that are in either +a_root+ or +b_root+, with
|
@@ -215,7 +221,7 @@ module ChefFS
|
|
215
221
|
private
|
216
222
|
|
217
223
|
# Copy two entries (could be files or dirs)
|
218
|
-
def self.copy_entries(src_entry, dest_entry, new_dest_parent, recurse_depth, options, ui)
|
224
|
+
def self.copy_entries(src_entry, dest_entry, new_dest_parent, recurse_depth, options, ui, format_path)
|
219
225
|
# A NOTE about this algorithm:
|
220
226
|
# There are cases where this algorithm does too many network requests.
|
221
227
|
# knife upload with a specific filename will first check if the file
|
@@ -227,126 +233,140 @@ module ChefFS
|
|
227
233
|
# exist.
|
228
234
|
# Will need to decide how that works with checksums, though.
|
229
235
|
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
+
error = false
|
237
|
+
begin
|
238
|
+
dest_path = format_path.call(dest_entry)
|
239
|
+
src_path = format_path.call(src_entry)
|
240
|
+
if !src_entry.exists?
|
241
|
+
if options[:purge]
|
242
|
+
# If we would not have uploaded it, we will not purge it.
|
243
|
+
if src_entry.parent.can_have_child?(dest_entry.name, dest_entry.dir?)
|
244
|
+
if options[:dry_run]
|
245
|
+
ui.output "Would delete #{dest_path}"
|
246
|
+
else
|
247
|
+
dest_entry.delete(true)
|
248
|
+
ui.output "Deleted extra entry #{dest_path} (purge is on)"
|
249
|
+
end
|
236
250
|
else
|
237
|
-
|
238
|
-
ui.output "Deleted extra entry #{dest_entry.path_for_printing} (purge is on)"
|
251
|
+
Chef::Log.info("Not deleting extra entry #{dest_path} (purge is off)")
|
239
252
|
end
|
240
|
-
else
|
241
|
-
Chef::Log.info("Not deleting extra entry #{dest_entry.path_for_printing} (purge is off)")
|
242
253
|
end
|
243
|
-
end
|
244
254
|
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
255
|
+
elsif !dest_entry.exists?
|
256
|
+
if new_dest_parent.can_have_child?(src_entry.name, src_entry.dir?)
|
257
|
+
# If the entry can do a copy directly from filesystem, do that.
|
258
|
+
if new_dest_parent.respond_to?(:create_child_from)
|
259
|
+
if options[:dry_run]
|
260
|
+
ui.output "Would create #{dest_path}"
|
261
|
+
else
|
262
|
+
new_dest_parent.create_child_from(src_entry)
|
263
|
+
ui.output "Created #{dest_path}"
|
264
|
+
end
|
265
|
+
return
|
254
266
|
end
|
255
|
-
return
|
256
|
-
end
|
257
267
|
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
268
|
+
if src_entry.dir?
|
269
|
+
if options[:dry_run]
|
270
|
+
ui.output "Would create #{dest_path}"
|
271
|
+
new_dest_dir = new_dest_parent.child(src_entry.name)
|
272
|
+
else
|
273
|
+
new_dest_dir = new_dest_parent.create_child(src_entry.name, nil)
|
274
|
+
ui.output "Created #{dest_path}"
|
275
|
+
end
|
276
|
+
# Directory creation is recursive.
|
277
|
+
if recurse_depth != 0
|
278
|
+
src_entry.children.each do |src_child|
|
279
|
+
new_dest_child = new_dest_dir.child(src_child.name)
|
280
|
+
child_error = copy_entries(src_child, new_dest_child, new_dest_dir, recurse_depth ? recurse_depth - 1 : recurse_depth, options, ui, format_path)
|
281
|
+
error ||= child_error
|
282
|
+
end
|
271
283
|
end
|
272
|
-
end
|
273
|
-
else
|
274
|
-
if options[:dry_run]
|
275
|
-
ui.output "Would create #{dest_entry.path_for_printing}"
|
276
284
|
else
|
277
|
-
|
278
|
-
|
285
|
+
if options[:dry_run]
|
286
|
+
ui.output "Would create #{dest_path}"
|
287
|
+
else
|
288
|
+
new_dest_parent.create_child(src_entry.name, src_entry.read)
|
289
|
+
ui.output "Created #{dest_path}"
|
290
|
+
end
|
279
291
|
end
|
280
292
|
end
|
281
|
-
end
|
282
|
-
|
283
|
-
else
|
284
|
-
# Both exist.
|
285
293
|
|
286
|
-
|
287
|
-
|
288
|
-
if options[:force] || compare(src_entry, dest_entry)[0] == false
|
289
|
-
if options[:dry_run]
|
290
|
-
ui.output "Would update #{dest_entry.path_for_printing}"
|
291
|
-
else
|
292
|
-
dest_entry.copy_from(src_entry)
|
293
|
-
ui.output "Updated #{dest_entry.path_for_printing}"
|
294
|
-
end
|
295
|
-
end
|
296
|
-
return
|
297
|
-
end
|
294
|
+
else
|
295
|
+
# Both exist.
|
298
296
|
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
297
|
+
# If the entry can do a copy directly, do that.
|
298
|
+
if dest_entry.respond_to?(:copy_from)
|
299
|
+
if options[:force] || compare(src_entry, dest_entry)[0] == false
|
300
|
+
if options[:dry_run]
|
301
|
+
ui.output "Would update #{dest_path}"
|
302
|
+
else
|
303
|
+
dest_entry.copy_from(src_entry)
|
304
|
+
ui.output "Updated #{dest_path}"
|
306
305
|
end
|
307
306
|
end
|
308
|
-
else
|
309
|
-
# If they are different types.
|
310
|
-
ui.error("File #{dest_entry.path_for_printing} is a directory while file #{dest_entry.path_for_printing} is a regular file\n")
|
311
307
|
return
|
312
308
|
end
|
313
|
-
else
|
314
|
-
if dest_entry.dir?
|
315
|
-
ui.error("File #{dest_entry.path_for_printing} is a directory while file #{dest_entry.path_for_printing} is a regular file\n")
|
316
|
-
return
|
317
|
-
else
|
318
309
|
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
310
|
+
# If they are different types, log an error.
|
311
|
+
if src_entry.dir?
|
312
|
+
if dest_entry.dir?
|
313
|
+
# If both are directories, recurse into their children
|
314
|
+
if recurse_depth != 0
|
315
|
+
child_pairs(src_entry, dest_entry).each do |src_child, dest_child|
|
316
|
+
child_error = copy_entries(src_child, dest_child, dest_entry, recurse_depth ? recurse_depth - 1 : recurse_depth, options, ui, format_path)
|
317
|
+
error ||= child_error
|
318
|
+
end
|
319
|
+
end
|
323
320
|
else
|
324
|
-
|
325
|
-
|
321
|
+
# If they are different types.
|
322
|
+
ui.error("File #{src_path} is a directory while file #{dest_path} is a regular file\n")
|
323
|
+
return
|
326
324
|
end
|
327
|
-
|
328
|
-
|
329
|
-
|
325
|
+
else
|
326
|
+
if dest_entry.dir?
|
327
|
+
ui.error("File #{src_path} is a directory while file #{dest_path} is a regular file\n")
|
328
|
+
return
|
329
|
+
else
|
330
|
+
|
331
|
+
# Both are files! Copy them unless we're sure they are the same.
|
332
|
+
if options[:force]
|
333
|
+
should_copy = true
|
334
|
+
src_value = nil
|
330
335
|
else
|
331
|
-
src_value = src_entry
|
332
|
-
|
333
|
-
|
336
|
+
are_same, src_value, dest_value = compare(src_entry, dest_entry)
|
337
|
+
should_copy = !are_same
|
338
|
+
end
|
339
|
+
if should_copy
|
340
|
+
if options[:dry_run]
|
341
|
+
ui.output "Would update #{dest_path}"
|
342
|
+
else
|
343
|
+
src_value = src_entry.read if src_value.nil?
|
344
|
+
dest_entry.write(src_value)
|
345
|
+
ui.output "Updated #{dest_path}"
|
346
|
+
end
|
334
347
|
end
|
335
348
|
end
|
336
349
|
end
|
337
350
|
end
|
351
|
+
rescue OperationSkippedError
|
352
|
+
# If it was simply skipped, a warning has already been printed.
|
353
|
+
rescue OperationNotAllowedError => e
|
354
|
+
ui.error e.message
|
355
|
+
error = true
|
338
356
|
end
|
357
|
+
error
|
339
358
|
end
|
340
359
|
|
341
|
-
def self.get_or_create_parent(entry, options, ui)
|
360
|
+
def self.get_or_create_parent(entry, options, ui, format_path)
|
342
361
|
parent = entry.parent
|
343
362
|
if parent && !parent.exists?
|
344
|
-
|
363
|
+
parent_path = format_path.call(parent)
|
364
|
+
parent_parent = get_or_create_parent(entry.parent, options, ui, format_path)
|
345
365
|
if options[:dry_run]
|
346
|
-
ui.output "Would create #{
|
366
|
+
ui.output "Would create #{parent_path}"
|
347
367
|
else
|
348
|
-
parent = parent_parent.create_child(parent.name,
|
349
|
-
ui.output "Created #{
|
368
|
+
parent = parent_parent.create_child(parent.name, nil)
|
369
|
+
ui.output "Created #{parent_path}"
|
350
370
|
end
|
351
371
|
end
|
352
372
|
return parent
|