between_meals 0.0.5 → 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +2 -2
- data/lib/between_meals/changes/change.rb +3 -3
- data/lib/between_meals/changes/cookbook.rb +8 -8
- data/lib/between_meals/changes/databag.rb +3 -3
- data/lib/between_meals/changes/role.rb +4 -4
- data/lib/between_meals/changeset.rb +3 -3
- data/lib/between_meals/cmd.rb +44 -0
- data/lib/between_meals/knife.rb +52 -13
- data/lib/between_meals/repo.rb +74 -30
- data/lib/between_meals/repo/git.rb +49 -49
- data/lib/between_meals/repo/git/cmd.rb +49 -0
- data/lib/between_meals/repo/hg.rb +214 -0
- data/lib/between_meals/repo/hg/cmd.rb +72 -0
- data/lib/between_meals/repo/svn.rb +51 -68
- data/lib/between_meals/repo/svn/cmd.rb +56 -0
- data/lib/between_meals/util.rb +3 -3
- metadata +41 -8
data/README.md
CHANGED
@@ -9,8 +9,8 @@ Between Meals is the library for calculating what Chef objects where modified
|
|
9
9
|
between two revisions in a version control system. It is also the library
|
10
10
|
that that backs Taste Tester and Grocery Delivery.
|
11
11
|
|
12
|
-
It currently supports SVN and
|
13
|
-
other systems.
|
12
|
+
It currently supports SVN, GIT and HG, but plugins can easily be written for
|
13
|
+
other source control systems.
|
14
14
|
|
15
15
|
It also includes some wrappers around knife execution and a few other utility
|
16
16
|
functions.
|
@@ -1,13 +1,13 @@
|
|
1
1
|
# vim: syntax=ruby:expandtab:shiftwidth=2:softtabstop=2:tabstop=2
|
2
2
|
|
3
3
|
# Copyright 2013-present Facebook
|
4
|
-
#
|
4
|
+
#
|
5
5
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
6
|
# you may not use this file except in compliance with the License.
|
7
7
|
# You may obtain a copy of the License at
|
8
|
-
#
|
8
|
+
#
|
9
9
|
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
-
#
|
10
|
+
#
|
11
11
|
# Unless required by applicable law or agreed to in writing, software
|
12
12
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
13
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
@@ -1,13 +1,13 @@
|
|
1
1
|
# vim: syntax=ruby:expandtab:shiftwidth=2:softtabstop=2:tabstop=2
|
2
2
|
|
3
3
|
# Copyright 2013-present Facebook
|
4
|
-
#
|
4
|
+
#
|
5
5
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
6
|
# you may not use this file except in compliance with the License.
|
7
7
|
# You may obtain a copy of the License at
|
8
|
-
#
|
8
|
+
#
|
9
9
|
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
-
#
|
10
|
+
#
|
11
11
|
# Unless required by applicable law or agreed to in writing, software
|
12
12
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
13
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
@@ -54,10 +54,10 @@ module BetweenMeals
|
|
54
54
|
# otherwise it was modified
|
55
55
|
# and will be re-uploaded
|
56
56
|
if files.
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
57
|
+
select { |x| x[:status] == :deleted }.
|
58
|
+
map { |x| x[:path].match(%{.*metadata\.rb$}) }.
|
59
|
+
compact.
|
60
|
+
any?
|
61
61
|
@status = :deleted
|
62
62
|
else
|
63
63
|
@status = :modified
|
@@ -78,7 +78,7 @@ module BetweenMeals
|
|
78
78
|
g = self.explode_path(x[:path], cookbook_dirs)
|
79
79
|
g[:cookbook_dir] + '/' + g[:name] if g
|
80
80
|
end.
|
81
|
-
|
81
|
+
map do |_, change|
|
82
82
|
# Confirm we're dealing with a cookbook
|
83
83
|
# Changes to OWNERS or other stuff that might end up
|
84
84
|
# in [core, other, secure] dirs are ignored
|
@@ -1,13 +1,13 @@
|
|
1
1
|
# vim: syntax=ruby:expandtab:shiftwidth=2:softtabstop=2:tabstop=2
|
2
2
|
|
3
3
|
# Copyright 2013-present Facebook
|
4
|
-
#
|
4
|
+
#
|
5
5
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
6
|
# you may not use this file except in compliance with the License.
|
7
7
|
# You may obtain a copy of the License at
|
8
|
-
#
|
8
|
+
#
|
9
9
|
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
-
#
|
10
|
+
#
|
11
11
|
# Unless required by applicable law or agreed to in writing, software
|
12
12
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
13
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
@@ -1,13 +1,13 @@
|
|
1
1
|
# vim: syntax=ruby:expandtab:shiftwidth=2:softtabstop=2:tabstop=2
|
2
2
|
|
3
3
|
# Copyright 2013-present Facebook
|
4
|
-
#
|
4
|
+
#
|
5
5
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
6
|
# you may not use this file except in compliance with the License.
|
7
7
|
# You may obtain a copy of the License at
|
8
|
-
#
|
8
|
+
#
|
9
9
|
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
-
#
|
10
|
+
#
|
11
11
|
# Unless required by applicable law or agreed to in writing, software
|
12
12
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
13
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
@@ -20,7 +20,7 @@ module BetweenMeals
|
|
20
20
|
# Changeset aware role
|
21
21
|
class Role < Change
|
22
22
|
def self.name_from_path(path, role_dir)
|
23
|
-
re =
|
23
|
+
re = %r{^#{role_dir}/(.+)\.rb}
|
24
24
|
debug("[role] Matching #{path} against #{re}")
|
25
25
|
m = path.match(re)
|
26
26
|
if m
|
@@ -1,13 +1,13 @@
|
|
1
1
|
# vim: syntax=ruby:expandtab:shiftwidth=2:softtabstop=2:tabstop=2
|
2
2
|
|
3
3
|
# Copyright 2013-present Facebook
|
4
|
-
#
|
4
|
+
#
|
5
5
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
6
|
# you may not use this file except in compliance with the License.
|
7
7
|
# You may obtain a copy of the License at
|
8
|
-
#
|
8
|
+
#
|
9
9
|
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
-
#
|
10
|
+
#
|
11
11
|
# Unless required by applicable law or agreed to in writing, software
|
12
12
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
13
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# vim: syntax=ruby:expandtab:shiftwidth=2:softtabstop=2:tabstop=2
|
2
|
+
|
3
|
+
# Copyright 2013-present Facebook
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
|
17
|
+
require 'logger'
|
18
|
+
|
19
|
+
module BetweenMeals
|
20
|
+
class Cmd
|
21
|
+
attr_accessor :bin
|
22
|
+
|
23
|
+
def initialize(params)
|
24
|
+
@bin = params[:bin] || fail
|
25
|
+
@cwd = params[:cwd] || Dir.pwd
|
26
|
+
@logger = params[:logger] || Logger.new(STDOUT)
|
27
|
+
end
|
28
|
+
|
29
|
+
def cmd(params, cwd = nil)
|
30
|
+
unless cwd
|
31
|
+
cwd = File.expand_path(@cwd)
|
32
|
+
end
|
33
|
+
cmd = "#{@bin} #{params}"
|
34
|
+
@logger.info("Running \"#{cmd}\"")
|
35
|
+
c = Mixlib::ShellOut.new(
|
36
|
+
cmd,
|
37
|
+
:cwd => cwd
|
38
|
+
)
|
39
|
+
c.run_command
|
40
|
+
c.error!
|
41
|
+
c
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/lib/between_meals/knife.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
# vim: syntax=ruby:expandtab:shiftwidth=2:softtabstop=2:tabstop=2
|
2
2
|
|
3
3
|
# Copyright 2013-present Facebook
|
4
|
-
#
|
4
|
+
#
|
5
5
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
6
|
# you may not use this file except in compliance with the License.
|
7
7
|
# You may obtain a copy of the License at
|
8
|
-
#
|
8
|
+
#
|
9
9
|
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
-
#
|
10
|
+
#
|
11
11
|
# Unless required by applicable law or agreed to in writing, software
|
12
12
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
13
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
@@ -31,14 +31,16 @@ module BetweenMeals
|
|
31
31
|
@user = opts[:user] || ENV['USER']
|
32
32
|
@home = opts[:home] || ENV['HOME']
|
33
33
|
# make sure people can pass in false :)
|
34
|
-
@ssl = opts[:ssl].nil? ? true : opts[:ssl]
|
34
|
+
@ssl = opts[:ssl].nil? ? true : opts[:ssl]
|
35
35
|
@host = opts[:host] || 'localhost'
|
36
36
|
@port = opts[:port] || 4000
|
37
37
|
@config = opts[:config] ||
|
38
|
-
|
38
|
+
"#{@home}/.chef/knife-#{@user}-taste-tester.rb"
|
39
39
|
@knife = opts[:bin] || 'knife'
|
40
|
+
@berks = opts[:berks_bin] || 'berks'
|
41
|
+
@berks_config = opts[:berks_config]
|
40
42
|
@pem = opts[:pem] ||
|
41
|
-
|
43
|
+
"#{@home}/.chef/#{@user}-taste-tester.pem"
|
42
44
|
@role_dir = opts[:role_dir]
|
43
45
|
@cookbook_dirs = opts[:cookbook_dirs]
|
44
46
|
@databag_dir = opts[:databag_dir]
|
@@ -48,8 +50,10 @@ module BetweenMeals
|
|
48
50
|
end
|
49
51
|
|
50
52
|
def role_upload_all
|
51
|
-
|
52
|
-
|
53
|
+
if File.exists?(@role_dir)
|
54
|
+
roles = File.join(@role_dir, '*.rb')
|
55
|
+
exec!("#{@knife} role from file #{roles} -c #{@config}", @logger)
|
56
|
+
end
|
53
57
|
end
|
54
58
|
|
55
59
|
def role_upload(roles)
|
@@ -73,13 +77,45 @@ module BetweenMeals
|
|
73
77
|
exec!("#{@knife} cookbook upload -a -c #{@config}", @logger)
|
74
78
|
end
|
75
79
|
|
80
|
+
def berks_cookbook_upload_all
|
81
|
+
if @berks_config
|
82
|
+
berks_config = '--config=' + @berks_config
|
83
|
+
end
|
84
|
+
@cookbook_dirs.each do |path|
|
85
|
+
cookbooks = Dir["#{path}/*"].select { |o| File.directory?(o) }
|
86
|
+
cookbooks.each do |cb|
|
87
|
+
@logger.warn("Running berkshelf on cookbook: #{cb}")
|
88
|
+
exec!("cd #{cb} && #{@berks} install #{berks_config} && " +
|
89
|
+
"#{@berks} upload #{berks_config}", @logger)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
76
94
|
def cookbook_upload(cookbooks)
|
77
95
|
if cookbooks.any?
|
78
|
-
cookbooks = cookbooks.map
|
96
|
+
cookbooks = cookbooks.map(&:name).join(' ')
|
79
97
|
exec!("#{@knife} cookbook upload #{cookbooks} -c #{@config}", @logger)
|
80
98
|
end
|
81
99
|
end
|
82
100
|
|
101
|
+
def berks_cookbook_upload(cookbooks)
|
102
|
+
# cookbooks: array
|
103
|
+
# cookbook_paths: array
|
104
|
+
if @berks_config
|
105
|
+
berks_config = '--config=' + @berks_config
|
106
|
+
end
|
107
|
+
if cookbooks.any?
|
108
|
+
@cookbook_dirs.each do |path|
|
109
|
+
cookbooks.each do |cb|
|
110
|
+
next unless File.exists?("#{path}/#{cb}")
|
111
|
+
@logger.warn("Running berkshelf on cookbook: #{cb}")
|
112
|
+
exec!("cd #{path}/#{cb} && #{@berks} install #{berks_config} && " +
|
113
|
+
"#{@berks} upload #{berks_config}", @logger)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
83
119
|
def cookbook_delete(cookbooks)
|
84
120
|
if cookbooks.any?
|
85
121
|
cookbooks.each do |cookbook|
|
@@ -101,19 +137,22 @@ module BetweenMeals
|
|
101
137
|
|
102
138
|
def databag_upload(databags)
|
103
139
|
if databags.any?
|
104
|
-
databags.group_by
|
140
|
+
databags.group_by(&:name).each do |dbname, dbs|
|
105
141
|
create_databag_if_missing(dbname)
|
106
142
|
dbitems = dbs.map do |x|
|
107
143
|
File.join(@databag_dir, dbname, "#{x.item}.json")
|
108
144
|
end.join(' ')
|
109
|
-
exec!(
|
145
|
+
exec!(
|
146
|
+
"#{@knife} data bag from file #{dbname} #{dbitems} -c #{@config}",
|
147
|
+
@logger
|
148
|
+
)
|
110
149
|
end
|
111
150
|
end
|
112
151
|
end
|
113
152
|
|
114
153
|
def databag_delete(databags)
|
115
154
|
if databags.any?
|
116
|
-
databags.group_by
|
155
|
+
databags.group_by(&:name).each do |dbname, dbs|
|
117
156
|
dbs.each do |db|
|
118
157
|
exec!("#{@knife} data bag delete #{dbname} #{db.item}" +
|
119
158
|
" --yes -c #{@config}", @logger)
|
@@ -146,7 +185,7 @@ BLOCK
|
|
146
185
|
end
|
147
186
|
if !File.exists?(@config) ||
|
148
187
|
::Digest::MD5.hexdigest(cfg) !=
|
149
|
-
|
188
|
+
::Digest::MD5.hexdigest(File.read(@config))
|
150
189
|
@logger.info("Generating #{@config}")
|
151
190
|
File.write(@config, cfg)
|
152
191
|
end
|
data/lib/between_meals/repo.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
# vim: syntax=ruby:expandtab:shiftwidth=2:softtabstop=2:tabstop=2
|
2
2
|
|
3
3
|
# Copyright 2013-present Facebook
|
4
|
-
#
|
4
|
+
#
|
5
5
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
6
|
# you may not use this file except in compliance with the License.
|
7
7
|
# You may obtain a copy of the License at
|
8
|
-
#
|
8
|
+
#
|
9
9
|
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
-
#
|
10
|
+
#
|
11
11
|
# Unless required by applicable law or agreed to in writing, software
|
12
12
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
13
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
@@ -19,8 +19,7 @@ require 'mixlib/shellout'
|
|
19
19
|
module BetweenMeals
|
20
20
|
# Local checkout wrapper
|
21
21
|
class Repo
|
22
|
-
attr_reader :repo_path
|
23
|
-
attr_writer :bin
|
22
|
+
attr_reader :repo_path, :bin
|
24
23
|
|
25
24
|
def initialize(repo_path, logger)
|
26
25
|
@repo_path = repo_path
|
@@ -35,93 +34,138 @@ module BetweenMeals
|
|
35
34
|
|
36
35
|
def self.get(type, repo_path, logger)
|
37
36
|
case type
|
37
|
+
when 'auto'
|
38
|
+
unless File.directory?(repo_path)
|
39
|
+
logger.warn("#{repo_path} does not point to a repo")
|
40
|
+
exit(1)
|
41
|
+
end
|
42
|
+
logger.info('Trying to detect repo type')
|
43
|
+
require 'between_meals/repo/git'
|
44
|
+
require 'between_meals/repo/hg'
|
45
|
+
require 'between_meals/repo/svn'
|
46
|
+
[
|
47
|
+
BetweenMeals::Repo::Git,
|
48
|
+
BetweenMeals::Repo::Hg,
|
49
|
+
BetweenMeals::Repo::Svn,
|
50
|
+
].each do |klass|
|
51
|
+
begin
|
52
|
+
r = klass.new(repo_path, logger)
|
53
|
+
if r.exists?
|
54
|
+
logger.info("Repo found to be #{klass.to_s.split('::').last}")
|
55
|
+
return r
|
56
|
+
end
|
57
|
+
rescue
|
58
|
+
logger.debug("Skipping #{klass}")
|
59
|
+
end
|
60
|
+
end
|
61
|
+
logger.warn("Failed detecting repo type at #{repo_path}")
|
62
|
+
exit(1)
|
38
63
|
when 'svn'
|
39
64
|
require 'between_meals/repo/svn'
|
40
65
|
BetweenMeals::Repo::Svn.new(repo_path, logger)
|
41
66
|
when 'git'
|
42
67
|
require 'between_meals/repo/git'
|
43
68
|
BetweenMeals::Repo::Git.new(repo_path, logger)
|
69
|
+
when 'hg'
|
70
|
+
require 'between_meals/repo/hg'
|
71
|
+
BetweenMeals::Repo::Hg.new(repo_path, logger)
|
44
72
|
else
|
45
73
|
fail "Do not know repo type #{type}"
|
46
74
|
end
|
47
75
|
end
|
48
76
|
|
77
|
+
def bin=(bin)
|
78
|
+
@bin = bin
|
79
|
+
@cmd.bin = bin
|
80
|
+
end
|
81
|
+
|
49
82
|
def exists?
|
50
|
-
fail
|
83
|
+
fail "#{__method__} not implemented"
|
51
84
|
end
|
52
85
|
|
53
86
|
def status
|
54
|
-
fail
|
87
|
+
fail "#{__method__} not implemented"
|
55
88
|
end
|
56
89
|
|
90
|
+
# This method *must* succeed in the case of no repo directory so that
|
91
|
+
# users can call `checkout`. Users may call `exists?` to find out if
|
92
|
+
# we have an underlying repo yet.
|
57
93
|
def setup
|
58
|
-
fail
|
94
|
+
fail "#{__method__} not implemented"
|
59
95
|
end
|
60
96
|
|
61
97
|
def head_rev
|
62
|
-
fail
|
98
|
+
fail "#{__method__} not implemented"
|
63
99
|
end
|
64
100
|
|
65
101
|
def head_msg
|
66
|
-
fail
|
102
|
+
fail "#{__method__} not implemented"
|
67
103
|
end
|
68
104
|
|
69
105
|
def head_msg=
|
70
|
-
fail
|
106
|
+
fail "#{__method__} not implemented"
|
71
107
|
end
|
72
108
|
|
73
109
|
def head_parents
|
74
|
-
fail
|
110
|
+
fail "#{__method__} not implemented"
|
75
111
|
end
|
76
112
|
|
77
113
|
def latest_revision
|
78
|
-
fail
|
114
|
+
fail "#{__method__} not implemented"
|
79
115
|
end
|
80
116
|
|
81
117
|
def create(_url)
|
82
|
-
fail
|
118
|
+
fail "#{__method__} not implemented"
|
83
119
|
end
|
84
120
|
|
85
121
|
# Return files changed between two revisions
|
86
122
|
def changes(_start_ref, _end_ref)
|
87
|
-
fail
|
123
|
+
fail "#{__method__} not implemented"
|
88
124
|
end
|
89
125
|
|
90
126
|
def update
|
91
|
-
fail
|
127
|
+
fail "#{__method__} not implemented"
|
92
128
|
end
|
93
129
|
|
94
130
|
# Return all files
|
95
131
|
def files
|
96
|
-
fail
|
97
|
-
end
|
98
|
-
|
99
|
-
def latest_revision
|
100
|
-
fail 'Not implemented'
|
132
|
+
fail "#{__method__} not implemented"
|
101
133
|
end
|
102
134
|
|
103
135
|
def head
|
104
|
-
fail
|
136
|
+
fail "#{__method__} not implemented"
|
105
137
|
end
|
106
138
|
|
107
139
|
def checkout
|
108
|
-
fail
|
109
|
-
end
|
110
|
-
|
111
|
-
def update
|
112
|
-
fail 'Not implemented'
|
140
|
+
fail "#{__method__} not implemented"
|
113
141
|
end
|
114
142
|
|
115
143
|
def last_author
|
116
|
-
fail
|
144
|
+
fail "#{__method__} not implemented"
|
117
145
|
end
|
118
146
|
|
119
147
|
def last_msg
|
120
|
-
fail
|
148
|
+
fail "#{__method__} not implemented"
|
121
149
|
end
|
122
150
|
|
123
151
|
def last_msg=
|
124
|
-
fail
|
152
|
+
fail "#{__method__} not implemented"
|
153
|
+
end
|
154
|
+
|
155
|
+
def name
|
156
|
+
fail "#{__method__} not implemented"
|
157
|
+
end
|
158
|
+
|
159
|
+
def email
|
160
|
+
fail "#{__method__} not implemented"
|
161
|
+
end
|
162
|
+
|
163
|
+
def upstream?(_rev)
|
164
|
+
fail "#{__method__} not implemented"
|
165
|
+
end
|
166
|
+
|
167
|
+
def valid_ref?(_rev)
|
168
|
+
fail "#{__method__} not implemented"
|
125
169
|
end
|
126
170
|
end
|
127
171
|
end
|