between_meals 0.0.6 → 0.0.11
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.
- checksums.yaml +7 -0
- data/README.md +7 -3
- data/lib/between_meals/changes/change.rb +3 -6
- data/lib/between_meals/changes/cookbook.rb +90 -23
- data/lib/between_meals/changes/databag.rb +3 -1
- data/lib/between_meals/changes/role.rb +4 -2
- data/lib/between_meals/changeset.rb +10 -4
- data/lib/between_meals/cmd.rb +14 -5
- data/lib/between_meals/knife.rb +55 -23
- data/lib/between_meals/repo.rb +2 -2
- data/lib/between_meals/repo/git.rb +26 -24
- data/lib/between_meals/repo/hg.rb +26 -27
- data/lib/between_meals/repo/hg/cmd.rb +1 -1
- data/lib/between_meals/repo/svn.rb +6 -7
- data/lib/between_meals/util.rb +44 -18
- metadata +119 -152
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: e58d518baa0534eecc6de15ac0fb0f7f09a6069f6fb870a60c55adf2cf2f8404
|
4
|
+
data.tar.gz: 44aaa21c488bea122a228466f0c30f5d0c9eab3ff778b3f60242cccaf2020ee6
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 7a44420814d8e34888bea5be482a7d8b43d30979c0c8369cb11e0b13ff4cddc36e0a3da29a955d70917ba9b878fa75213640b718658c0f4b6fabbd199e002f8a
|
7
|
+
data.tar.gz: 12dece7d9a249c883bef1eb0c6460977998fbc7b7e6ba90ecaf5bb7912d374df72b919bd78b1aece7548e1063664e04b6d80007ad5c68baaf2a587060cc6a0aa
|
data/README.md
CHANGED
@@ -1,13 +1,14 @@
|
|
1
1
|
# Between Meals
|
2
2
|
|
3
|
-
[](http://travis-ci.org/facebook/between-meals)
|
4
|
+
[](https://circleci.com/gh/facebook/between-meals)
|
4
5
|
|
5
6
|
## Intro
|
6
7
|
Ohai!
|
7
8
|
|
8
|
-
Between Meals is the library for calculating what Chef objects
|
9
|
+
Between Meals is the library for calculating what Chef objects were modified
|
9
10
|
between two revisions in a version control system. It is also the library
|
10
|
-
that
|
11
|
+
that backs Taste Tester and Grocery Delivery.
|
11
12
|
|
12
13
|
It currently supports SVN, GIT and HG, but plugins can easily be written for
|
13
14
|
other source control systems.
|
@@ -22,3 +23,6 @@ functions.
|
|
22
23
|
* Mixlib::ShellOut
|
23
24
|
* Rugged
|
24
25
|
|
26
|
+
## License
|
27
|
+
|
28
|
+
See the `LICENSE` file in this repo.
|
@@ -37,15 +37,11 @@ module BetweenMeals
|
|
37
37
|
end
|
38
38
|
|
39
39
|
def self.info(msg)
|
40
|
-
|
41
|
-
@@logger.info(msg)
|
42
|
-
end
|
40
|
+
@@logger&.info(msg)
|
43
41
|
end
|
44
42
|
|
45
43
|
def self.debug(msg)
|
46
|
-
|
47
|
-
@@logger.debug(msg)
|
48
|
-
end
|
44
|
+
@@logger&.debug(msg)
|
49
45
|
end
|
50
46
|
|
51
47
|
def info(msg)
|
@@ -58,3 +54,4 @@ module BetweenMeals
|
|
58
54
|
end
|
59
55
|
end
|
60
56
|
end
|
57
|
+
# rubocop:enable ClassVars
|
@@ -14,50 +14,111 @@
|
|
14
14
|
# See the License for the specific language governing permissions and
|
15
15
|
# limitations under the License.
|
16
16
|
|
17
|
-
# rubocop:disable ClassVars
|
18
17
|
module BetweenMeals
|
19
18
|
module Changes
|
20
19
|
# Changeset aware cookbook
|
21
20
|
class Cookbook < Change
|
22
|
-
def self.meaningful_cookbook_file?(path
|
23
|
-
|
24
|
-
re = %r{^#{dir}/([^/]+)/.*}
|
25
|
-
m = path.match(re)
|
26
|
-
debug("[cookbook] #{path} meaningful? [#{re}]: #{m}")
|
27
|
-
return true if m
|
28
|
-
end
|
29
|
-
false
|
21
|
+
def self.meaningful_cookbook_file?(path)
|
22
|
+
!explode_path(path).nil?
|
30
23
|
end
|
31
24
|
|
32
|
-
def self.explode_path(path
|
33
|
-
cookbook_dirs.each do |dir|
|
25
|
+
def self.explode_path(path)
|
26
|
+
@cookbook_dirs.each do |dir|
|
34
27
|
re = %r{^#{dir}/([^/]+)/.*}
|
35
28
|
debug("[cookbook] Matching #{path} against ^#{re}")
|
36
29
|
m = path.match(re)
|
37
30
|
next unless m
|
31
|
+
|
38
32
|
info("Cookbook is #{m[1]}")
|
39
33
|
return {
|
40
34
|
:cookbook_dir => dir,
|
41
|
-
:name => m[1]
|
35
|
+
:name => m[1],
|
36
|
+
}
|
42
37
|
end
|
43
38
|
nil
|
44
39
|
end
|
45
40
|
|
41
|
+
def self.map_symlinks(files)
|
42
|
+
# For each symlink get the source path, if any files have changed under
|
43
|
+
# the source path, fake them as coming from the symlink path. This
|
44
|
+
# allows the normal cookbook logic to just work.
|
45
|
+
symlinks = {}
|
46
|
+
@cookbook_dirs.each do |dir|
|
47
|
+
dir = File.join(@repo_dir, dir)
|
48
|
+
# Find symlinks in each cookbook_dir
|
49
|
+
links = Dir.foreach(dir).select do |d|
|
50
|
+
File.symlink?(File.join(dir, d))
|
51
|
+
end
|
52
|
+
links.each do |link|
|
53
|
+
link = File.join(dir, link)
|
54
|
+
next if symlinks[link]
|
55
|
+
|
56
|
+
source = File.realpath(link)
|
57
|
+
repo = File.join(@repo_dir, '/')
|
58
|
+
# maps absolute symlink path to relative source and link paths
|
59
|
+
symlinks[link] = {
|
60
|
+
'source' => source.gsub(repo, ''),
|
61
|
+
'link' => link.gsub(repo, ''),
|
62
|
+
}
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# Create the file hash expected for each file that is a link or coming
|
67
|
+
# from a linked directory but fake the source path as a symlink path.
|
68
|
+
# Hacky but works :)
|
69
|
+
links_to_append = []
|
70
|
+
symlinks.each_value do |lrp| # link_abs_path, link_relative_path
|
71
|
+
files.each do |f|
|
72
|
+
# a symlink will never have trailing '/', add one.
|
73
|
+
f[:path] += '/' if f[:path] == lrp['link']
|
74
|
+
|
75
|
+
# If a metadata file in the path of a symlink target directory has a
|
76
|
+
# deleted status, check if a metadata file exists in the symlink
|
77
|
+
# source directory. If so, mark it as modified to prevent deletion.
|
78
|
+
symlink_source_dir = File.join(@repo_dir, lrp['source'])
|
79
|
+
if (f[:path] == File.join(lrp['link'], 'metadata.rb') ||
|
80
|
+
f[:path] == File.join(lrp['link'], 'metadata.json')) &&
|
81
|
+
f[:status] == :deleted &&
|
82
|
+
(File.file?(File.join(symlink_source_dir, 'metadata.rb')) ||
|
83
|
+
File.file?(File.join(symlink_source_dir, 'metadata.json')))
|
84
|
+
f[:status] = :modified
|
85
|
+
end
|
86
|
+
|
87
|
+
next unless f[:path].start_with?(lrp['source'])
|
88
|
+
|
89
|
+
# This make a deep dup of the file hash
|
90
|
+
l = Marshal.load(Marshal.dump(f))
|
91
|
+
l[:path].gsub!(lrp['source'], lrp['link'])
|
92
|
+
links_to_append << l
|
93
|
+
end
|
94
|
+
end
|
95
|
+
links_to_append
|
96
|
+
end
|
97
|
+
|
46
98
|
def initialize(files, cookbook_dirs)
|
47
99
|
@files = files
|
48
|
-
@
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
# if metadata.rb is being deleted
|
100
|
+
@cookbook_dirs = cookbook_dirs
|
101
|
+
@name = self.class.explode_path(files.sample[:path])[:name]
|
102
|
+
# if metadata.(json|rb) is being deleted and we aren't also
|
103
|
+
# adding/modifying one of those two,
|
53
104
|
# cookbook is marked for deletion
|
54
105
|
# otherwise it was modified
|
55
106
|
# and will be re-uploaded
|
56
107
|
if files.
|
57
108
|
select { |x| x[:status] == :deleted }.
|
58
|
-
map
|
109
|
+
map do |x|
|
110
|
+
x[:path].match(
|
111
|
+
%{^(#{cookbook_dirs.join('|')})/[^/]+/metadata\.(rb|json)$},
|
112
|
+
)
|
113
|
+
end.
|
59
114
|
compact.
|
60
|
-
any?
|
115
|
+
any? &&
|
116
|
+
files.reject { |x| x[:status] == :deleted }.
|
117
|
+
map do |x|
|
118
|
+
x[:path].match(
|
119
|
+
%{^(#{cookbook_dirs.join('|')})/[^/]+/metadata\.(rb|json)$},
|
120
|
+
)
|
121
|
+
end.none?
|
61
122
|
@status = :deleted
|
62
123
|
else
|
63
124
|
@status = :modified
|
@@ -66,16 +127,22 @@ module BetweenMeals
|
|
66
127
|
|
67
128
|
# Given a list of changed files
|
68
129
|
# create a list of Cookbook objects
|
69
|
-
def self.find(list, cookbook_dirs, logger)
|
130
|
+
def self.find(list, cookbook_dirs, logger, repo, track_symlinks = false)
|
131
|
+
# rubocop:disable ClassVars
|
70
132
|
@@logger = logger
|
133
|
+
# rubocop:enable ClassVars
|
71
134
|
return [] if list.nil? || list.empty?
|
135
|
+
|
72
136
|
# rubocop:disable MultilineBlockChain
|
137
|
+
@repo_dir = File.realpath(repo.repo_path)
|
138
|
+
@cookbook_dirs = cookbook_dirs
|
139
|
+
list += map_symlinks(list) if track_symlinks
|
73
140
|
list.
|
74
141
|
group_by do |x|
|
75
142
|
# Group by prefix of cookbok_dir + cookbook_name
|
76
143
|
# so that we treat deletes and modifications across
|
77
144
|
# two locations separately
|
78
|
-
g = self.explode_path(x[:path]
|
145
|
+
g = self.explode_path(x[:path])
|
79
146
|
g[:cookbook_dir] + '/' + g[:name] if g
|
80
147
|
end.
|
81
148
|
map do |_, change|
|
@@ -83,10 +150,10 @@ module BetweenMeals
|
|
83
150
|
# Changes to OWNERS or other stuff that might end up
|
84
151
|
# in [core, other, secure] dirs are ignored
|
85
152
|
is_cookbook = change.select do |c|
|
86
|
-
self.meaningful_cookbook_file?(c[:path]
|
153
|
+
self.meaningful_cookbook_file?(c[:path])
|
87
154
|
end.any?
|
88
155
|
if is_cookbook
|
89
|
-
BetweenMeals::Changes::Cookbook.new(change, cookbook_dirs)
|
156
|
+
BetweenMeals::Changes::Cookbook.new(change, @cookbook_dirs)
|
90
157
|
end
|
91
158
|
end.compact
|
92
159
|
# rubocop:enable MultilineBlockChain
|
@@ -14,7 +14,6 @@
|
|
14
14
|
# See the License for the specific language governing permissions and
|
15
15
|
# limitations under the License.
|
16
16
|
|
17
|
-
# rubocop:disable ClassVars
|
18
17
|
module BetweenMeals
|
19
18
|
module Changes
|
20
19
|
# Changeset aware databag
|
@@ -37,8 +36,11 @@ module BetweenMeals
|
|
37
36
|
end
|
38
37
|
|
39
38
|
def self.find(list, databag_dir, logger)
|
39
|
+
# rubocop:disable ClassVars
|
40
40
|
@@logger = logger
|
41
|
+
# rubocop:enable ClassVars
|
41
42
|
return [] if list.nil? || list.empty?
|
43
|
+
|
42
44
|
list.
|
43
45
|
select { |x| self.name_from_path(x[:path], databag_dir) }.
|
44
46
|
map do |x|
|
@@ -14,13 +14,12 @@
|
|
14
14
|
# See the License for the specific language governing permissions and
|
15
15
|
# limitations under the License.
|
16
16
|
|
17
|
-
# rubocop:disable ClassVars
|
18
17
|
module BetweenMeals
|
19
18
|
module Changes
|
20
19
|
# Changeset aware role
|
21
20
|
class Role < Change
|
22
21
|
def self.name_from_path(path, role_dir)
|
23
|
-
re = %r{^#{role_dir}/(.+)\.rb}
|
22
|
+
re = %r{^#{role_dir}/(.+)\.(?:rb|json)}
|
24
23
|
debug("[role] Matching #{path} against #{re}")
|
25
24
|
m = path.match(re)
|
26
25
|
if m
|
@@ -38,8 +37,11 @@ module BetweenMeals
|
|
38
37
|
# Given a list of changed files
|
39
38
|
# create a list of Role objects
|
40
39
|
def self.find(list, role_dir, logger)
|
40
|
+
# rubocop:disable ClassVars
|
41
41
|
@@logger = logger
|
42
|
+
# rubocop:enable ClassVars
|
42
43
|
return [] if list.nil? || list.empty?
|
44
|
+
|
43
45
|
list.
|
44
46
|
select { |x| self.name_from_path(x[:path], role_dir) }.
|
45
47
|
map do |x|
|
@@ -27,15 +27,19 @@ module BetweenMeals
|
|
27
27
|
# Basically, you always want to use BetweenMeals::Changes through this
|
28
28
|
# helper class.
|
29
29
|
class Changeset
|
30
|
-
class ReferenceError <
|
30
|
+
class ReferenceError < RuntimeError
|
31
31
|
end
|
32
|
-
|
33
|
-
def initialize(
|
32
|
+
# rubocop:disable Metrics/ParameterLists
|
33
|
+
def initialize(
|
34
|
+
logger, repo, start_ref, end_ref, locations, track_symlinks = false
|
35
|
+
)
|
36
|
+
# rubocop:enable Metrics/ParameterLists
|
34
37
|
@logger = logger
|
35
38
|
@repo = repo
|
36
39
|
@cookbook_dirs = locations[:cookbook_dirs].dup
|
37
40
|
@role_dir = locations[:role_dir]
|
38
41
|
@databag_dir = locations[:databag_dir]
|
42
|
+
@track_symlinks = track_symlinks
|
39
43
|
# Figure out which files changed if refs provided
|
40
44
|
# or return all files (full upload) otherwise
|
41
45
|
if start_ref
|
@@ -49,7 +53,9 @@ module BetweenMeals
|
|
49
53
|
end
|
50
54
|
|
51
55
|
def cookbooks
|
52
|
-
BetweenMeals::Changes::Cookbook.find(
|
56
|
+
BetweenMeals::Changes::Cookbook.find(
|
57
|
+
@files, @cookbook_dirs, @logger, @repo, @track_symlinks
|
58
|
+
)
|
53
59
|
end
|
54
60
|
|
55
61
|
def roles
|
data/lib/between_meals/cmd.rb
CHANGED
@@ -27,17 +27,26 @@ module BetweenMeals
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def cmd(params, cwd = nil)
|
30
|
-
|
31
|
-
cwd = File.expand_path(@cwd)
|
32
|
-
end
|
30
|
+
cwd ||= File.expand_path(@cwd)
|
33
31
|
cmd = "#{@bin} #{params}"
|
34
32
|
@logger.info("Running \"#{cmd}\"")
|
35
33
|
c = Mixlib::ShellOut.new(
|
36
34
|
cmd,
|
37
|
-
:cwd => cwd
|
35
|
+
:cwd => cwd,
|
36
|
+
:env => {
|
37
|
+
# macOS needs /usr/local/bin as hg cannot be installed in /bin or
|
38
|
+
# /usr/bin
|
39
|
+
'PATH' => '/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin',
|
40
|
+
},
|
38
41
|
)
|
39
42
|
c.run_command
|
40
|
-
c.error
|
43
|
+
if c.error?
|
44
|
+
# Let's make sure the error goes to the logs
|
45
|
+
@logger.error("#{@bin} failed: #{c.format_for_exception}")
|
46
|
+
# if our logger is STDOUT, we'll double log when we throw
|
47
|
+
# the exception, but that's OK
|
48
|
+
c.error!
|
49
|
+
end
|
41
50
|
c
|
42
51
|
end
|
43
52
|
end
|
data/lib/between_meals/knife.rb
CHANGED
@@ -26,6 +26,8 @@ module BetweenMeals
|
|
26
26
|
class Knife
|
27
27
|
include BetweenMeals::Util
|
28
28
|
|
29
|
+
attr_accessor :cookbook_dirs
|
30
|
+
|
29
31
|
def initialize(opts = {})
|
30
32
|
@logger = opts[:logger] || nil
|
31
33
|
@user = opts[:user] || ENV['USER']
|
@@ -37,11 +39,20 @@ module BetweenMeals
|
|
37
39
|
@config = opts[:config] ||
|
38
40
|
"#{@home}/.chef/knife-#{@user}-taste-tester.rb"
|
39
41
|
@knife = opts[:bin] || 'knife'
|
42
|
+
@knife_verb_option = ''
|
43
|
+
unless @logger.nil?
|
44
|
+
if @logger.level == Logger::DEBUG
|
45
|
+
@knife_verb_option = '-VV'
|
46
|
+
elsif @logger.level == Logger::INFO
|
47
|
+
@knife_verb_option = '-V'
|
48
|
+
end
|
49
|
+
end
|
40
50
|
@berks = opts[:berks_bin] || 'berks'
|
41
51
|
@berks_config = opts[:berks_config]
|
42
52
|
@pem = opts[:pem] ||
|
43
53
|
"#{@home}/.chef/#{@user}-taste-tester.pem"
|
44
54
|
@role_dir = opts[:role_dir]
|
55
|
+
@role_type = opts[:role_type] || 'rb'
|
45
56
|
@cookbook_dirs = opts[:cookbook_dirs]
|
46
57
|
@databag_dir = opts[:databag_dir]
|
47
58
|
@checksum_dir = opts[:checksum_dir]
|
@@ -51,30 +62,34 @@ module BetweenMeals
|
|
51
62
|
|
52
63
|
def role_upload_all
|
53
64
|
if File.exists?(@role_dir)
|
54
|
-
roles = File.join(@role_dir,
|
55
|
-
exec!("#{@knife} role from file #{roles}
|
65
|
+
roles = File.join(@role_dir, "*.#{@role_type}")
|
66
|
+
exec!("#{@knife} role from file #{roles} #{@knife_verb_option} " +
|
67
|
+
"-c #{@config}", @logger)
|
56
68
|
end
|
57
69
|
end
|
58
70
|
|
59
71
|
def role_upload(roles)
|
60
72
|
if roles.any?
|
61
|
-
roles = roles.map
|
62
|
-
|
73
|
+
roles = roles.map do |x|
|
74
|
+
File.join(@role_dir, "#{x.name}.#{@role_type}")
|
75
|
+
end.join(' ')
|
76
|
+
exec!("#{@knife} role from file #{roles} #{@knife_verb_option} " +
|
77
|
+
"-c #{@config}", @logger)
|
63
78
|
end
|
64
79
|
end
|
65
80
|
|
66
81
|
def role_delete(roles)
|
67
82
|
if roles.any?
|
68
83
|
roles.each do |role|
|
69
|
-
exec!(
|
70
|
-
"
|
71
|
-
)
|
84
|
+
exec!("#{@knife} role delete #{role.name} #{@knife_verb_option} " +
|
85
|
+
"--yes -c #{@config}", @logger)
|
72
86
|
end
|
73
87
|
end
|
74
88
|
end
|
75
89
|
|
76
90
|
def cookbook_upload_all
|
77
|
-
exec!("#{@knife} cookbook upload -a
|
91
|
+
exec!("#{@knife} cookbook upload -a #{@knife_verb_option} " +
|
92
|
+
"-c #{@config}", @logger)
|
78
93
|
end
|
79
94
|
|
80
95
|
def berks_cookbook_upload_all
|
@@ -94,7 +109,8 @@ module BetweenMeals
|
|
94
109
|
def cookbook_upload(cookbooks)
|
95
110
|
if cookbooks.any?
|
96
111
|
cookbooks = cookbooks.map(&:name).join(' ')
|
97
|
-
exec!("#{@knife} cookbook upload #{cookbooks}
|
112
|
+
exec!("#{@knife} cookbook upload #{cookbooks} #{@knife_verb_option} " +
|
113
|
+
"-c #{@config}", @logger)
|
98
114
|
end
|
99
115
|
end
|
100
116
|
|
@@ -108,6 +124,7 @@ module BetweenMeals
|
|
108
124
|
@cookbook_dirs.each do |path|
|
109
125
|
cookbooks.each do |cb|
|
110
126
|
next unless File.exists?("#{path}/#{cb}")
|
127
|
+
|
111
128
|
@logger.warn("Running berkshelf on cookbook: #{cb}")
|
112
129
|
exec!("cd #{path}/#{cb} && #{@berks} install #{berks_config} && " +
|
113
130
|
"#{@berks} upload #{berks_config}", @logger)
|
@@ -120,7 +137,8 @@ module BetweenMeals
|
|
120
137
|
if cookbooks.any?
|
121
138
|
cookbooks.each do |cookbook|
|
122
139
|
exec!("#{@knife} cookbook delete #{cookbook.name}" +
|
123
|
-
" --purge -a --yes -c #{@config}",
|
140
|
+
" --purge -a --yes #{@knife_verb_option} -c #{@config}",
|
141
|
+
@logger)
|
124
142
|
end
|
125
143
|
end
|
126
144
|
end
|
@@ -143,8 +161,9 @@ module BetweenMeals
|
|
143
161
|
File.join(@databag_dir, dbname, "#{x.item}.json")
|
144
162
|
end.join(' ')
|
145
163
|
exec!(
|
146
|
-
"#{@knife} data bag from file #{dbname} #{dbitems}
|
147
|
-
@
|
164
|
+
"#{@knife} data bag from file #{dbname} #{dbitems} " +
|
165
|
+
"#{@knife_verb_option} -c #{@config}",
|
166
|
+
@logger,
|
148
167
|
)
|
149
168
|
end
|
150
169
|
end
|
@@ -155,7 +174,7 @@ module BetweenMeals
|
|
155
174
|
databags.group_by(&:name).each do |dbname, dbs|
|
156
175
|
dbs.each do |db|
|
157
176
|
exec!("#{@knife} data bag delete #{dbname} #{db.item}" +
|
158
|
-
" --yes -c #{@config}", @logger)
|
177
|
+
" --yes #{@knife_verb_option} -c #{@config}", @logger)
|
159
178
|
end
|
160
179
|
delete_databag_if_empty(dbname)
|
161
180
|
end
|
@@ -180,8 +199,11 @@ BLOCK
|
|
180
199
|
cfg << " \"#{dir}\",\n"
|
181
200
|
end
|
182
201
|
cfg << "]\n"
|
183
|
-
|
184
|
-
Dir.mkdir(File.dirname(@config),
|
202
|
+
begin
|
203
|
+
Dir.mkdir(File.dirname(@config), 0o755)
|
204
|
+
rescue Errno::EEXIST
|
205
|
+
# not an error if it's already there.
|
206
|
+
nil
|
185
207
|
end
|
186
208
|
if !File.exists?(@config) ||
|
187
209
|
::Digest::MD5.hexdigest(cfg) !=
|
@@ -220,7 +242,14 @@ zvgEHqbS0/QkJGOZ+UifPRanTDuGYQkPdHHOER4UghbM+Kz5rZbBicJ3bCyNOsah
|
|
220
242
|
IAMAEpsWX2s2A6phgMCx7kH6wMmoZn3hb7Thh9+PfR8Jtp2/7k+ibCeF4gEWUCs5
|
221
243
|
6wX4GR84dwyhG80yd4TP8Qo=
|
222
244
|
-----END PRIVATE KEY-----
|
223
|
-
|
245
|
+
BLOCK
|
246
|
+
|
247
|
+
begin
|
248
|
+
Dir.mkdir(File.dirname(@pem), 0o755)
|
249
|
+
rescue Errno::EEXIST
|
250
|
+
# not an error if it's already there.
|
251
|
+
nil
|
252
|
+
end
|
224
253
|
|
225
254
|
unless File.exists?(@pem)
|
226
255
|
@logger.info("Generating #{@pem}")
|
@@ -232,22 +261,25 @@ IAMAEpsWX2s2A6phgMCx7kH6wMmoZn3hb7Thh9+PfR8Jtp2/7k+ibCeF4gEWUCs5
|
|
232
261
|
|
233
262
|
def create_databag_if_missing(databag)
|
234
263
|
s = Mixlib::ShellOut.new("#{@knife} data bag list" +
|
235
|
-
" --format json
|
264
|
+
" --format json #{@knife_verb_option} " +
|
265
|
+
"-c #{@config}").run_command
|
236
266
|
s.error!
|
237
|
-
db = JSON.
|
267
|
+
db = JSON.parse(s.stdout)
|
238
268
|
unless db.include?(databag)
|
239
|
-
exec!("#{@knife} data bag create #{databag}
|
269
|
+
exec!("#{@knife} data bag create #{databag} #{@knife_verb_option} " +
|
270
|
+
"-c #{@config}", @logger)
|
240
271
|
end
|
241
272
|
end
|
242
273
|
|
243
274
|
def delete_databag_if_empty(databag)
|
244
275
|
s = Mixlib::ShellOut.new("#{@knife} data bag show #{databag}" +
|
245
|
-
" --format json
|
276
|
+
" --format json #{@knife_verb_option} " +
|
277
|
+
"-c #{@config}").run_command
|
246
278
|
s.error!
|
247
|
-
db = JSON.
|
279
|
+
db = JSON.parse(s.stdout)
|
248
280
|
if db.empty?
|
249
|
-
exec!("#{@knife} data bag delete #{databag} --yes
|
250
|
-
|
281
|
+
exec!("#{@knife} data bag delete #{databag} --yes " +
|
282
|
+
"#{@knife_verb_option} -c #{@config}", @logger)
|
251
283
|
end
|
252
284
|
end
|
253
285
|
end
|
data/lib/between_meals/repo.rb
CHANGED
@@ -27,7 +27,7 @@ module BetweenMeals
|
|
27
27
|
@repo = nil
|
28
28
|
@bin = nil
|
29
29
|
setup
|
30
|
-
rescue
|
30
|
+
rescue StandardError
|
31
31
|
@logger.warn("Unable to read repo from #{File.expand_path(repo_path)}")
|
32
32
|
exit(1)
|
33
33
|
end
|
@@ -54,7 +54,7 @@ module BetweenMeals
|
|
54
54
|
logger.info("Repo found to be #{klass.to_s.split('::').last}")
|
55
55
|
return r
|
56
56
|
end
|
57
|
-
rescue
|
57
|
+
rescue StandardError
|
58
58
|
logger.debug("Skipping #{klass}")
|
59
59
|
end
|
60
60
|
end
|
@@ -29,7 +29,7 @@ module BetweenMeals
|
|
29
29
|
if File.exists?(File.expand_path(@repo_path))
|
30
30
|
begin
|
31
31
|
@repo = Rugged::Repository.new(File.expand_path(@repo_path))
|
32
|
-
rescue
|
32
|
+
rescue StandardError
|
33
33
|
@repo = nil
|
34
34
|
end
|
35
35
|
else
|
@@ -60,7 +60,7 @@ module BetweenMeals
|
|
60
60
|
{
|
61
61
|
:message => msg,
|
62
62
|
:update_ref => 'HEAD',
|
63
|
-
}
|
63
|
+
},
|
64
64
|
)
|
65
65
|
end
|
66
66
|
|
@@ -86,10 +86,10 @@ module BetweenMeals
|
|
86
86
|
stdout = @cmd.diff(start_ref, end_ref).stdout
|
87
87
|
begin
|
88
88
|
parse_status(stdout).compact
|
89
|
-
rescue => e
|
89
|
+
rescue StandardError => e
|
90
90
|
# We've seen some weird non-reproducible failures here
|
91
91
|
@logger.error(
|
92
|
-
'Something went wrong. Please
|
92
|
+
'Something went wrong. Please report this output.',
|
93
93
|
)
|
94
94
|
@logger.error(e)
|
95
95
|
stdout.lines.each do |line|
|
@@ -112,8 +112,9 @@ module BetweenMeals
|
|
112
112
|
if @cmd.merge_base(rev, master).stdout.strip == rev
|
113
113
|
return true
|
114
114
|
end
|
115
|
+
|
115
116
|
return false
|
116
|
-
rescue
|
117
|
+
rescue StandardError
|
117
118
|
return false
|
118
119
|
end
|
119
120
|
|
@@ -153,62 +154,63 @@ module BetweenMeals
|
|
153
154
|
|
154
155
|
# rubocop:disable MultilineBlockChain
|
155
156
|
changes.lines.map do |line|
|
156
|
-
|
157
|
-
|
157
|
+
parts = line.chomp.split("\t")
|
158
|
+
case parts[0]
|
159
|
+
when 'A'
|
158
160
|
# A path
|
159
161
|
{
|
160
162
|
:status => :modified,
|
161
|
-
:path =>
|
163
|
+
:path => parts[1],
|
162
164
|
}
|
163
|
-
when /^C(?:\d*)
|
165
|
+
when /^C(?:\d*)/
|
164
166
|
# C<numbers> path1 path2
|
165
167
|
{
|
166
168
|
:status => :modified,
|
167
|
-
:path =>
|
169
|
+
:path => parts[2],
|
168
170
|
}
|
169
|
-
when
|
171
|
+
when 'D'
|
170
172
|
# D path
|
171
173
|
{
|
172
174
|
:status => :deleted,
|
173
|
-
:path =>
|
175
|
+
:path => parts[1],
|
174
176
|
}
|
175
|
-
when /^M(?:\d*)
|
177
|
+
when /^M(?:\d*)/
|
176
178
|
# M<numbers> path
|
177
179
|
{
|
178
180
|
:status => :modified,
|
179
|
-
:path =>
|
181
|
+
:path => parts[1],
|
180
182
|
}
|
181
|
-
when /^R(?:\d*)
|
183
|
+
when /^R(?:\d*)/
|
182
184
|
# R<numbers> path1 path2
|
183
185
|
[
|
184
186
|
{
|
185
187
|
:status => :deleted,
|
186
|
-
:path =>
|
188
|
+
:path => parts[1],
|
187
189
|
},
|
188
190
|
{
|
189
191
|
:status => :modified,
|
190
|
-
:path =>
|
191
|
-
}
|
192
|
+
:path => parts[2],
|
193
|
+
},
|
192
194
|
]
|
193
|
-
when
|
195
|
+
when 'T'
|
194
196
|
# T path
|
195
197
|
[
|
196
198
|
{
|
197
199
|
:status => :deleted,
|
198
|
-
:path =>
|
200
|
+
:path => parts[1],
|
199
201
|
},
|
200
202
|
{
|
201
203
|
:status => :modified,
|
202
|
-
:path =>
|
203
|
-
}
|
204
|
+
:path => parts[1],
|
205
|
+
},
|
204
206
|
]
|
205
207
|
else
|
206
|
-
fail '
|
208
|
+
fail 'Failed to parse repo diff line.'
|
207
209
|
end
|
208
210
|
end.flatten.map do |x|
|
209
211
|
{
|
210
212
|
:status => x[:status],
|
211
|
-
:path => x[:path].sub("#{@repo_path}/", '')
|
213
|
+
:path => x[:path].sub("#{@repo_path}/", ''),
|
212
214
|
}
|
213
215
|
end
|
214
216
|
# rubocop:enable MultilineBlockChain
|
@@ -50,10 +50,10 @@ module BetweenMeals
|
|
50
50
|
stdout = @cmd.status(start_ref, end_ref).stdout
|
51
51
|
begin
|
52
52
|
parse_status(stdout).compact
|
53
|
-
rescue => e
|
53
|
+
rescue StandardError => e
|
54
54
|
# We've seen some weird non-reproducible failures here
|
55
55
|
@logger.error(
|
56
|
-
'Something went wrong. Please
|
56
|
+
'Something went wrong. Please report this output.',
|
57
57
|
)
|
58
58
|
@logger.error(e)
|
59
59
|
stdout.lines.each do |line|
|
@@ -65,9 +65,9 @@ module BetweenMeals
|
|
65
65
|
|
66
66
|
def update
|
67
67
|
@cmd.pull.stdout
|
68
|
-
rescue
|
68
|
+
rescue StandardError => e
|
69
69
|
@logger.error('Something went wrong with hg!')
|
70
|
-
@logger.error(
|
70
|
+
@logger.error(e)
|
71
71
|
raise
|
72
72
|
end
|
73
73
|
|
@@ -83,7 +83,7 @@ module BetweenMeals
|
|
83
83
|
:time => Time.parse(@cmd.log('date|isodate', 'master').stdout),
|
84
84
|
:rev => @cmd.log('node', 'master').stdout,
|
85
85
|
}]
|
86
|
-
rescue
|
86
|
+
rescue StandardError
|
87
87
|
[{
|
88
88
|
:time => nil,
|
89
89
|
:rev => nil,
|
@@ -103,7 +103,7 @@ module BetweenMeals
|
|
103
103
|
|
104
104
|
def last_msg
|
105
105
|
@cmd.log('desc').stdout
|
106
|
-
rescue
|
106
|
+
rescue StandardError
|
107
107
|
nil
|
108
108
|
end
|
109
109
|
|
@@ -115,13 +115,13 @@ module BetweenMeals
|
|
115
115
|
|
116
116
|
def email
|
117
117
|
username[2]
|
118
|
-
rescue
|
118
|
+
rescue StandardError
|
119
119
|
nil
|
120
120
|
end
|
121
121
|
|
122
122
|
def name
|
123
123
|
username[1]
|
124
|
-
rescue
|
124
|
+
rescue StandardError
|
125
125
|
nil
|
126
126
|
end
|
127
127
|
|
@@ -143,7 +143,7 @@ module BetweenMeals
|
|
143
143
|
def valid_ref?(ref)
|
144
144
|
@cmd.rev(ref)
|
145
145
|
return true
|
146
|
-
rescue
|
146
|
+
rescue StandardError
|
147
147
|
raise Changeset::ReferenceError
|
148
148
|
end
|
149
149
|
|
@@ -165,49 +165,48 @@ module BetweenMeals
|
|
165
165
|
# I = ignored
|
166
166
|
# = origin of the previous file (with --copies)
|
167
167
|
|
168
|
-
# rubocop:disable MultilineBlockChain
|
169
168
|
changes.lines.map do |line|
|
170
|
-
|
171
|
-
|
169
|
+
parts = line.chomp.split(nil, 2)
|
170
|
+
case parts[0]
|
171
|
+
when 'A'
|
172
172
|
{
|
173
173
|
:status => :added,
|
174
|
-
:path =>
|
174
|
+
:path => parts[1],
|
175
175
|
}
|
176
|
-
when
|
176
|
+
when 'C'
|
177
177
|
{
|
178
178
|
:status => :clean,
|
179
|
-
:path =>
|
179
|
+
:path => parts[1],
|
180
180
|
}
|
181
|
-
when
|
181
|
+
when 'R'
|
182
182
|
{
|
183
183
|
:status => :deleted,
|
184
|
-
:path =>
|
184
|
+
:path => parts[1],
|
185
185
|
}
|
186
|
-
when
|
186
|
+
when 'M'
|
187
187
|
{
|
188
188
|
:status => :modified,
|
189
|
-
:path =>
|
189
|
+
:path => parts[1],
|
190
190
|
}
|
191
|
-
when
|
191
|
+
when '!'
|
192
192
|
{
|
193
193
|
:status => :missing,
|
194
|
-
:path =>
|
194
|
+
:path => parts[1],
|
195
195
|
}
|
196
|
-
when
|
196
|
+
when '?'
|
197
197
|
{
|
198
198
|
:status => :untracked,
|
199
|
-
:path =>
|
199
|
+
:path => parts[1],
|
200
200
|
}
|
201
|
-
when
|
201
|
+
when 'I'
|
202
202
|
{
|
203
203
|
:status => :ignored,
|
204
|
-
:path =>
|
204
|
+
:path => parts[1],
|
205
205
|
}
|
206
206
|
else
|
207
|
-
fail '
|
207
|
+
fail 'Failed to parse repo diff line.'
|
208
208
|
end
|
209
209
|
end
|
210
|
-
# rubocop:enable MultilineBlockChain
|
211
210
|
end
|
212
211
|
end
|
213
212
|
end
|
@@ -64,9 +64,9 @@ module BetweenMeals
|
|
64
64
|
|
65
65
|
begin
|
66
66
|
parse_status(changes).compact
|
67
|
-
rescue => e
|
67
|
+
rescue StandardError => e
|
68
68
|
@logger.error(
|
69
|
-
'Something went wrong. Please
|
69
|
+
'Something went wrong. Please report this output.',
|
70
70
|
)
|
71
71
|
@logger.error(e)
|
72
72
|
stdout.lines.each do |line|
|
@@ -88,12 +88,11 @@ module BetweenMeals
|
|
88
88
|
end
|
89
89
|
end
|
90
90
|
|
91
|
-
def upstream
|
92
|
-
end
|
91
|
+
def upstream?; end
|
93
92
|
|
94
93
|
def valid_ref?(ref)
|
95
94
|
@cmd.info_r(ref, @repo_path)
|
96
|
-
rescue
|
95
|
+
rescue StandardError
|
97
96
|
raise Changeset::ReferenceError
|
98
97
|
end
|
99
98
|
|
@@ -103,13 +102,13 @@ module BetweenMeals
|
|
103
102
|
# http://svnbook.red-bean.com/en/1.0/re26.html
|
104
103
|
changes.lines.map do |line|
|
105
104
|
case line
|
106
|
-
when
|
105
|
+
when /^([\w ])\w?\s+(.+)$/
|
107
106
|
{
|
108
107
|
:status => Regexp.last_match(1) == 'D' ? :deleted : :modified,
|
109
108
|
:path => Regexp.last_match(2).sub("#{@repo_path}/", ''),
|
110
109
|
}
|
111
110
|
else
|
112
|
-
fail '
|
111
|
+
fail 'Failed to parse repo diff line.'
|
113
112
|
end
|
114
113
|
end
|
115
114
|
end
|
data/lib/between_meals/util.rb
CHANGED
@@ -15,13 +15,15 @@
|
|
15
15
|
# limitations under the License.
|
16
16
|
|
17
17
|
require 'colorize'
|
18
|
+
require 'net/http'
|
19
|
+
require 'openssl'
|
18
20
|
require 'socket'
|
19
21
|
require 'timeout'
|
20
22
|
|
21
23
|
module BetweenMeals
|
22
24
|
# A set of simple utility functions used throughout BetweenMeals
|
23
25
|
#
|
24
|
-
# Feel
|
26
|
+
# Feel free to use... note that if you pass in a logger once
|
25
27
|
# you don't need to again, but be safe and always pass one in. :)
|
26
28
|
|
27
29
|
# Util classes need class vars :)
|
@@ -36,28 +38,29 @@ module BetweenMeals
|
|
36
38
|
info("Executed in #{format('%.2f', Time.now - t0)}s")
|
37
39
|
end
|
38
40
|
|
39
|
-
def exec!(command, logger = nil)
|
41
|
+
def exec!(command, logger = nil, stream = nil)
|
40
42
|
@@logger = logger if logger
|
41
|
-
c = execute(command)
|
43
|
+
c = execute(command, stream)
|
42
44
|
c.error!
|
43
45
|
return c.status.exitstatus, c.stdout
|
44
46
|
end
|
45
47
|
|
46
|
-
def exec(command, logger = nil)
|
48
|
+
def exec(command, logger = nil, stream = nil)
|
47
49
|
@@logger = logger if logger
|
48
|
-
|
50
|
+
|
51
|
+
c = execute(command, stream)
|
49
52
|
return c.status.exitstatus, c.stdout
|
50
53
|
end
|
51
54
|
|
52
55
|
private
|
53
56
|
|
54
57
|
def info(msg)
|
55
|
-
@@logger
|
58
|
+
@@logger&.info(msg)
|
56
59
|
end
|
57
60
|
|
58
|
-
def execute(command)
|
61
|
+
def execute(command, stream)
|
59
62
|
info("Running: #{command}")
|
60
|
-
c = Mixlib::ShellOut.new(command)
|
63
|
+
c = Mixlib::ShellOut.new(command, :live_stream => stream)
|
61
64
|
c.run_command
|
62
65
|
c.stdout.lines.each do |line|
|
63
66
|
info("STDOUT: #{line.strip}")
|
@@ -69,20 +72,43 @@ module BetweenMeals
|
|
69
72
|
end
|
70
73
|
|
71
74
|
def port_open?(port)
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
75
|
+
ips = Socket.ip_address_list
|
76
|
+
ips.map!(&:ip_address)
|
77
|
+
ips.each do |ip|
|
78
|
+
begin
|
79
|
+
Timeout.timeout(1) do
|
80
|
+
begin
|
81
|
+
s = TCPSocket.new(ip, port)
|
82
|
+
s.close
|
83
|
+
return true
|
84
|
+
rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH
|
85
|
+
next
|
86
|
+
end
|
87
|
+
end
|
88
|
+
rescue Timeout::Error
|
89
|
+
next
|
90
|
+
end
|
91
|
+
end
|
92
|
+
return false
|
93
|
+
end
|
94
|
+
|
95
|
+
def chef_zero_running?(port, use_ssl)
|
96
|
+
Timeout.timeout(1) do
|
97
|
+
begin
|
98
|
+
http = Net::HTTP.new('localhost', port)
|
99
|
+
if use_ssl
|
100
|
+
http.use_ssl = true
|
101
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
80
102
|
end
|
103
|
+
res = http.get('/')
|
104
|
+
return res['Server'] == 'chef-zero'
|
105
|
+
rescue StandardError
|
106
|
+
return false
|
81
107
|
end
|
82
|
-
rescue Timeout::Error
|
83
|
-
return false
|
84
108
|
end
|
109
|
+
rescue Timeout::Error
|
85
110
|
return false
|
86
111
|
end
|
87
112
|
end
|
88
113
|
end
|
114
|
+
# rubocop:enable ClassVars
|
metadata
CHANGED
@@ -1,208 +1,175 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: between_meals
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
prerelease:
|
6
|
-
segments:
|
7
|
-
- 0
|
8
|
-
- 0
|
9
|
-
- 6
|
10
|
-
version: 0.0.6
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.11
|
11
5
|
platform: ruby
|
12
|
-
authors:
|
6
|
+
authors:
|
13
7
|
- Phil Dibowitz
|
14
8
|
- Marcin Sawicki
|
15
9
|
autorequire:
|
16
10
|
bindir: bin
|
17
11
|
cert_chain: []
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
- !ruby/object:Gem::Dependency
|
12
|
+
date: 2020-05-28 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
22
15
|
name: colorize
|
23
|
-
|
24
|
-
|
25
|
-
none: false
|
26
|
-
requirements:
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
27
18
|
- - ">="
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
|
30
|
-
segments:
|
31
|
-
- 0
|
32
|
-
version: "0"
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '0'
|
33
21
|
type: :runtime
|
34
|
-
version_requirements: *id001
|
35
|
-
- !ruby/object:Gem::Dependency
|
36
|
-
name: json
|
37
22
|
prerelease: false
|
38
|
-
|
39
|
-
|
40
|
-
requirements:
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
41
25
|
- - ">="
|
42
|
-
- !ruby/object:Gem::Version
|
43
|
-
|
44
|
-
|
45
|
-
- 0
|
46
|
-
version: "0"
|
47
|
-
type: :runtime
|
48
|
-
version_requirements: *id002
|
49
|
-
- !ruby/object:Gem::Dependency
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '0'
|
28
|
+
- !ruby/object:Gem::Dependency
|
50
29
|
name: mixlib-shellout
|
51
|
-
|
52
|
-
|
53
|
-
none: false
|
54
|
-
requirements:
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
55
32
|
- - ">="
|
56
|
-
- !ruby/object:Gem::Version
|
57
|
-
|
58
|
-
segments:
|
59
|
-
- 0
|
60
|
-
version: "0"
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '0'
|
61
35
|
type: :runtime
|
62
|
-
version_requirements: *id003
|
63
|
-
- !ruby/object:Gem::Dependency
|
64
|
-
name: rugged
|
65
36
|
prerelease: false
|
66
|
-
|
67
|
-
|
68
|
-
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: rugged
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
69
46
|
- - ">="
|
70
|
-
- !ruby/object:Gem::Version
|
71
|
-
|
72
|
-
segments:
|
73
|
-
- 0
|
74
|
-
version: "0"
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
75
49
|
type: :runtime
|
76
|
-
version_requirements: *id004
|
77
|
-
- !ruby/object:Gem::Dependency
|
78
|
-
name: rspec-core
|
79
50
|
prerelease: false
|
80
|
-
|
81
|
-
|
82
|
-
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: rspec-core
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
83
60
|
- - ">="
|
84
|
-
- !ruby/object:Gem::Version
|
85
|
-
|
86
|
-
segments:
|
87
|
-
- 0
|
88
|
-
version: "0"
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0'
|
89
63
|
type: :development
|
90
|
-
version_requirements: *id005
|
91
|
-
- !ruby/object:Gem::Dependency
|
92
|
-
name: rspec-expectations
|
93
64
|
prerelease: false
|
94
|
-
|
95
|
-
|
96
|
-
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: rspec-expectations
|
72
|
+
requirement: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
97
74
|
- - ">="
|
98
|
-
- !ruby/object:Gem::Version
|
99
|
-
|
100
|
-
segments:
|
101
|
-
- 0
|
102
|
-
version: "0"
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
103
77
|
type: :development
|
104
|
-
version_requirements: *id006
|
105
|
-
- !ruby/object:Gem::Dependency
|
106
|
-
name: rspec-mocks
|
107
78
|
prerelease: false
|
108
|
-
|
109
|
-
|
110
|
-
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - ">="
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '0'
|
84
|
+
- !ruby/object:Gem::Dependency
|
85
|
+
name: rspec-mocks
|
86
|
+
requirement: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
111
88
|
- - ">="
|
112
|
-
- !ruby/object:Gem::Version
|
113
|
-
|
114
|
-
segments:
|
115
|
-
- 0
|
116
|
-
version: "0"
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '0'
|
117
91
|
type: :development
|
118
|
-
version_requirements: *id007
|
119
|
-
- !ruby/object:Gem::Dependency
|
120
|
-
name: rubocop
|
121
92
|
prerelease: false
|
122
|
-
|
123
|
-
|
124
|
-
requirements:
|
93
|
+
version_requirements: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
125
95
|
- - ">="
|
126
|
-
- !ruby/object:Gem::Version
|
127
|
-
|
128
|
-
|
129
|
-
- 0
|
130
|
-
version: "0"
|
131
|
-
type: :development
|
132
|
-
version_requirements: *id008
|
133
|
-
- !ruby/object:Gem::Dependency
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '0'
|
98
|
+
- !ruby/object:Gem::Dependency
|
134
99
|
name: simplecov
|
100
|
+
requirement: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
102
|
+
- - ">="
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: '0'
|
105
|
+
type: :development
|
135
106
|
prerelease: false
|
136
|
-
|
137
|
-
|
138
|
-
requirements:
|
107
|
+
version_requirements: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
139
109
|
- - ">="
|
140
|
-
- !ruby/object:Gem::Version
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '0'
|
112
|
+
- !ruby/object:Gem::Dependency
|
113
|
+
name: rubocop
|
114
|
+
requirement: !ruby/object:Gem::Requirement
|
115
|
+
requirements:
|
116
|
+
- - '='
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
version: 0.49.1
|
145
119
|
type: :development
|
146
|
-
|
120
|
+
prerelease: false
|
121
|
+
version_requirements: !ruby/object:Gem::Requirement
|
122
|
+
requirements:
|
123
|
+
- - '='
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: 0.49.1
|
147
126
|
description: Library for calculation Chef differences between revisions
|
148
127
|
email:
|
149
128
|
executables: []
|
150
|
-
|
151
129
|
extensions: []
|
152
|
-
|
153
|
-
extra_rdoc_files:
|
130
|
+
extra_rdoc_files:
|
154
131
|
- README.md
|
155
132
|
- LICENSE
|
156
|
-
files:
|
157
|
-
- README.md
|
133
|
+
files:
|
158
134
|
- LICENSE
|
159
|
-
-
|
160
|
-
- lib/between_meals/cmd.rb
|
161
|
-
- lib/between_meals/util.rb
|
162
|
-
- lib/between_meals/repo.rb
|
163
|
-
- lib/between_meals/changeset.rb
|
135
|
+
- README.md
|
164
136
|
- lib/between_meals/changes/change.rb
|
165
|
-
- lib/between_meals/changes/role.rb
|
166
137
|
- lib/between_meals/changes/cookbook.rb
|
167
138
|
- lib/between_meals/changes/databag.rb
|
168
|
-
- lib/between_meals/
|
169
|
-
- lib/between_meals/
|
170
|
-
- lib/between_meals/
|
171
|
-
- lib/between_meals/
|
139
|
+
- lib/between_meals/changes/role.rb
|
140
|
+
- lib/between_meals/changeset.rb
|
141
|
+
- lib/between_meals/cmd.rb
|
142
|
+
- lib/between_meals/knife.rb
|
143
|
+
- lib/between_meals/repo.rb
|
172
144
|
- lib/between_meals/repo/git.rb
|
145
|
+
- lib/between_meals/repo/git/cmd.rb
|
173
146
|
- lib/between_meals/repo/hg.rb
|
147
|
+
- lib/between_meals/repo/hg/cmd.rb
|
148
|
+
- lib/between_meals/repo/svn.rb
|
149
|
+
- lib/between_meals/repo/svn/cmd.rb
|
150
|
+
- lib/between_meals/util.rb
|
174
151
|
homepage: https://github.com/facebook/between-meals
|
175
|
-
licenses:
|
176
|
-
- Apache
|
152
|
+
licenses:
|
153
|
+
- Apache-2.0
|
154
|
+
metadata: {}
|
177
155
|
post_install_message:
|
178
156
|
rdoc_options: []
|
179
|
-
|
180
|
-
require_paths:
|
157
|
+
require_paths:
|
181
158
|
- lib
|
182
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
183
|
-
|
184
|
-
requirements:
|
159
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
160
|
+
requirements:
|
185
161
|
- - ">="
|
186
|
-
- !ruby/object:Gem::Version
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
version: "0"
|
191
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
192
|
-
none: false
|
193
|
-
requirements:
|
162
|
+
- !ruby/object:Gem::Version
|
163
|
+
version: '0'
|
164
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
165
|
+
requirements:
|
194
166
|
- - ">="
|
195
|
-
- !ruby/object:Gem::Version
|
196
|
-
|
197
|
-
segments:
|
198
|
-
- 0
|
199
|
-
version: "0"
|
167
|
+
- !ruby/object:Gem::Version
|
168
|
+
version: '0'
|
200
169
|
requirements: []
|
201
|
-
|
202
170
|
rubyforge_project:
|
203
|
-
rubygems_version:
|
171
|
+
rubygems_version: 2.7.6.2
|
204
172
|
signing_key:
|
205
|
-
specification_version:
|
173
|
+
specification_version: 4
|
206
174
|
summary: Between Meals
|
207
175
|
test_files: []
|
208
|
-
|