Class: KnifeChangelog::Changelog
- Inherits:
-
Object
- Object
- KnifeChangelog::Changelog
show all
- Defined in:
- lib/knife/changelog/berksfile.rb,
lib/knife/changelog/changelog.rb
Defined Under Namespace
Classes: Berksfile, Location
Constant Summary
collapse
- GERRIT_REGEXP =
%r{^(.*)/[^/]+/[^/]+(?:\.git)$}
Instance Method Summary
collapse
-
#all_cookbooks ⇒ Object
returns a list of all cookbooks names.
-
#clean ⇒ Object
-
#cookbook_highest_version(json) ⇒ Object
-
#detect_cur_revision(name, rev, git) ⇒ Object
-
#execute(name, submodule = false) ⇒ Object
-
#format_changelog(name, version_change, changelog) ⇒ Object
-
#generate_from_changelog_file(filename, current_rev, rev_parse, git) ⇒ Object
-
#generate_from_git_history(git, location, current_rev, rev_parse) ⇒ Object
-
#get_from_supermarket_sources(name) ⇒ Object
-
#git?(name) ⇒ Boolean
return true if cookbook is downloaded from git.
-
#git_location(name) ⇒ Object
return a Changelog::Location for a given cookbook.
-
#guess_version_for(name) ⇒ Object
return current locked version for a given cookbook.
-
#handle_git(name, location) ⇒ Object
take cookbook name and Changelog::Location instance.
-
#handle_new_cookbook ⇒ Object
-
#handle_source(name) ⇒ Object
-
#handle_submodule(name) ⇒ Object
-
#https_url(location) ⇒ Object
-
#initialize(config = {}) ⇒ Changelog
constructor
A new instance of Changelog.
-
#linkify(url, changelog) ⇒ Object
-
#local?(name) ⇒ Boolean
return true if cookbook is downloaded from local path.
-
#new_cookbook?(name) ⇒ Boolean
return true if cookbook is not already listed as dependency.
-
#run(cookbooks) ⇒ Object
-
#short(location) ⇒ Object
-
#supermarket?(name) ⇒ Boolean
return true if cookbook is downloaded from supermarket.
-
#supermarkets_for(name) ⇒ Object
Constructor Details
#initialize(config = {}) ⇒ Changelog
Returns a new instance of Changelog.
21
22
23
24
25
|
# File 'lib/knife/changelog/changelog.rb', line 21
def initialize(config = {})
@tmp_prefix = 'knife-changelog'
@config = config
@tmp_dirs = []
end
|
Instance Method Details
#all_cookbooks ⇒ Object
returns a list of all cookbooks names
28
29
30
|
# File 'lib/knife/changelog/changelog.rb', line 28
def all_cookbooks
raise NotImplementedError
end
|
#clean ⇒ Object
95
96
97
98
99
|
# File 'lib/knife/changelog/changelog.rb', line 95
def clean
@tmp_dirs.each do |dir|
FileUtils.rm_rf dir
end
end
|
#cookbook_highest_version(json) ⇒ Object
164
165
166
167
168
169
|
# File 'lib/knife/changelog/changelog.rb', line 164
def cookbook_highest_version(json)
json['versions']
.map { |version_url| Chef::Version.new(version_url.gsub(/.*\//, '')) }
.sort
.last
end
|
#detect_cur_revision(name, rev, git) ⇒ Object
184
185
186
187
188
189
190
191
|
# File 'lib/knife/changelog/changelog.rb', line 184
def detect_cur_revision(name, rev, git)
unless git.revision_exists?(rev)
prefixed_rev = 'v' + rev
return prefixed_rev if git.revision_exists?(prefixed_rev)
fail "#{rev} is not an existing revision (#{name}), not a tag/commit/branch name."
end
rev
end
|
#execute(name, submodule = false) ⇒ Object
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
# File 'lib/knife/changelog/changelog.rb', line 106
def execute(name, submodule = false)
version_change, changelog = if submodule
handle_submodule(name)
elsif new_cookbook?(name)
['', handle_new_cookbook]
else
case true
when supermarket?(name)
handle_source(name)
when git?(name)
handle_git(name, git_location(name))
when local?(name)
Chef::Log.debug "path location are always at the last version"
['', '']
else
raise "Cannot handle #{loc.class} yet"
end
end
format_changelog(name, version_change, changelog)
end
|
127
128
129
130
131
132
133
134
135
136
137
|
# File 'lib/knife/changelog/changelog.rb', line 127
def format_changelog(name, version_change, changelog)
if changelog.empty?
nil
else
full = ["Changelog for #{name}: #{version_change}"]
full << '=' * full.first.size
full << changelog
full << ''
full.compact.join("\n")
end
end
|
#generate_from_changelog_file(filename, current_rev, rev_parse, git) ⇒ Object
225
226
227
228
229
230
231
|
# File 'lib/knife/changelog/changelog.rb', line 225
def generate_from_changelog_file(filename, current_rev, rev_parse, git)
ch = git.diff(filename, current_rev, rev_parse)
.collect { |line| $1.strip if line =~ /^{\+(.*)\+}$/ }.compact
.map { |line| line.gsub(/^#+(.*)$/, "\\1\n---")} .select { |line| !(line =~ /^===+/)}.compact ch.empty? ? nil : ch
end
|
#generate_from_git_history(git, location, current_rev, rev_parse) ⇒ Object
233
234
235
236
237
238
239
240
|
# File 'lib/knife/changelog/changelog.rb', line 233
def generate_from_git_history(git, location, current_rev, rev_parse)
c = git.log(current_rev, rev_parse)
n = https_url(location)
c = linkify(n, c) if @config[:linkify] and n
c = c.map { |line| "* " + line } if @config[:markdown]
c = c.map { |line| line.strip } c
end
|
#get_from_supermarket_sources(name) ⇒ Object
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
|
# File 'lib/knife/changelog/changelog.rb', line 139
def get_from_supermarket_sources(name)
supermarkets_for(name).map do |uri|
begin
RestClient::Request.execute(
url: "#{uri}/api/v1/cookbooks/#{name}",
method: :get,
verify_ssl: false )
rescue => e
Chef::Log.debug "Error fetching package from supermarket #{e.class.name} #{e.message}"
nil
end
end
.compact
.map { |json| JSON.parse(json) }
.sort_by { |ck| cookbook_highest_version(ck) }
.map { |ck| ck['source_url'] || ck ['external_url'] }
.last
.tap do |source|
raise "Cannot find any changelog source for #{name}" unless source
end
end
|
#git?(name) ⇒ Boolean
return true if cookbook is downloaded from git
43
44
45
|
# File 'lib/knife/changelog/changelog.rb', line 43
def git?(name)
raise NotImplementedError
end
|
#git_location(name) ⇒ Object
return a Changelog::Location for a given cookbook
53
54
55
|
# File 'lib/knife/changelog/changelog.rb', line 53
def git_location(name)
raise NotImplementedError
end
|
#guess_version_for(name) ⇒ Object
return current locked version for a given cookbook
64
65
66
|
# File 'lib/knife/changelog/changelog.rb', line 64
def guess_version_for(name)
raise NotImplementedError
end
|
#handle_git(name, location) ⇒ Object
take cookbook name and Changelog::Location instance
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
|
# File 'lib/knife/changelog/changelog.rb', line 208
def handle_git(name, location)
raise "should be a location" unless location.is_a?(Changelog::Location)
git = Git.new(@tmp_prefix, location.uri)
@tmp_dirs << git.shallow_clone
rev_parse = location.rev_parse
cur_rev = detect_cur_revision(name, location.revision, git)
changelog_file = git.files(rev_parse).find { |line| line =~ /\s(changelog.*$)/i }
changelog = if changelog_file and !@config[:ignore_changelog_file]
Chef::Log.info "Found changelog file : " + $1
generate_from_changelog_file($1, cur_rev, rev_parse, git)
end
changelog ||= generate_from_git_history(git, location, cur_rev, rev_parse)
["#{cur_rev}->#{rev_parse}", changelog]
end
|
#handle_new_cookbook ⇒ Object
101
102
103
104
|
# File 'lib/knife/changelog/changelog.rb', line 101
def handle_new_cookbook
stars = '**' if @config[:markdown]
["#{stars}Cookbook was not in the berksfile#{stars}"]
end
|
#handle_source(name) ⇒ Object
171
172
173
174
175
176
177
178
179
180
181
182
|
# File 'lib/knife/changelog/changelog.rb', line 171
def handle_source(name)
url = get_from_supermarket_sources(name)
raise "No source found in supermarket for cookbook '#{name}'" unless url
Chef::Log.debug("Using #{url} as source url")
if !url.end_with?('.git')
url = "#{url}.git"
end
location = Location.new(url, guess_version_for(name), 'HEAD')
handle_git(name, location)
end
|
#handle_submodule(name) ⇒ Object
193
194
195
196
197
198
199
200
201
202
203
204
205
|
# File 'lib/knife/changelog/changelog.rb', line 193
def handle_submodule(name)
subm_url = Mixlib::ShellOut.new("git config --list| grep ^submodule | grep ^submodule.#{name}.url")
subm_url.run_command
subm_url.error!
url = subm_url.stdout.lines.first.split('=')[1].chomp
subm_revision = Mixlib::ShellOut.new("git submodule status #{name}")
subm_revision.run_command
subm_revision.error!
revision = subm_revision.stdout.strip.split(' ').first
revision.gsub!(/^\+/, '')
loc = Location.new(url, revision, 'HEAD')
handle_git(name, loc)
end
|
#https_url(location) ⇒ Object
253
254
255
256
257
258
259
|
# File 'lib/knife/changelog/changelog.rb', line 253
def https_url(location)
if location.uri =~ /^\w+:\/\/(.*@)?(.*)(\.git)?/
"https://%s" % [ $2 ]
else
fail "Cannot guess http url from git remote url: #{location.uri}"
end
end
|
#linkify(url, changelog) ⇒ Object
243
244
245
246
247
248
249
250
251
|
# File 'lib/knife/changelog/changelog.rb', line 243
def linkify(url, changelog)
format = case url
when /gitlab/, /github/
"\\2 (#{url.chomp('.git')}/commit/\\1)"
when GERRIT_REGEXP
"\\2 (#{::Regexp.last_match(1)}/#/q/\\1)"
end
format ? changelog.map { |line| line.sub(/^([a-f0-9]+) (.*)$/, format) } : changelog
end
|
#local?(name) ⇒ Boolean
return true if cookbook is downloaded from local path
48
49
50
|
# File 'lib/knife/changelog/changelog.rb', line 48
def local?(name)
raise NotImplementedError
end
|
#new_cookbook?(name) ⇒ Boolean
return true if cookbook is not already listed as dependency
33
34
35
|
# File 'lib/knife/changelog/changelog.rb', line 33
def new_cookbook?(name)
raise NotImplementedError
end
|
#run(cookbooks) ⇒ Object
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
|
# File 'lib/knife/changelog/changelog.rb', line 70
def run(cookbooks)
changelog = []
begin
if cookbooks.empty? and @config[:allow_update_all]
cks = all_cookbooks
else
cks = cookbooks
end
changelog += cks.map do |cookbook|
Chef::Log.debug "Checking changelog for #{cookbook} (cookbook)"
execute cookbook
end
subs = @config[:submodules] || []
subs = subs.split(',') if subs.is_a? String
changelog += subs.map do |submodule|
Chef::Log.debug "Checking changelog for #{submodule} (submodule)"
execute(submodule, true)
end
update(cks) if @config[:update]
ensure
clean
end
changelog.compact.join("\n")
end
|
#short(location) ⇒ Object
261
262
263
264
265
|
# File 'lib/knife/changelog/changelog.rb', line 261
def short(location)
if location.uri =~ /([\w-]+)\/([\w-]+)(\.git)?$/
"%s/%s" % [$1,$2]
end
end
|
#supermarket?(name) ⇒ Boolean
return true if cookbook is downloaded from supermarket
38
39
40
|
# File 'lib/knife/changelog/changelog.rb', line 38
def supermarket?(name)
raise NotImplementedError
end
|
#supermarkets_for(name) ⇒ Object
59
60
61
|
# File 'lib/knife/changelog/changelog.rb', line 59
def supermarkets_for(name)
raise NotImplementedError
end
|