between_meals 0.0.5 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- 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
|