between_meals 0.0.7 → 0.0.12

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 5952ca7e5fa6d2486432f7a3c6680e01829056e0
4
- data.tar.gz: e1a35decf62bb0cc2fbb7bda9e449754184f50cd
2
+ SHA256:
3
+ metadata.gz: 21f7e5e4186f163af47afb9a74c9f877d12949c3a637232747eb1fbfd1e9b845
4
+ data.tar.gz: 3e5e53f85e47ae60291c05c83e244e4d3414e4984443b9471ef4711aad36e937
5
5
  SHA512:
6
- metadata.gz: 5b179124ee7a2330a15e52c87784ad975f1110954cfefc61ad351dc125b57740604eb8197b2ec3320ee3c237ff1ae6bb79471b678a03fd5e4693837289ffaca3
7
- data.tar.gz: fa1efa5aaa80231f1b9b2dab50427e608ea3a4bd6e1c910d36ab61ffa33928076b2f841e5aa1d8a4a93e00aaa19b8bd4a0545dccb0db4e1d0648090bc93e0b15
6
+ metadata.gz: 0ae9b2b8ad9a02e11dbbbce04bd8fb9e240f2c9af5ae4aa6bd709cc8a18e5453705d3bb41729ac4dd699c016aebbd658b62f0021779af47202c54882554d3d25
7
+ data.tar.gz: 138c9464b07cd6f797ac41fcb91bd360db357db3ca26a2ccca12b21f0d8afbabd99919e41129ae40a2f2b75e4ac1749822eeb291d126eb44172c42d39b109663
data/README.md CHANGED
@@ -1,13 +1,13 @@
1
1
  # Between Meals
2
2
 
3
- [![Build Status](https://travis-ci.org/facebook/between-meals.svg)](http://travis-ci.org/facebook/between-meals)
3
+ ![Continuous Integration](https://github.com/facebook/between-meals/workflows/Continuous%20Integration/badge.svg?event=push)
4
4
 
5
5
  ## Intro
6
6
  Ohai!
7
7
 
8
- Between Meals is the library for calculating what Chef objects where modified
8
+ Between Meals is the library for calculating what Chef objects were modified
9
9
  between two revisions in a version control system. It is also the library
10
- that that backs Taste Tester and Grocery Delivery.
10
+ that backs Taste Tester and Grocery Delivery.
11
11
 
12
12
  It currently supports SVN, GIT and HG, but plugins can easily be written for
13
13
  other source control systems.
@@ -18,7 +18,9 @@ functions.
18
18
  ## Dependencies
19
19
 
20
20
  * Colorize
21
- * JSON
22
21
  * Mixlib::ShellOut
23
22
  * Rugged
24
23
 
24
+ ## License
25
+
26
+ 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
- if @@logger
41
- @@logger.info(msg)
42
- end
40
+ @@logger&.info(msg)
43
41
  end
44
42
 
45
43
  def self.debug(msg)
46
- if @@logger
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,27 +14,21 @@
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, cookbook_dirs)
23
- cookbook_dirs.each do |dir|
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, cookbook_dirs)
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,
@@ -44,21 +38,87 @@ module BetweenMeals
44
38
  nil
45
39
  end
46
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
+
47
98
  def initialize(files, cookbook_dirs)
48
99
  @files = files
49
- @name = self.class.explode_path(
50
- files.sample[:path],
51
- cookbook_dirs,
52
- )[:name]
53
- # 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,
54
104
  # cookbook is marked for deletion
55
105
  # otherwise it was modified
56
106
  # and will be re-uploaded
57
107
  if files.
58
108
  select { |x| x[:status] == :deleted }.
59
- map { |x| x[:path].match(%{.*metadata\.rb$}) }.
109
+ map do |x|
110
+ x[:path].match(
111
+ %{^(#{cookbook_dirs.join('|')})/[^/]+/metadata\.(rb|json)$},
112
+ )
113
+ end.
60
114
  compact.
61
- 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?
62
122
  @status = :deleted
63
123
  else
64
124
  @status = :modified
@@ -67,16 +127,22 @@ module BetweenMeals
67
127
 
68
128
  # Given a list of changed files
69
129
  # create a list of Cookbook objects
70
- def self.find(list, cookbook_dirs, logger)
130
+ def self.find(list, cookbook_dirs, logger, repo, track_symlinks = false)
131
+ # rubocop:disable ClassVars
71
132
  @@logger = logger
133
+ # rubocop:enable ClassVars
72
134
  return [] if list.nil? || list.empty?
135
+
73
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
74
140
  list.
75
141
  group_by do |x|
76
142
  # Group by prefix of cookbok_dir + cookbook_name
77
143
  # so that we treat deletes and modifications across
78
144
  # two locations separately
79
- g = self.explode_path(x[:path], cookbook_dirs)
145
+ g = self.explode_path(x[:path])
80
146
  g[:cookbook_dir] + '/' + g[:name] if g
81
147
  end.
82
148
  map do |_, change|
@@ -84,10 +150,10 @@ module BetweenMeals
84
150
  # Changes to OWNERS or other stuff that might end up
85
151
  # in [core, other, secure] dirs are ignored
86
152
  is_cookbook = change.select do |c|
87
- self.meaningful_cookbook_file?(c[:path], cookbook_dirs)
153
+ self.meaningful_cookbook_file?(c[:path])
88
154
  end.any?
89
155
  if is_cookbook
90
- BetweenMeals::Changes::Cookbook.new(change, cookbook_dirs)
156
+ BetweenMeals::Changes::Cookbook.new(change, @cookbook_dirs)
91
157
  end
92
158
  end.compact
93
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,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 role
@@ -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|
@@ -29,13 +29,17 @@ module BetweenMeals
29
29
  class Changeset
30
30
  class ReferenceError < RuntimeError
31
31
  end
32
-
33
- def initialize(logger, repo, start_ref, end_ref, locations)
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(@files, @cookbook_dirs, @logger)
56
+ BetweenMeals::Changes::Cookbook.find(
57
+ @files, @cookbook_dirs, @logger, @repo, @track_symlinks
58
+ )
53
59
  end
54
60
 
55
61
  def roles
@@ -26,18 +26,28 @@ module BetweenMeals
26
26
  @logger = params[:logger] || Logger.new(STDOUT)
27
27
  end
28
28
 
29
- def cmd(params, cwd = nil)
30
- unless cwd
31
- cwd = File.expand_path(@cwd)
32
- end
29
+ def cmd(params, cwd = nil, nofail = false)
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
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 the user asked us not to fail, let them handle error reporting
44
+ if c.error? && !nofail
45
+ # Let's make sure the error goes to the logs
46
+ @logger.error("#{@bin} failed: #{c.format_for_exception}")
47
+ # if our logger is STDOUT, we'll double log when we throw
48
+ # the exception, but that's OK
49
+ c.error!
50
+ end
41
51
  c
42
52
  end
43
53
  end
@@ -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,6 +39,14 @@ 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] ||
@@ -51,9 +61,10 @@ module BetweenMeals
51
61
  end
52
62
 
53
63
  def role_upload_all
54
- if File.exists?(@role_dir)
64
+ if File.exist?(@role_dir)
55
65
  roles = File.join(@role_dir, "*.#{@role_type}")
56
- exec!("#{@knife} role from file #{roles} -c #{@config}", @logger)
66
+ exec!("#{@knife} role from file #{roles} #{@knife_verb_option} " +
67
+ "-c #{@config}", @logger)
57
68
  end
58
69
  end
59
70
 
@@ -62,22 +73,23 @@ module BetweenMeals
62
73
  roles = roles.map do |x|
63
74
  File.join(@role_dir, "#{x.name}.#{@role_type}")
64
75
  end.join(' ')
65
- exec!("#{@knife} role from file #{roles} -c #{@config}", @logger)
76
+ exec!("#{@knife} role from file #{roles} #{@knife_verb_option} " +
77
+ "-c #{@config}", @logger)
66
78
  end
67
79
  end
68
80
 
69
81
  def role_delete(roles)
70
82
  if roles.any?
71
83
  roles.each do |role|
72
- exec!(
73
- "#{@knife} role delete #{role.name} --yes -c #{@config}", @logger
74
- )
84
+ exec!("#{@knife} role delete #{role.name} #{@knife_verb_option} " +
85
+ "--yes -c #{@config}", @logger)
75
86
  end
76
87
  end
77
88
  end
78
89
 
79
90
  def cookbook_upload_all
80
- exec!("#{@knife} cookbook upload -a -c #{@config}", @logger)
91
+ exec!("#{@knife} cookbook upload -a #{@knife_verb_option} " +
92
+ "-c #{@config}", @logger)
81
93
  end
82
94
 
83
95
  def berks_cookbook_upload_all
@@ -97,7 +109,8 @@ module BetweenMeals
97
109
  def cookbook_upload(cookbooks)
98
110
  if cookbooks.any?
99
111
  cookbooks = cookbooks.map(&:name).join(' ')
100
- exec!("#{@knife} cookbook upload #{cookbooks} -c #{@config}", @logger)
112
+ exec!("#{@knife} cookbook upload #{cookbooks} #{@knife_verb_option} " +
113
+ "-c #{@config}", @logger)
101
114
  end
102
115
  end
103
116
 
@@ -110,7 +123,8 @@ module BetweenMeals
110
123
  if cookbooks.any?
111
124
  @cookbook_dirs.each do |path|
112
125
  cookbooks.each do |cb|
113
- next unless File.exists?("#{path}/#{cb}")
126
+ next unless File.exist?("#{path}/#{cb}")
127
+
114
128
  @logger.warn("Running berkshelf on cookbook: #{cb}")
115
129
  exec!("cd #{path}/#{cb} && #{@berks} install #{berks_config} && " +
116
130
  "#{@berks} upload #{berks_config}", @logger)
@@ -123,7 +137,8 @@ module BetweenMeals
123
137
  if cookbooks.any?
124
138
  cookbooks.each do |cookbook|
125
139
  exec!("#{@knife} cookbook delete #{cookbook.name}" +
126
- " --purge -a --yes -c #{@config}", @logger)
140
+ " --purge -a --yes #{@knife_verb_option} -c #{@config}",
141
+ @logger)
127
142
  end
128
143
  end
129
144
  end
@@ -146,7 +161,8 @@ module BetweenMeals
146
161
  File.join(@databag_dir, dbname, "#{x.item}.json")
147
162
  end.join(' ')
148
163
  exec!(
149
- "#{@knife} data bag from file #{dbname} #{dbitems} -c #{@config}",
164
+ "#{@knife} data bag from file #{dbname} #{dbitems} " +
165
+ "#{@knife_verb_option} -c #{@config}",
150
166
  @logger,
151
167
  )
152
168
  end
@@ -158,7 +174,7 @@ module BetweenMeals
158
174
  databags.group_by(&:name).each do |dbname, dbs|
159
175
  dbs.each do |db|
160
176
  exec!("#{@knife} data bag delete #{dbname} #{db.item}" +
161
- " --yes -c #{@config}", @logger)
177
+ " --yes #{@knife_verb_option} -c #{@config}", @logger)
162
178
  end
163
179
  delete_databag_if_empty(dbname)
164
180
  end
@@ -183,10 +199,13 @@ BLOCK
183
199
  cfg << " \"#{dir}\",\n"
184
200
  end
185
201
  cfg << "]\n"
186
- unless File.directory?(File.dirname(@config))
202
+ begin
187
203
  Dir.mkdir(File.dirname(@config), 0o755)
204
+ rescue Errno::EEXIST
205
+ # not an error if it's already there.
206
+ nil
188
207
  end
189
- if !File.exists?(@config) ||
208
+ if !File.exist?(@config) ||
190
209
  ::Digest::MD5.hexdigest(cfg) !=
191
210
  ::Digest::MD5.hexdigest(File.read(@config))
192
211
  @logger.info("Generating #{@config}")
@@ -223,9 +242,16 @@ zvgEHqbS0/QkJGOZ+UifPRanTDuGYQkPdHHOER4UghbM+Kz5rZbBicJ3bCyNOsah
223
242
  IAMAEpsWX2s2A6phgMCx7kH6wMmoZn3hb7Thh9+PfR8Jtp2/7k+ibCeF4gEWUCs5
224
243
  6wX4GR84dwyhG80yd4TP8Qo=
225
244
  -----END PRIVATE KEY-----
226
- BLOCK
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
227
253
 
228
- unless File.exists?(@pem)
254
+ unless File.exist?(@pem)
229
255
  @logger.info("Generating #{@pem}")
230
256
  File.write(@pem, pem)
231
257
  end
@@ -235,22 +261,25 @@ IAMAEpsWX2s2A6phgMCx7kH6wMmoZn3hb7Thh9+PfR8Jtp2/7k+ibCeF4gEWUCs5
235
261
 
236
262
  def create_databag_if_missing(databag)
237
263
  s = Mixlib::ShellOut.new("#{@knife} data bag list" +
238
- " --format json -c #{@config}").run_command
264
+ " --format json #{@knife_verb_option} " +
265
+ "-c #{@config}").run_command
239
266
  s.error!
240
267
  db = JSON.parse(s.stdout)
241
268
  unless db.include?(databag)
242
- exec!("#{@knife} data bag create #{databag} -c #{@config}", @logger)
269
+ exec!("#{@knife} data bag create #{databag} #{@knife_verb_option} " +
270
+ "-c #{@config}", @logger)
243
271
  end
244
272
  end
245
273
 
246
274
  def delete_databag_if_empty(databag)
247
275
  s = Mixlib::ShellOut.new("#{@knife} data bag show #{databag}" +
248
- " --format json -c #{@config}").run_command
276
+ " --format json #{@knife_verb_option} " +
277
+ "-c #{@config}").run_command
249
278
  s.error!
250
279
  db = JSON.parse(s.stdout)
251
280
  if db.empty?
252
- exec!("#{@knife} data bag delete #{databag} --yes -c #{@config}",
253
- @logger)
281
+ exec!("#{@knife} data bag delete #{databag} --yes " +
282
+ "#{@knife_verb_option} -c #{@config}", @logger)
254
283
  end
255
284
  end
256
285
  end
@@ -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
@@ -87,6 +87,12 @@ module BetweenMeals
87
87
  fail "#{__method__} not implemented"
88
88
  end
89
89
 
90
+ # Only interesting in the case of git where we have an underlying
91
+ # repo object courtesy of Rugged.
92
+ def repo_object
93
+ fail "#{__method__} not implemented"
94
+ end
95
+
90
96
  # This method *must* succeed in the case of no repo directory so that
91
97
  # users can call `checkout`. Users may call `exists?` to find out if
92
98
  # we have an underlying repo yet.
@@ -26,10 +26,10 @@ module BetweenMeals
26
26
  class Repo
27
27
  class Git < BetweenMeals::Repo
28
28
  def setup
29
- if File.exists?(File.expand_path(@repo_path))
29
+ if File.exist?(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
@@ -43,6 +43,12 @@ module BetweenMeals
43
43
  )
44
44
  end
45
45
 
46
+ # Allow people to get access to the underlying Rugged
47
+ # object for their hooks
48
+ def repo_object
49
+ @repo
50
+ end
51
+
46
52
  def exists?
47
53
  !@repo.nil?
48
54
  end
@@ -86,7 +92,7 @@ module BetweenMeals
86
92
  stdout = @cmd.diff(start_ref, end_ref).stdout
87
93
  begin
88
94
  parse_status(stdout).compact
89
- rescue => e
95
+ rescue StandardError => e
90
96
  # We've seen some weird non-reproducible failures here
91
97
  @logger.error(
92
98
  'Something went wrong. Please report this output.',
@@ -108,12 +114,13 @@ module BetweenMeals
108
114
  @repo.index.map { |x| { :path => x[:path], :status => :created } }
109
115
  end
110
116
 
111
- def upstream?(rev, master = 'remotes/trunk')
117
+ def upstream?(rev, master = 'upstream/master')
112
118
  if @cmd.merge_base(rev, master).stdout.strip == rev
113
119
  return true
114
120
  end
121
+
115
122
  return false
116
- rescue
123
+ rescue StandardError
117
124
  return false
118
125
  end
119
126
 
@@ -153,53 +160,54 @@ module BetweenMeals
153
160
 
154
161
  # rubocop:disable MultilineBlockChain
155
162
  changes.lines.map do |line|
156
- case line
157
- when /^A\s+(\S+)$/
163
+ parts = line.chomp.split("\t")
164
+ case parts[0]
165
+ when 'A'
158
166
  # A path
159
167
  {
160
168
  :status => :modified,
161
- :path => Regexp.last_match(1),
169
+ :path => parts[1],
162
170
  }
163
- when /^C(?:\d*)\s+(\S+)\s+(\S+)/
171
+ when /^C(?:\d*)/
164
172
  # C<numbers> path1 path2
165
173
  {
166
174
  :status => :modified,
167
- :path => Regexp.last_match(2),
175
+ :path => parts[2],
168
176
  }
169
- when /^D\s+(\S+)$/
177
+ when 'D'
170
178
  # D path
171
179
  {
172
180
  :status => :deleted,
173
- :path => Regexp.last_match(1),
181
+ :path => parts[1],
174
182
  }
175
- when /^M(?:\d*)\s+(\S+)$/
183
+ when /^M(?:\d*)/
176
184
  # M<numbers> path
177
185
  {
178
186
  :status => :modified,
179
- :path => Regexp.last_match(1),
187
+ :path => parts[1],
180
188
  }
181
- when /^R(?:\d*)\s+(\S+)\s+(\S+)/
189
+ when /^R(?:\d*)/
182
190
  # R<numbers> path1 path2
183
191
  [
184
192
  {
185
193
  :status => :deleted,
186
- :path => Regexp.last_match(1),
194
+ :path => parts[1],
187
195
  },
188
196
  {
189
197
  :status => :modified,
190
- :path => Regexp.last_match(2),
198
+ :path => parts[2],
191
199
  },
192
200
  ]
193
- when /^T\s+(\S+)$/
201
+ when 'T'
194
202
  # T path
195
203
  [
196
204
  {
197
205
  :status => :deleted,
198
- :path => Regexp.last_match(1),
206
+ :path => parts[1],
199
207
  },
200
208
  {
201
209
  :status => :modified,
202
- :path => Regexp.last_match(1),
210
+ :path => parts[1],
203
211
  },
204
212
  ]
205
213
  else
@@ -21,7 +21,11 @@ module BetweenMeals
21
21
  class Git < BetweenMeals::Repo
22
22
  class Cmd < BetweenMeals::Cmd
23
23
  def config(key)
24
- cmd("config #{key}")
24
+ s = cmd("config #{key}", nil, true)
25
+ unless [0, 1].include?(s.exitstatus)
26
+ s.error!
27
+ end
28
+ s
25
29
  end
26
30
 
27
31
  def clone(url, repo_path)
@@ -32,7 +32,7 @@ module BetweenMeals
32
32
  end
33
33
 
34
34
  def exists?
35
- Dir.exists?(Pathname.new(@repo_path).join('.hg'))
35
+ Dir.exist?(Pathname.new(@repo_path).join('.hg'))
36
36
  end
37
37
 
38
38
  def head_rev
@@ -50,7 +50,7 @@ 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
56
  'Something went wrong. Please report this output.',
@@ -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(cmd.stdout)
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
- case line
171
- when /^A (\S+)$/
169
+ parts = line.chomp.split(nil, 2)
170
+ case parts[0]
171
+ when 'A'
172
172
  {
173
173
  :status => :added,
174
- :path => Regexp.last_match(1),
174
+ :path => parts[1],
175
175
  }
176
- when /^C (\S+)$/
176
+ when 'C'
177
177
  {
178
178
  :status => :clean,
179
- :path => Regexp.last_match(1),
179
+ :path => parts[1],
180
180
  }
181
- when /^R (\S+)$/
181
+ when 'R'
182
182
  {
183
183
  :status => :deleted,
184
- :path => Regexp.last_match(1),
184
+ :path => parts[1],
185
185
  }
186
- when /^M (\S+)$/
186
+ when 'M'
187
187
  {
188
188
  :status => :modified,
189
- :path => Regexp.last_match(1),
189
+ :path => parts[1],
190
190
  }
191
- when /^! (\S+)$/
191
+ when '!'
192
192
  {
193
193
  :status => :missing,
194
- :path => Regexp.last_match(1),
194
+ :path => parts[1],
195
195
  }
196
- when /^\? (\S+)$/
196
+ when '?'
197
197
  {
198
198
  :status => :untracked,
199
- :path => Regexp.last_match(1),
199
+ :path => parts[1],
200
200
  }
201
- when /^I (\S+)$/
201
+ when 'I'
202
202
  {
203
203
  :status => :ignored,
204
- :path => Regexp.last_match(1),
204
+ :path => parts[1],
205
205
  }
206
206
  else
207
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
@@ -50,7 +50,7 @@ module BetweenMeals
50
50
  begin
51
51
  f.write(msg)
52
52
  f.flush
53
- cmd("commit --amend -l #{f.path}")
53
+ cmd("commit --amend --exclude '**' -l #{f.path}")
54
54
  ensure
55
55
  f.close
56
56
  f.unlink
@@ -33,7 +33,7 @@ module BetweenMeals
33
33
  end
34
34
 
35
35
  def exists?
36
- Dir.exists?(Pathname.new(@repo_path).join('.svn'))
36
+ Dir.exist?(Pathname.new(@repo_path).join('.svn'))
37
37
  end
38
38
 
39
39
  def head_rev
@@ -64,7 +64,7 @@ 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
69
  'Something went wrong. Please report this output.',
70
70
  )
@@ -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,7 +102,7 @@ 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 /^([\w ])\w?\s+(\S+)$/
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}/", ''),
@@ -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 freeo to use... note that if you pass in a logger once
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
- c = execute(command)
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.info(msg) if @@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
- begin
73
- Timeout.timeout(1) do
74
- begin
75
- s = TCPSocket.new('localhost', port)
76
- s.close
77
- return true
78
- rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH
79
- return false
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,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: between_meals
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
4
+ version: 0.0.12
5
5
  platform: ruby
6
6
  authors:
7
7
  - Phil Dibowitz
@@ -9,135 +9,51 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2016-09-26 00:00:00.000000000 Z
12
+ date: 2020-09-21 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: colorize
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  requirements:
18
- - - '>='
18
+ - - ">="
19
19
  - !ruby/object:Gem::Version
20
20
  version: '0'
21
21
  type: :runtime
22
22
  prerelease: false
23
23
  version_requirements: !ruby/object:Gem::Requirement
24
24
  requirements:
25
- - - '>='
26
- - !ruby/object:Gem::Version
27
- version: '0'
28
- - !ruby/object:Gem::Dependency
29
- name: json
30
- requirement: !ruby/object:Gem::Requirement
31
- requirements:
32
- - - '>='
33
- - !ruby/object:Gem::Version
34
- version: '0'
35
- type: :runtime
36
- prerelease: false
37
- version_requirements: !ruby/object:Gem::Requirement
38
- requirements:
39
- - - '>='
25
+ - - ">="
40
26
  - !ruby/object:Gem::Version
41
27
  version: '0'
42
28
  - !ruby/object:Gem::Dependency
43
29
  name: mixlib-shellout
44
30
  requirement: !ruby/object:Gem::Requirement
45
31
  requirements:
46
- - - '>='
32
+ - - ">="
47
33
  - !ruby/object:Gem::Version
48
34
  version: '0'
49
35
  type: :runtime
50
36
  prerelease: false
51
37
  version_requirements: !ruby/object:Gem::Requirement
52
38
  requirements:
53
- - - '>='
39
+ - - ">="
54
40
  - !ruby/object:Gem::Version
55
41
  version: '0'
56
42
  - !ruby/object:Gem::Dependency
57
43
  name: rugged
58
44
  requirement: !ruby/object:Gem::Requirement
59
45
  requirements:
60
- - - '>='
46
+ - - ">="
61
47
  - !ruby/object:Gem::Version
62
48
  version: '0'
63
49
  type: :runtime
64
50
  prerelease: false
65
51
  version_requirements: !ruby/object:Gem::Requirement
66
52
  requirements:
67
- - - '>='
68
- - !ruby/object:Gem::Version
69
- version: '0'
70
- - !ruby/object:Gem::Dependency
71
- name: rspec-core
72
- requirement: !ruby/object:Gem::Requirement
73
- requirements:
74
- - - '>='
75
- - !ruby/object:Gem::Version
76
- version: '0'
77
- type: :development
78
- prerelease: false
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-expectations
86
- requirement: !ruby/object:Gem::Requirement
87
- requirements:
88
- - - '>='
89
- - !ruby/object:Gem::Version
90
- version: '0'
91
- type: :development
92
- prerelease: false
93
- version_requirements: !ruby/object:Gem::Requirement
94
- requirements:
95
- - - '>='
96
- - !ruby/object:Gem::Version
97
- version: '0'
98
- - !ruby/object:Gem::Dependency
99
- name: rspec-mocks
100
- requirement: !ruby/object:Gem::Requirement
101
- requirements:
102
- - - '>='
103
- - !ruby/object:Gem::Version
104
- version: '0'
105
- type: :development
106
- prerelease: false
107
- version_requirements: !ruby/object:Gem::Requirement
108
- requirements:
109
- - - '>='
53
+ - - ">="
110
54
  - !ruby/object:Gem::Version
111
55
  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'
119
- type: :development
120
- prerelease: false
121
- version_requirements: !ruby/object:Gem::Requirement
122
- requirements:
123
- - - '>='
124
- - !ruby/object:Gem::Version
125
- version: '0'
126
- - !ruby/object:Gem::Dependency
127
- name: simplecov
128
- requirement: !ruby/object:Gem::Requirement
129
- requirements:
130
- - - '>='
131
- - !ruby/object:Gem::Version
132
- version: '0'
133
- type: :development
134
- prerelease: false
135
- version_requirements: !ruby/object:Gem::Requirement
136
- requirements:
137
- - - '>='
138
- - !ruby/object:Gem::Version
139
- version: '0'
140
- description: Library for calculation Chef differences between revisions
56
+ description: Library for calculating Chef differences between revisions
141
57
  email:
142
58
  executables: []
143
59
  extensions: []
@@ -145,26 +61,26 @@ extra_rdoc_files:
145
61
  - README.md
146
62
  - LICENSE
147
63
  files:
148
- - README.md
149
64
  - LICENSE
150
- - lib/between_meals/util.rb
65
+ - README.md
66
+ - lib/between_meals/changes/change.rb
67
+ - lib/between_meals/changes/cookbook.rb
68
+ - lib/between_meals/changes/databag.rb
69
+ - lib/between_meals/changes/role.rb
151
70
  - lib/between_meals/changeset.rb
71
+ - lib/between_meals/cmd.rb
152
72
  - lib/between_meals/knife.rb
153
73
  - lib/between_meals/repo.rb
154
- - lib/between_meals/cmd.rb
155
- - lib/between_meals/changes/databag.rb
156
- - lib/between_meals/changes/cookbook.rb
157
- - lib/between_meals/changes/change.rb
158
- - lib/between_meals/changes/role.rb
159
74
  - lib/between_meals/repo/git.rb
160
- - lib/between_meals/repo/svn.rb
161
75
  - lib/between_meals/repo/git/cmd.rb
162
- - lib/between_meals/repo/svn/cmd.rb
163
- - lib/between_meals/repo/hg/cmd.rb
164
76
  - lib/between_meals/repo/hg.rb
77
+ - lib/between_meals/repo/hg/cmd.rb
78
+ - lib/between_meals/repo/svn.rb
79
+ - lib/between_meals/repo/svn/cmd.rb
80
+ - lib/between_meals/util.rb
165
81
  homepage: https://github.com/facebook/between-meals
166
82
  licenses:
167
- - Apache
83
+ - Apache-2.0
168
84
  metadata: {}
169
85
  post_install_message:
170
86
  rdoc_options: []
@@ -172,17 +88,16 @@ require_paths:
172
88
  - lib
173
89
  required_ruby_version: !ruby/object:Gem::Requirement
174
90
  requirements:
175
- - - '>='
91
+ - - ">="
176
92
  - !ruby/object:Gem::Version
177
93
  version: '0'
178
94
  required_rubygems_version: !ruby/object:Gem::Requirement
179
95
  requirements:
180
- - - '>='
96
+ - - ">="
181
97
  - !ruby/object:Gem::Version
182
98
  version: '0'
183
99
  requirements: []
184
- rubyforge_project:
185
- rubygems_version: 2.0.14
100
+ rubygems_version: 3.1.2
186
101
  signing_key:
187
102
  specification_version: 4
188
103
  summary: Between Meals