knife-essentials 0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +201 -0
- data/README.rdoc +114 -0
- data/Rakefile +24 -0
- data/lib/chef/knife/diff.rb +28 -0
- data/lib/chef/knife/list.rb +107 -0
- data/lib/chef/knife/show.rb +30 -0
- data/lib/chef_fs.rb +9 -0
- data/lib/chef_fs/command_line.rb +91 -0
- data/lib/chef_fs/diff.rb +158 -0
- data/lib/chef_fs/file_pattern.rb +292 -0
- data/lib/chef_fs/file_system.rb +69 -0
- data/lib/chef_fs/file_system/base_fs_dir.rb +23 -0
- data/lib/chef_fs/file_system/base_fs_object.rb +52 -0
- data/lib/chef_fs/file_system/chef_server_root_dir.rb +48 -0
- data/lib/chef_fs/file_system/cookbook_dir.rb +80 -0
- data/lib/chef_fs/file_system/cookbook_file.rb +32 -0
- data/lib/chef_fs/file_system/cookbook_subdir.rb +25 -0
- data/lib/chef_fs/file_system/cookbooks_dir.rb +21 -0
- data/lib/chef_fs/file_system/data_bag_dir.rb +22 -0
- data/lib/chef_fs/file_system/data_bags_dir.rb +23 -0
- data/lib/chef_fs/file_system/file_system_entry.rb +36 -0
- data/lib/chef_fs/file_system/file_system_root_dir.rb +11 -0
- data/lib/chef_fs/file_system/nonexistent_fs_object.rb +23 -0
- data/lib/chef_fs/file_system/not_found_exception.rb +12 -0
- data/lib/chef_fs/file_system/rest_list_dir.rb +42 -0
- data/lib/chef_fs/file_system/rest_list_entry.rb +72 -0
- data/lib/chef_fs/knife.rb +47 -0
- data/lib/chef_fs/path_utils.rb +43 -0
- data/lib/chef_fs/version.rb +4 -0
- data/spec/chef_fs/diff_spec.rb +263 -0
- data/spec/chef_fs/file_pattern_spec.rb +507 -0
- data/spec/chef_fs/file_system_spec.rb +117 -0
- data/spec/support/file_system_support.rb +108 -0
- metadata +79 -0
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'chef_fs/file_system/base_fs_object'
|
2
|
+
|
3
|
+
module ChefFS
|
4
|
+
module FileSystem
|
5
|
+
class NonexistentFSObject < BaseFSObject
|
6
|
+
def initialize(name, parent)
|
7
|
+
super
|
8
|
+
end
|
9
|
+
|
10
|
+
def exists?
|
11
|
+
false
|
12
|
+
end
|
13
|
+
|
14
|
+
def child(name)
|
15
|
+
NonexistentFSObject.new(name, self)
|
16
|
+
end
|
17
|
+
|
18
|
+
def read
|
19
|
+
raise ChefFS::FileSystem::NotFoundException, "Nonexistent object"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module ChefFS
|
2
|
+
module FileSystem
|
3
|
+
class NotFoundException < Exception
|
4
|
+
def initialize(other_exception)
|
5
|
+
super(other_exception.respond_to?(:message) ? other_exception.message : message)
|
6
|
+
@exception = other_exception
|
7
|
+
end
|
8
|
+
|
9
|
+
attr_reader :exception
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'chef_fs/file_system/base_fs_dir'
|
2
|
+
require 'chef_fs/file_system/rest_list_entry'
|
3
|
+
|
4
|
+
# TODO: take environment into account
|
5
|
+
|
6
|
+
module ChefFS
|
7
|
+
module FileSystem
|
8
|
+
class RestListDir < BaseFSDir
|
9
|
+
def initialize(name, parent, api_path = nil)
|
10
|
+
super(name, parent)
|
11
|
+
@api_path = api_path || (parent.api_path == "" ? name : "#{parent.api_path}/#{name}")
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_reader :api_path
|
15
|
+
|
16
|
+
def child(name)
|
17
|
+
result = @children.select { |child| child.name == name }.first if @children
|
18
|
+
result || RestListEntry.new(name, self)
|
19
|
+
end
|
20
|
+
|
21
|
+
def children
|
22
|
+
begin
|
23
|
+
@children ||= rest.get_rest(api_path).keys.map { |key| RestListEntry.new("#{key}.json", self, true) }
|
24
|
+
rescue Net::HTTPServerException
|
25
|
+
if $!.response.code == "404"
|
26
|
+
raise ChefFS::FileSystem::NotFoundException, $!
|
27
|
+
else
|
28
|
+
raise
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def environment
|
34
|
+
parent.environment
|
35
|
+
end
|
36
|
+
|
37
|
+
def rest
|
38
|
+
parent.rest
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'chef_fs/file_system/base_fs_object'
|
2
|
+
require 'chef_fs/file_system/not_found_exception'
|
3
|
+
# TODO: these are needed for rest.get_rest() to work. This seems strange.
|
4
|
+
require 'chef/role'
|
5
|
+
require 'chef/node'
|
6
|
+
|
7
|
+
# TODO: take environment into account
|
8
|
+
module ChefFS
|
9
|
+
module FileSystem
|
10
|
+
class RestListEntry < BaseFSObject
|
11
|
+
def initialize(name, parent, exists = nil)
|
12
|
+
super(name, parent)
|
13
|
+
@exists = exists
|
14
|
+
end
|
15
|
+
|
16
|
+
def api_path
|
17
|
+
if name.length < 5 && name[-5,5] != ".json"
|
18
|
+
raise "Invalid name #{name}: must include .json"
|
19
|
+
end
|
20
|
+
api_child_name = name[0,name.length-5]
|
21
|
+
environment ? "#{parent.api_path}/#{api_child_name}/environments/#{environment}" : "#{parent.api_path}/#{api_child_name}"
|
22
|
+
end
|
23
|
+
|
24
|
+
def environment
|
25
|
+
parent.environment
|
26
|
+
end
|
27
|
+
|
28
|
+
def exists?
|
29
|
+
if @exists.nil?
|
30
|
+
@exists = parent.children.any? { |child| child.name == name }
|
31
|
+
end
|
32
|
+
@exists
|
33
|
+
end
|
34
|
+
|
35
|
+
def delete
|
36
|
+
begin
|
37
|
+
rest.delete_rest(api_path)
|
38
|
+
rescue Net::HTTPServerException
|
39
|
+
if $!.response.code == "404"
|
40
|
+
raise ChefFS::FileSystem::NotFoundException, $!
|
41
|
+
else
|
42
|
+
raise
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def read
|
48
|
+
begin
|
49
|
+
Chef::JSONCompat.to_json_pretty(rest.get_rest(api_path).to_hash)
|
50
|
+
rescue Net::HTTPServerException
|
51
|
+
if $!.response.code == "404"
|
52
|
+
raise ChefFS::FileSystem::NotFoundException, $!
|
53
|
+
else
|
54
|
+
raise
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def rest
|
60
|
+
parent.rest
|
61
|
+
end
|
62
|
+
|
63
|
+
def content_type
|
64
|
+
:json
|
65
|
+
end
|
66
|
+
|
67
|
+
def write(contents)
|
68
|
+
rest.put_rest(api_path, contents)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'chef_fs/file_system/chef_server_root_dir'
|
2
|
+
require 'chef_fs/file_system/file_system_root_dir'
|
3
|
+
require 'chef_fs/file_pattern'
|
4
|
+
require 'chef_fs/path_utils'
|
5
|
+
require 'chef/config'
|
6
|
+
|
7
|
+
module ChefFS
|
8
|
+
class Knife < Chef::Knife
|
9
|
+
def base_path
|
10
|
+
@base_path ||= "/" + ChefFS::PathUtils::relative_to(File.absolute_path(Dir.pwd), chef_repo)
|
11
|
+
end
|
12
|
+
|
13
|
+
def chef_fs
|
14
|
+
@chef_fs ||= ChefFS::FileSystem::ChefServerRootDir.new("remote", Chef::Config)
|
15
|
+
end
|
16
|
+
|
17
|
+
def chef_repo
|
18
|
+
@chef_repo ||= File.absolute_path(File.join(Chef::Config.cookbook_path, ".."))
|
19
|
+
end
|
20
|
+
|
21
|
+
def format_path(path)
|
22
|
+
if path[0,base_path.length] == base_path
|
23
|
+
if path == base_path
|
24
|
+
return "."
|
25
|
+
elsif path[base_path.length] == "/"
|
26
|
+
return path[base_path.length + 1, path.length - base_path.length - 1]
|
27
|
+
elsif base_path == "/" && path[0] == "/"
|
28
|
+
return path[1, path.length - 1]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
path
|
32
|
+
end
|
33
|
+
|
34
|
+
def local_fs
|
35
|
+
@local_fs ||= ChefFS::FileSystem::FileSystemRootDir.new(chef_repo)
|
36
|
+
end
|
37
|
+
|
38
|
+
def pattern_args
|
39
|
+
@pattern_args ||= pattern_args_from(name_args)
|
40
|
+
end
|
41
|
+
|
42
|
+
def pattern_args_from(args)
|
43
|
+
args.map { |arg| ChefFS::FilePattern::relative_to(base_path, arg) }.to_a
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'chef_fs'
|
2
|
+
|
3
|
+
module ChefFS
|
4
|
+
class PathUtils
|
5
|
+
|
6
|
+
# If you are in 'source', this is what you would have to type to reach 'dest'
|
7
|
+
# relative_to('/a/b/c/d/e', '/a/b/x/y') == '../../c/d/e'
|
8
|
+
# relative_to('/a/b', '/a/b') == ''
|
9
|
+
def self.relative_to(dest, source)
|
10
|
+
# Skip past the common parts
|
11
|
+
source_parts = ChefFS::PathUtils.split(source)
|
12
|
+
dest_parts = ChefFS::PathUtils.split(dest)
|
13
|
+
i = 0
|
14
|
+
until i >= source_parts.length || i >= dest_parts.length || source_parts[i] != source_parts[i]
|
15
|
+
i+=1
|
16
|
+
end
|
17
|
+
# dot-dot up from 'source' to the common ancestor, then
|
18
|
+
# descend to 'dest' from the common ancestor
|
19
|
+
ChefFS::PathUtils.join(*(['..']*(source_parts.length-i) + dest_parts[i,dest.length-i]))
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.join(*parts)
|
23
|
+
return "" if parts.length == 0
|
24
|
+
# Determine if it started with a slash
|
25
|
+
absolute = parts[0].length == 0 || parts[0].length > 0 && parts[0][0] =~ /^#{regexp_path_separator}/
|
26
|
+
# Remove leading and trailing slashes from each part so that the join will work (and the slash at the end will go away)
|
27
|
+
parts = parts.map { |part| part.gsub(/^\/|\/$/, "") }
|
28
|
+
# Don't join empty bits
|
29
|
+
result = parts.select { |part| part != "" }.join("/")
|
30
|
+
# Put the / back on
|
31
|
+
absolute ? "/#{result}" : result
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.split(path)
|
35
|
+
path.split(Regexp.new(regexp_path_separator))
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.regexp_path_separator
|
39
|
+
ChefFS::windows? ? '[/\\]' : '/'
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,263 @@
|
|
1
|
+
require 'support/file_system_support'
|
2
|
+
require 'chef_fs/diff'
|
3
|
+
require 'chef_fs/file_pattern'
|
4
|
+
require 'chef_fs/command_line'
|
5
|
+
|
6
|
+
describe ChefFS::Diff do
|
7
|
+
include FileSystemSupport
|
8
|
+
|
9
|
+
context 'with two filesystems with all types of difference' do
|
10
|
+
let(:a) {
|
11
|
+
memory_fs('a', {
|
12
|
+
:both_dirs => {
|
13
|
+
:sub_both_dirs => { :subsub => nil },
|
14
|
+
:sub_both_files => nil,
|
15
|
+
:sub_both_files_different => "a\n",
|
16
|
+
:sub_both_dirs_empty => {},
|
17
|
+
:sub_a_only_dir => { :subsub => nil },
|
18
|
+
:sub_a_only_file => nil,
|
19
|
+
:sub_dir_in_a_file_in_b => {},
|
20
|
+
:sub_file_in_a_dir_in_b => nil
|
21
|
+
},
|
22
|
+
:both_files => nil,
|
23
|
+
:both_files_different => "a\n",
|
24
|
+
:both_dirs_empty => {},
|
25
|
+
:a_only_dir => { :subsub => nil },
|
26
|
+
:a_only_file => nil,
|
27
|
+
:dir_in_a_file_in_b => {},
|
28
|
+
:file_in_a_dir_in_b => nil
|
29
|
+
})
|
30
|
+
}
|
31
|
+
let(:b) {
|
32
|
+
memory_fs('b', {
|
33
|
+
:both_dirs => {
|
34
|
+
:sub_both_dirs => { :subsub => nil },
|
35
|
+
:sub_both_files => nil,
|
36
|
+
:sub_both_files_different => "b\n",
|
37
|
+
:sub_both_dirs_empty => {},
|
38
|
+
:sub_b_only_dir => { :subsub => nil },
|
39
|
+
:sub_b_only_file => nil,
|
40
|
+
:sub_dir_in_a_file_in_b => nil,
|
41
|
+
:sub_file_in_a_dir_in_b => {}
|
42
|
+
},
|
43
|
+
:both_files => nil,
|
44
|
+
:both_files_different => "b\n",
|
45
|
+
:both_dirs_empty => {},
|
46
|
+
:b_only_dir => { :subsub => nil },
|
47
|
+
:b_only_file => nil,
|
48
|
+
:dir_in_a_file_in_b => nil,
|
49
|
+
:file_in_a_dir_in_b => {}
|
50
|
+
})
|
51
|
+
}
|
52
|
+
it 'diffable_leaves' do
|
53
|
+
diffable_leaves_should_yield_paths(a, b, nil,
|
54
|
+
%w(
|
55
|
+
/both_dirs/sub_both_dirs/subsub
|
56
|
+
/both_dirs/sub_both_files
|
57
|
+
/both_dirs/sub_both_files_different
|
58
|
+
/both_dirs/sub_both_dirs_empty
|
59
|
+
/both_dirs/sub_a_only_dir
|
60
|
+
/both_dirs/sub_a_only_file
|
61
|
+
/both_dirs/sub_b_only_dir
|
62
|
+
/both_dirs/sub_b_only_file
|
63
|
+
/both_dirs/sub_dir_in_a_file_in_b
|
64
|
+
/both_dirs/sub_file_in_a_dir_in_b
|
65
|
+
/both_files
|
66
|
+
/both_files_different
|
67
|
+
/both_dirs_empty
|
68
|
+
/a_only_dir
|
69
|
+
/a_only_file
|
70
|
+
/b_only_dir
|
71
|
+
/b_only_file
|
72
|
+
/dir_in_a_file_in_b
|
73
|
+
/file_in_a_dir_in_b
|
74
|
+
))
|
75
|
+
end
|
76
|
+
it 'diffable_leaves_from_pattern(/**file*)' do
|
77
|
+
diffable_leaves_from_pattern_should_yield_paths(pattern('/**file*'), a, b, nil,
|
78
|
+
%w(
|
79
|
+
/both_dirs/sub_both_files
|
80
|
+
/both_dirs/sub_both_files_different
|
81
|
+
/both_dirs/sub_a_only_file
|
82
|
+
/both_dirs/sub_b_only_file
|
83
|
+
/both_dirs/sub_dir_in_a_file_in_b
|
84
|
+
/both_dirs/sub_file_in_a_dir_in_b
|
85
|
+
/both_files
|
86
|
+
/both_files_different
|
87
|
+
/a_only_file
|
88
|
+
/b_only_file
|
89
|
+
/dir_in_a_file_in_b
|
90
|
+
/file_in_a_dir_in_b
|
91
|
+
))
|
92
|
+
end
|
93
|
+
it 'diffable_leaves_from_pattern(/*dir*)' do
|
94
|
+
diffable_leaves_from_pattern_should_yield_paths(pattern('/*dir*'), a, b, nil,
|
95
|
+
%w(
|
96
|
+
/both_dirs/sub_both_dirs/subsub
|
97
|
+
/both_dirs/sub_both_files
|
98
|
+
/both_dirs/sub_both_files_different
|
99
|
+
/both_dirs/sub_both_dirs_empty
|
100
|
+
/both_dirs/sub_a_only_dir
|
101
|
+
/both_dirs/sub_a_only_file
|
102
|
+
/both_dirs/sub_b_only_dir
|
103
|
+
/both_dirs/sub_b_only_file
|
104
|
+
/both_dirs/sub_dir_in_a_file_in_b
|
105
|
+
/both_dirs/sub_file_in_a_dir_in_b
|
106
|
+
/both_dirs_empty
|
107
|
+
/a_only_dir
|
108
|
+
/b_only_dir
|
109
|
+
/dir_in_a_file_in_b
|
110
|
+
/file_in_a_dir_in_b
|
111
|
+
))
|
112
|
+
end
|
113
|
+
it 'ChefFS::CommandLine.diff(/)' do
|
114
|
+
results = []
|
115
|
+
ChefFS::CommandLine.diff(pattern('/'), a, b, nil) do |diff|
|
116
|
+
results << diff.gsub(/\s+\d\d\d\d-\d\d-\d\d\s\d?\d:\d\d:\d\d\.\d{9} -\d\d\d\d/, ' DATE')
|
117
|
+
end
|
118
|
+
results.should =~ [
|
119
|
+
'diff --knife a/both_dirs/sub_both_files_different b/both_dirs/sub_both_files_different
|
120
|
+
--- a/both_dirs/sub_both_files_different DATE
|
121
|
+
+++ b/both_dirs/sub_both_files_different DATE
|
122
|
+
@@ -1 +1 @@
|
123
|
+
-a
|
124
|
+
+b
|
125
|
+
','Common subdirectories: /both_dirs/sub_both_dirs_empty
|
126
|
+
','Only in a/both_dirs: sub_a_only_dir
|
127
|
+
','diff --knife a/both_dirs/sub_a_only_file b/both_dirs/sub_a_only_file
|
128
|
+
deleted file
|
129
|
+
--- a/both_dirs/sub_a_only_file DATE
|
130
|
+
+++ /dev/null DATE
|
131
|
+
@@ -1 +0,0 @@
|
132
|
+
-sub_a_only_file
|
133
|
+
','File b/both_dirs/sub_dir_in_a_file_in_b is a directory while file b/both_dirs/sub_dir_in_a_file_in_b is a regular file
|
134
|
+
','File a/both_dirs/sub_file_in_a_dir_in_b is a regular file while file a/both_dirs/sub_file_in_a_dir_in_b is a directory
|
135
|
+
','Only in b/both_dirs: sub_b_only_dir
|
136
|
+
','diff --knife a/both_dirs/sub_b_only_file b/both_dirs/sub_b_only_file
|
137
|
+
new file
|
138
|
+
--- /dev/null DATE
|
139
|
+
+++ b/both_dirs/sub_b_only_file DATE
|
140
|
+
@@ -0,0 +1 @@
|
141
|
+
+sub_b_only_file
|
142
|
+
','diff --knife a/both_files_different b/both_files_different
|
143
|
+
--- a/both_files_different DATE
|
144
|
+
+++ b/both_files_different DATE
|
145
|
+
@@ -1 +1 @@
|
146
|
+
-a
|
147
|
+
+b
|
148
|
+
','Common subdirectories: /both_dirs_empty
|
149
|
+
','Only in a: a_only_dir
|
150
|
+
','diff --knife a/a_only_file b/a_only_file
|
151
|
+
deleted file
|
152
|
+
--- a/a_only_file DATE
|
153
|
+
+++ /dev/null DATE
|
154
|
+
@@ -1 +0,0 @@
|
155
|
+
-a_only_file
|
156
|
+
','File b/dir_in_a_file_in_b is a directory while file b/dir_in_a_file_in_b is a regular file
|
157
|
+
','File a/file_in_a_dir_in_b is a regular file while file a/file_in_a_dir_in_b is a directory
|
158
|
+
','Only in b: b_only_dir
|
159
|
+
','diff --knife a/b_only_file b/b_only_file
|
160
|
+
new file
|
161
|
+
--- /dev/null DATE
|
162
|
+
+++ b/b_only_file DATE
|
163
|
+
@@ -0,0 +1 @@
|
164
|
+
+b_only_file
|
165
|
+
' ]
|
166
|
+
end
|
167
|
+
it 'ChefFS::CommandLine.diff(/both_dirs)' do
|
168
|
+
results = []
|
169
|
+
ChefFS::CommandLine.diff(pattern('/both_dirs'), a, b, nil) do |diff|
|
170
|
+
results << diff.gsub(/\s+\d\d\d\d-\d\d-\d\d\s\d?\d:\d\d:\d\d\.\d{9} -\d\d\d\d/, ' DATE')
|
171
|
+
end
|
172
|
+
results.should =~ [
|
173
|
+
'diff --knife a/both_dirs/sub_both_files_different b/both_dirs/sub_both_files_different
|
174
|
+
--- a/both_dirs/sub_both_files_different DATE
|
175
|
+
+++ b/both_dirs/sub_both_files_different DATE
|
176
|
+
@@ -1 +1 @@
|
177
|
+
-a
|
178
|
+
+b
|
179
|
+
','Common subdirectories: /both_dirs/sub_both_dirs_empty
|
180
|
+
','Only in a/both_dirs: sub_a_only_dir
|
181
|
+
','diff --knife a/both_dirs/sub_a_only_file b/both_dirs/sub_a_only_file
|
182
|
+
deleted file
|
183
|
+
--- a/both_dirs/sub_a_only_file DATE
|
184
|
+
+++ /dev/null DATE
|
185
|
+
@@ -1 +0,0 @@
|
186
|
+
-sub_a_only_file
|
187
|
+
','File b/both_dirs/sub_dir_in_a_file_in_b is a directory while file b/both_dirs/sub_dir_in_a_file_in_b is a regular file
|
188
|
+
','File a/both_dirs/sub_file_in_a_dir_in_b is a regular file while file a/both_dirs/sub_file_in_a_dir_in_b is a directory
|
189
|
+
','Only in b/both_dirs: sub_b_only_dir
|
190
|
+
','diff --knife a/both_dirs/sub_b_only_file b/both_dirs/sub_b_only_file
|
191
|
+
new file
|
192
|
+
--- /dev/null DATE
|
193
|
+
+++ b/both_dirs/sub_b_only_file DATE
|
194
|
+
@@ -0,0 +1 @@
|
195
|
+
+sub_b_only_file
|
196
|
+
' ]
|
197
|
+
end
|
198
|
+
it 'ChefFS::CommandLine.diff(/) with depth 1' do
|
199
|
+
results = []
|
200
|
+
ChefFS::CommandLine.diff(pattern('/'), a, b, 1) do |diff|
|
201
|
+
results << diff.gsub(/\s+\d\d\d\d-\d\d-\d\d\s\d?\d:\d\d:\d\d\.\d{9} -\d\d\d\d/, ' DATE')
|
202
|
+
end
|
203
|
+
results.should =~ [
|
204
|
+
'Common subdirectories: /both_dirs
|
205
|
+
','diff --knife a/both_files_different b/both_files_different
|
206
|
+
--- a/both_files_different DATE
|
207
|
+
+++ b/both_files_different DATE
|
208
|
+
@@ -1 +1 @@
|
209
|
+
-a
|
210
|
+
+b
|
211
|
+
','Common subdirectories: /both_dirs_empty
|
212
|
+
','Only in a: a_only_dir
|
213
|
+
','diff --knife a/a_only_file b/a_only_file
|
214
|
+
deleted file
|
215
|
+
--- a/a_only_file DATE
|
216
|
+
+++ /dev/null DATE
|
217
|
+
@@ -1 +0,0 @@
|
218
|
+
-a_only_file
|
219
|
+
','File b/dir_in_a_file_in_b is a directory while file b/dir_in_a_file_in_b is a regular file
|
220
|
+
','File a/file_in_a_dir_in_b is a regular file while file a/file_in_a_dir_in_b is a directory
|
221
|
+
','Only in b: b_only_dir
|
222
|
+
','diff --knife a/b_only_file b/b_only_file
|
223
|
+
new file
|
224
|
+
--- /dev/null DATE
|
225
|
+
+++ b/b_only_file DATE
|
226
|
+
@@ -0,0 +1 @@
|
227
|
+
+b_only_file
|
228
|
+
' ]
|
229
|
+
end
|
230
|
+
it 'ChefFS::CommandLine.diff(/*_*) with depth 0' do
|
231
|
+
results = []
|
232
|
+
ChefFS::CommandLine.diff(pattern('/*_*'), a, b, 0) do |diff|
|
233
|
+
results << diff.gsub(/\s+\d\d\d\d-\d\d-\d\d\s\d?\d:\d\d:\d\d\.\d{9} -\d\d\d\d/, ' DATE')
|
234
|
+
end
|
235
|
+
results.should =~ [
|
236
|
+
'Common subdirectories: /both_dirs
|
237
|
+
','diff --knife a/both_files_different b/both_files_different
|
238
|
+
--- a/both_files_different DATE
|
239
|
+
+++ b/both_files_different DATE
|
240
|
+
@@ -1 +1 @@
|
241
|
+
-a
|
242
|
+
+b
|
243
|
+
','Common subdirectories: /both_dirs_empty
|
244
|
+
','Only in a: a_only_dir
|
245
|
+
','diff --knife a/a_only_file b/a_only_file
|
246
|
+
deleted file
|
247
|
+
--- a/a_only_file DATE
|
248
|
+
+++ /dev/null DATE
|
249
|
+
@@ -1 +0,0 @@
|
250
|
+
-a_only_file
|
251
|
+
','File b/dir_in_a_file_in_b is a directory while file b/dir_in_a_file_in_b is a regular file
|
252
|
+
','File a/file_in_a_dir_in_b is a regular file while file a/file_in_a_dir_in_b is a directory
|
253
|
+
','Only in b: b_only_dir
|
254
|
+
','diff --knife a/b_only_file b/b_only_file
|
255
|
+
new file
|
256
|
+
--- /dev/null DATE
|
257
|
+
+++ b/b_only_file DATE
|
258
|
+
@@ -0,0 +1 @@
|
259
|
+
+b_only_file
|
260
|
+
' ]
|
261
|
+
end
|
262
|
+
end
|
263
|
+
end
|