chlog 0.9.0 → 1.6.1.alpha
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of chlog might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/bin/chlog +532 -0
- metadata +13 -29
- data/exe/chlog +0 -82
- data/lib/chlog/version.rb +0 -16
- data/lib/chlog.rb +0 -417
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2ab687f94e5ae6381ae55993779ab02ca0d043f7f8a57924890cc5c891390a89
|
4
|
+
data.tar.gz: 1a4e1bc3f3b10aefbcd29c124b0e812e0dde7fd017740cc351d674074fe150b7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8891858162cf7e70148069d1802f50d12a60cfc63caac84a9d149e872ba19bb0a368cfa42b89fb12f43bfeca84bb13eafbfed52253a1d9d5e006515b7b40132f
|
7
|
+
data.tar.gz: 5d306384893f5ca1486c4decca64e727fb0e0ca7329d3a2499e9278ac4a1772064eef67f7b063b9c203413f9c8a6272d1975dc1cc4010d00c6f8db0f241095e4
|
data/bin/chlog
ADDED
@@ -0,0 +1,532 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# ------------------------------------------------------
|
3
|
+
# File : chlog.rb
|
4
|
+
# Authors : ccmywish <ccmywish@qq.com>
|
5
|
+
# Created on : <2022-03-18>
|
6
|
+
# Last modified : <2022-04-09>
|
7
|
+
#
|
8
|
+
# chlog:
|
9
|
+
#
|
10
|
+
# Maintain your project's Changelog on the cli.
|
11
|
+
#
|
12
|
+
# ------------------------------------------------------
|
13
|
+
|
14
|
+
puts __FILE__
|
15
|
+
puts $0
|
16
|
+
|
17
|
+
CHLOG_VERSION = "1.6.1.alpha"
|
18
|
+
|
19
|
+
require 'date'
|
20
|
+
$today = Date.today.to_s
|
21
|
+
|
22
|
+
UNRELEASED_TITLE = "## [Unreleased](#) (#$today)"
|
23
|
+
|
24
|
+
CHLOG_TEMPLATE = <<EOT
|
25
|
+
# Changelog
|
26
|
+
|
27
|
+
#{UNRELEASED_TITLE}
|
28
|
+
|
29
|
+
<br>
|
30
|
+
|
31
|
+
## [Initialize](#) (#$today)
|
32
|
+
|
33
|
+
<br>
|
34
|
+
|
35
|
+
<hr>
|
36
|
+
|
37
|
+
This Changelog is maintained with [chlog](https://github.com/ccmywish/chlog)
|
38
|
+
|
39
|
+
EOT
|
40
|
+
|
41
|
+
$Changelog_file = `git rev-parse --show-toplevel`.chomp + '/CHANGELOG.md'
|
42
|
+
|
43
|
+
def get_changelog
|
44
|
+
file = $Changelog_file
|
45
|
+
if File.exists? file
|
46
|
+
return File.read file
|
47
|
+
else
|
48
|
+
puts "chlog: Auto generate #$Changelog_file"
|
49
|
+
File.write(file, CHLOG_TEMPLATE)
|
50
|
+
return File.read file
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
def help
|
56
|
+
puts <<EOH
|
57
|
+
chlog (v#{CHLOG_VERSION}): Help maintain the Changelog of your projects
|
58
|
+
|
59
|
+
usage:
|
60
|
+
|
61
|
+
chlog => Generate CHANGELOG.md in git root
|
62
|
+
chlog -g (-m) (--sub) => Reuse last commit log (m category / sub category)
|
63
|
+
chlog (--sub) log => Determine main category(fallback Enhancements) (/ sub category) add log
|
64
|
+
chlog -n (--sub) log => Add log to New features (/ sub category)
|
65
|
+
chlog -e (--sub) log => Add log to Enhancements (/ sub category)
|
66
|
+
chlog -b (--sub) log => Add log to Bug fixes (/ sub category)
|
67
|
+
chlog -s (--sub) log => Add log to Security (/ sub category)
|
68
|
+
chlog -c (--sub) log => Add log to Compatibility(/ sub category)
|
69
|
+
chlog -d (--sub) log => Add log to Deprecations (/ sub category)
|
70
|
+
chlog -r v3.14 => Release version to v3.14
|
71
|
+
|
72
|
+
EOH
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
def match_unreleased?(str)
|
77
|
+
str =~ /^## \[Unreleased\]\(.*\) \(\d{4}-\d\d-\d\d\)/
|
78
|
+
end
|
79
|
+
|
80
|
+
def match_unreleased_fail!(str)
|
81
|
+
unless match_unreleased?(str)
|
82
|
+
puts "chlog: Unmathed format with chlog"
|
83
|
+
# "#{lns[1][1..]}"
|
84
|
+
puts " Unreleased version must be the third line.", ""
|
85
|
+
exit -1
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def match_new_features?(str)
|
90
|
+
str =~ /^### New features:/
|
91
|
+
end
|
92
|
+
|
93
|
+
def match_enhancements?(str)
|
94
|
+
str =~ /^### Enhancements:/
|
95
|
+
end
|
96
|
+
|
97
|
+
def match_bug_fixes?(str)
|
98
|
+
str =~ /^### Bug fixes:/
|
99
|
+
end
|
100
|
+
|
101
|
+
def match_security?(str)
|
102
|
+
str =~ /^### Security:/
|
103
|
+
end
|
104
|
+
|
105
|
+
def match_compatibility?(str)
|
106
|
+
str =~ /^### Compatibility:/
|
107
|
+
end
|
108
|
+
|
109
|
+
def match_deprecations?(str)
|
110
|
+
str =~ /^### Deprecations:/
|
111
|
+
end
|
112
|
+
|
113
|
+
|
114
|
+
def next_version_index(lns_array)
|
115
|
+
nvi = lns_array[3..].each_with_index {break _2 if _1.start_with?("## [") }
|
116
|
+
nvi += 3
|
117
|
+
end
|
118
|
+
|
119
|
+
def next_category_index(lns_array)
|
120
|
+
nci = lns_array[3...nvi].each_with_index {break _2 if _1.start_with?("### ") }
|
121
|
+
|
122
|
+
# The not match return value is not nil!! But an array!!
|
123
|
+
if nci.is_a(Integer)
|
124
|
+
nci += 3
|
125
|
+
else
|
126
|
+
nil
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
|
131
|
+
#
|
132
|
+
# ### New features:
|
133
|
+
#
|
134
|
+
# - xaaaaa
|
135
|
+
# - xbbbbb
|
136
|
+
# - xccccc [-> this]
|
137
|
+
#
|
138
|
+
def find_main_category_last_list_item_index(lns,
|
139
|
+
main_cat_index,
|
140
|
+
first_lower_order_category_index)
|
141
|
+
mci = main_cat_index
|
142
|
+
nci = first_lower_order_category_index
|
143
|
+
|
144
|
+
list_i = lns[mci+2..nci].each_with_index do
|
145
|
+
break _2 if _1 !~ /^- .*/
|
146
|
+
end
|
147
|
+
list_i += mci+2 - 1
|
148
|
+
end
|
149
|
+
|
150
|
+
|
151
|
+
|
152
|
+
$order_table = [
|
153
|
+
:match_new_features?,
|
154
|
+
:match_enhancements?,
|
155
|
+
:match_bug_fixes?,
|
156
|
+
:match_security?,
|
157
|
+
:match_compatibility?,
|
158
|
+
:match_deprecations?
|
159
|
+
]
|
160
|
+
|
161
|
+
|
162
|
+
def first_lower_order_category_index(lns_array, category_order)
|
163
|
+
|
164
|
+
o = category_order
|
165
|
+
|
166
|
+
nvi = next_version_index(lns_array)
|
167
|
+
|
168
|
+
while o < $order_table.size
|
169
|
+
lns_array[0...nvi].each_with_index do
|
170
|
+
if send($order_table[o], _1)
|
171
|
+
return _2
|
172
|
+
end
|
173
|
+
end
|
174
|
+
o += 1
|
175
|
+
end
|
176
|
+
|
177
|
+
# Next version above
|
178
|
+
return (nvi - 2)
|
179
|
+
end
|
180
|
+
|
181
|
+
|
182
|
+
|
183
|
+
#
|
184
|
+
# A meta function: do the real work other 6 functions delegate
|
185
|
+
#
|
186
|
+
# This function detect the main category, and then handle the
|
187
|
+
# sub category.
|
188
|
+
#
|
189
|
+
def meta_add_to_a_category(log, main_category_order, category)
|
190
|
+
|
191
|
+
content = get_changelog
|
192
|
+
lns = content.lines
|
193
|
+
|
194
|
+
match_unreleased_fail!(lns[2])
|
195
|
+
|
196
|
+
nvi = next_version_index(lns)
|
197
|
+
# To find the existing category line
|
198
|
+
main_cat_i = lns[0...nvi].each_with_index do
|
199
|
+
# Adjust to index of the order table
|
200
|
+
break _2 if send($order_table[main_category_order-1], _1)
|
201
|
+
end
|
202
|
+
|
203
|
+
#
|
204
|
+
# Always update to latest time when making a log
|
205
|
+
#
|
206
|
+
# We must add a "\n" because every element of the array
|
207
|
+
# is a sentence with a trailing newline, then they can
|
208
|
+
# be 'joined' to a working long string
|
209
|
+
#
|
210
|
+
lns[2] = UNRELEASED_TITLE + "\n"
|
211
|
+
|
212
|
+
f_l_o_c_i = first_lower_order_category_index(lns, main_category_order)
|
213
|
+
|
214
|
+
if main_cat_i.class != Integer
|
215
|
+
################################################################################
|
216
|
+
# The main category not exists
|
217
|
+
################################################################################
|
218
|
+
|
219
|
+
|
220
|
+
########################################
|
221
|
+
if $sub_category
|
222
|
+
|
223
|
+
# Because the main category not exists,
|
224
|
+
# nor does the sub category
|
225
|
+
#
|
226
|
+
sub_cat_i = f_l_o_c_i
|
227
|
+
to_wr = lns[0...sub_cat_i].join + "### #{category}:\n\n" + "**#{$sub_category}**\n\n" + ' - ' + log + "\n\n"
|
228
|
+
File.write($Changelog_file, to_wr + lns[sub_cat_i..].join)
|
229
|
+
|
230
|
+
puts "chlog: Add log to #{category}/#{$sub_category}"
|
231
|
+
return
|
232
|
+
end # end of if $sub_category
|
233
|
+
########################################
|
234
|
+
|
235
|
+
|
236
|
+
# situation: no sub category
|
237
|
+
|
238
|
+
# Not need adjust to the index of the order table
|
239
|
+
log_loc = f_l_o_c_i
|
240
|
+
puts "chlog: Add '#{category}' category"
|
241
|
+
to_wr = lns[0...(log_loc)].join + "### #{category}:\n\n" + '- ' + log + "\n"
|
242
|
+
File.write($Changelog_file, to_wr + lns[log_loc-1..].join)
|
243
|
+
|
244
|
+
else
|
245
|
+
################################################################################
|
246
|
+
# The main category exists
|
247
|
+
################################################################################
|
248
|
+
|
249
|
+
|
250
|
+
########################################
|
251
|
+
if $sub_category
|
252
|
+
|
253
|
+
# from first list item to next main cat
|
254
|
+
# search if sub cat already exists
|
255
|
+
sub_cat_i = lns[main_cat_i+2...f_l_o_c_i].each_with_index do
|
256
|
+
break _2 if _1 =~ /^\*\*#{$sub_category}\*\*/
|
257
|
+
end
|
258
|
+
|
259
|
+
if !sub_cat_i.is_a?(Integer)
|
260
|
+
# the sub category not exists
|
261
|
+
|
262
|
+
sub_cat_i = 2 + find_main_category_last_list_item_index(lns,main_cat_i,f_l_o_c_i)
|
263
|
+
to_wr = lns[0...sub_cat_i].join + "**#{$sub_category}**\n\n" + ' - ' + log + "\n\n"
|
264
|
+
File.write($Changelog_file, to_wr + lns[sub_cat_i..].join)
|
265
|
+
else
|
266
|
+
# the sub category exists
|
267
|
+
|
268
|
+
sub_cat_i += main_cat_i+2
|
269
|
+
to_wr = lns[0..sub_cat_i+1].join + ' - ' + log + "\n"
|
270
|
+
File.write($Changelog_file, to_wr + lns[sub_cat_i+2..].join)
|
271
|
+
end
|
272
|
+
|
273
|
+
puts "chlog: Add log to #{category}/#{$sub_category}"
|
274
|
+
return
|
275
|
+
end # end of if $sub_category
|
276
|
+
########################################
|
277
|
+
|
278
|
+
|
279
|
+
|
280
|
+
# situation: no sub category
|
281
|
+
|
282
|
+
to_wr = lns[0..main_cat_i+1].join + '- ' + log + "\n"
|
283
|
+
|
284
|
+
# main category list should be separated with
|
285
|
+
# sub category
|
286
|
+
if lns[main_cat_i+2] =~ /\*\*.*/
|
287
|
+
to_wr += "\n"
|
288
|
+
end
|
289
|
+
File.write($Changelog_file, to_wr + lns[main_cat_i+2..].join)
|
290
|
+
end
|
291
|
+
puts "chlog: Add log to #{category}"
|
292
|
+
end
|
293
|
+
|
294
|
+
|
295
|
+
#
|
296
|
+
# main category order: 1
|
297
|
+
#
|
298
|
+
def add_to_new_features(log)
|
299
|
+
meta_add_to_a_category(log, 1, "New features")
|
300
|
+
end
|
301
|
+
|
302
|
+
#
|
303
|
+
# main category order: 2
|
304
|
+
#
|
305
|
+
def add_to_enhancements(log)
|
306
|
+
meta_add_to_a_category(log, 2, "Enhancements")
|
307
|
+
end
|
308
|
+
|
309
|
+
#
|
310
|
+
# main_category_order: 3
|
311
|
+
#
|
312
|
+
def add_to_bug_fixes(log)
|
313
|
+
meta_add_to_a_category(log, 3, "Bug fixes")
|
314
|
+
end
|
315
|
+
|
316
|
+
#
|
317
|
+
# main_category_order: 4
|
318
|
+
#
|
319
|
+
def add_to_security(log)
|
320
|
+
meta_add_to_a_category(log, 4, "Security")
|
321
|
+
end
|
322
|
+
|
323
|
+
#
|
324
|
+
# main_category_order: 5
|
325
|
+
#
|
326
|
+
def add_to_compatibility(log)
|
327
|
+
meta_add_to_a_category(log, 5, "Compatibility")
|
328
|
+
end
|
329
|
+
|
330
|
+
#
|
331
|
+
# The last of order table
|
332
|
+
# main_category_order: 6
|
333
|
+
#
|
334
|
+
def add_to_deprecations(log)
|
335
|
+
meta_add_to_a_category(log, 6, "Deprecations")
|
336
|
+
end
|
337
|
+
|
338
|
+
|
339
|
+
#
|
340
|
+
# Release a version
|
341
|
+
#
|
342
|
+
def release_new_version(ver)
|
343
|
+
if ver.nil?
|
344
|
+
puts "chlog: No version supplied! "
|
345
|
+
puts " Use chlog -r <version>!",""
|
346
|
+
exit 1
|
347
|
+
end
|
348
|
+
|
349
|
+
content = get_changelog
|
350
|
+
lns = content.lines
|
351
|
+
|
352
|
+
match_unreleased_fail!(lns[2])
|
353
|
+
|
354
|
+
header = <<EOF
|
355
|
+
# Changelog
|
356
|
+
|
357
|
+
## [Unreleased](#) (#$today)
|
358
|
+
|
359
|
+
<br>
|
360
|
+
|
361
|
+
EOF
|
362
|
+
|
363
|
+
new_version = "## [#{ver}](#) (#$today)\n"
|
364
|
+
new_cont = header + new_version + lns[3..].join('')
|
365
|
+
File.write($Changelog_file, new_cont)
|
366
|
+
puts "Release #{ver} in changelog!"
|
367
|
+
end
|
368
|
+
|
369
|
+
|
370
|
+
def add_log_sensitive(log)
|
371
|
+
|
372
|
+
# Be careful the when statements order
|
373
|
+
# Match the case you want first
|
374
|
+
case log
|
375
|
+
when /deprecat/i, /^remove/i, /^not/i then add_to_deprecations(log)
|
376
|
+
when /^new/i, /^add/i, /new feature/i, /^support/i then add_to_new_features(log)
|
377
|
+
when /^fix/i, /repair/i, /bug/i then add_to_bug_fixes(log)
|
378
|
+
when /compatible/i, /compatibility/i then add_to_compatibility(log)
|
379
|
+
when /security/i, /secure/i, /cve/i then add_to_security(log)
|
380
|
+
when /feature/i, /update/i, /problem/i, /issue/i then add_to_enhancements(log)
|
381
|
+
else
|
382
|
+
add_to_enhancements(log)
|
383
|
+
end
|
384
|
+
end
|
385
|
+
|
386
|
+
|
387
|
+
#
|
388
|
+
# reuse git commit log
|
389
|
+
#
|
390
|
+
def add_with_git(first, second)
|
391
|
+
|
392
|
+
main_category = nil
|
393
|
+
|
394
|
+
if first =~ /^-([nebscd])$/
|
395
|
+
main_category = $1
|
396
|
+
elsif first =~ /^--(.*)/
|
397
|
+
$sub_category = $1
|
398
|
+
end
|
399
|
+
|
400
|
+
if second =~ /^-([nebscd])$/
|
401
|
+
main_category = $1
|
402
|
+
elsif second =~ /^--(.*)/
|
403
|
+
$sub_category = $1
|
404
|
+
end
|
405
|
+
|
406
|
+
|
407
|
+
gitlog = `git log --oneline -n 1`
|
408
|
+
log = gitlog.split(' ')
|
409
|
+
log = log[1..].join(' ')
|
410
|
+
puts "last commit: #{log}"
|
411
|
+
|
412
|
+
if $sub_category.nil?
|
413
|
+
puts "What sub category? Input or leave it blank"
|
414
|
+
print '>'
|
415
|
+
sub = STDIN.gets.chomp
|
416
|
+
case sub
|
417
|
+
when ''
|
418
|
+
$sub_category = nil
|
419
|
+
else
|
420
|
+
$sub_category = sub
|
421
|
+
end
|
422
|
+
end
|
423
|
+
|
424
|
+
if main_category.nil?
|
425
|
+
puts "What main category? Input number or leave it blank to auto determine"
|
426
|
+
puts <<~EOC
|
427
|
+
----------------
|
428
|
+
1. New features
|
429
|
+
2. Enhancements
|
430
|
+
3. Bug fixes
|
431
|
+
4. Security
|
432
|
+
5. Compatibility
|
433
|
+
6. Deprecations
|
434
|
+
----------------
|
435
|
+
EOC
|
436
|
+
|
437
|
+
print '>'
|
438
|
+
case STDIN.gets.chomp
|
439
|
+
when '1' then add_to_new_features(log)
|
440
|
+
when '2' then add_to_enhancements(log)
|
441
|
+
when '3' then add_to_bug_fixes(log)
|
442
|
+
when '4' then add_to_security(log)
|
443
|
+
when '5' then add_to_compatibility(log)
|
444
|
+
when '6' then add_to_deprecations(log)
|
445
|
+
else
|
446
|
+
add_log_sensitive(log)
|
447
|
+
end
|
448
|
+
else
|
449
|
+
tbl = {
|
450
|
+
'n' => :add_to_new_features,
|
451
|
+
'e' => :add_to_enhancements,
|
452
|
+
'b' => :add_to_bug_fixes,
|
453
|
+
's' => :add_to_security,
|
454
|
+
'c' => :add_to_compatibility,
|
455
|
+
'd' => :add_to_deprecations
|
456
|
+
}
|
457
|
+
send(tbl[main_category], log)
|
458
|
+
end
|
459
|
+
|
460
|
+
# Auto commit
|
461
|
+
files = `git diff --exit-code --name-only`
|
462
|
+
files = files.split
|
463
|
+
if (files.size == 1) && (files[0] == "CHANGELOG.md")
|
464
|
+
puts "chlog: Able to commit the new Changelog, input y/yes/blank to agree, or others to refuse"
|
465
|
+
print '>'
|
466
|
+
case STDIN.gets.chomp.downcase
|
467
|
+
when '', 'yes', 'y'
|
468
|
+
system("git add #$Changelog_file && git commit -m 'Update the Changelog' ")
|
469
|
+
else
|
470
|
+
"do nothing"
|
471
|
+
end
|
472
|
+
end
|
473
|
+
end
|
474
|
+
|
475
|
+
|
476
|
+
#############
|
477
|
+
# main
|
478
|
+
#############
|
479
|
+
|
480
|
+
if __FILE__ == $0
|
481
|
+
|
482
|
+
if $*.size == 0
|
483
|
+
if File.exists? $Changelog_file
|
484
|
+
puts "chlog: Already exists Changelog (#$Changelog_file)"
|
485
|
+
puts " Use chlog -h to see options"
|
486
|
+
else
|
487
|
+
get_changelog
|
488
|
+
end
|
489
|
+
exit
|
490
|
+
end
|
491
|
+
|
492
|
+
action = $*[0]
|
493
|
+
if $*[1] =~ /--(.*)/
|
494
|
+
puts "-> DEBUG: #$1"
|
495
|
+
$sub_category = $1
|
496
|
+
log = $*[2..].join(' ')
|
497
|
+
else
|
498
|
+
$sub_category = nil
|
499
|
+
log = $*[1..].join(' ')
|
500
|
+
end
|
501
|
+
|
502
|
+
|
503
|
+
case action
|
504
|
+
when "-h", "--help" then help()
|
505
|
+
when "-n" then add_to_new_features(log)
|
506
|
+
when "-e" then add_to_enhancements(log)
|
507
|
+
when "-b" then add_to_bug_fixes(log)
|
508
|
+
when "-s" then add_to_security(log)
|
509
|
+
when "-c" then add_to_compatibility(log)
|
510
|
+
when "-d" then add_to_deprecations(log)
|
511
|
+
when "-r" then release_new_version($*[1])
|
512
|
+
when "-g" then add_with_git($*[1], $*[2])
|
513
|
+
else
|
514
|
+
if action =~ /^-[^-]*$/
|
515
|
+
puts "chlog: Unknown option!"
|
516
|
+
exit 1
|
517
|
+
else
|
518
|
+
if $*[0] =~ /^--(.*)/
|
519
|
+
$sub_category = $1
|
520
|
+
log = $*[1..].join(' ')
|
521
|
+
else
|
522
|
+
$sub_category = nil
|
523
|
+
log = $*[0..].join(' ')
|
524
|
+
end
|
525
|
+
puts "chlog: Auto determine log category"
|
526
|
+
add_log_sensitive(log)
|
527
|
+
end
|
528
|
+
end
|
529
|
+
|
530
|
+
|
531
|
+
# end main
|
532
|
+
end
|
metadata
CHANGED
@@ -1,29 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: chlog
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 1.6.1.alpha
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
-
|
8
|
-
autorequire:
|
9
|
-
bindir:
|
7
|
+
- ccmywish
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
12
|
-
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: highline
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - "~>"
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '2.0'
|
20
|
-
type: :runtime
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - "~>"
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: '2.0'
|
11
|
+
date: 2022-04-09 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
27
13
|
description: 'This command line tool `chlog` helps generate and maintain the Changelog
|
28
14
|
of your projects.
|
29
15
|
|
@@ -34,16 +20,14 @@ executables:
|
|
34
20
|
extensions: []
|
35
21
|
extra_rdoc_files: []
|
36
22
|
files:
|
37
|
-
-
|
38
|
-
- lib/chlog.rb
|
39
|
-
- lib/chlog/version.rb
|
23
|
+
- bin/chlog
|
40
24
|
homepage: https://github.com/ccmywish/chlog
|
41
25
|
licenses:
|
42
26
|
- MIT
|
43
27
|
metadata:
|
44
28
|
bug_tracker_uri: https://github.com/ccmywish/chlog/issues
|
45
29
|
source_code_uri: https://github.com/ccmywish/chlog
|
46
|
-
post_install_message:
|
30
|
+
post_install_message:
|
47
31
|
rdoc_options: []
|
48
32
|
require_paths:
|
49
33
|
- lib
|
@@ -54,12 +38,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
54
38
|
version: '0'
|
55
39
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
56
40
|
requirements:
|
57
|
-
- - "
|
41
|
+
- - ">"
|
58
42
|
- !ruby/object:Gem::Version
|
59
|
-
version:
|
43
|
+
version: 1.3.1
|
60
44
|
requirements: []
|
61
|
-
rubygems_version: 3.
|
62
|
-
signing_key:
|
45
|
+
rubygems_version: 3.3.7
|
46
|
+
signing_key:
|
63
47
|
specification_version: 4
|
64
|
-
summary:
|
48
|
+
summary: 'chlog: help maintain Changelog'
|
65
49
|
test_files: []
|
data/exe/chlog
DELETED
@@ -1,82 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# ------------------------------------------------------
|
3
|
-
# File : chlog.rb
|
4
|
-
# Authors : Aoran Zeng <ccmywish@qq.com>
|
5
|
-
# Created on : <2022-03-18>
|
6
|
-
# Last modified : <2023-05-09>
|
7
|
-
#
|
8
|
-
# chlog:
|
9
|
-
#
|
10
|
-
# Maintain your project's Changelog on the cli.
|
11
|
-
# ------------------------------------------------------
|
12
|
-
|
13
|
-
require 'chlog'
|
14
|
-
|
15
|
-
module Chlog::CLI
|
16
|
-
|
17
|
-
def self.run
|
18
|
-
|
19
|
-
args = $*.dup
|
20
|
-
|
21
|
-
if args.size == 0
|
22
|
-
help or exit
|
23
|
-
end
|
24
|
-
|
25
|
-
action = args[0]
|
26
|
-
|
27
|
-
case action
|
28
|
-
when "-h", "--help" then help or exit end
|
29
|
-
|
30
|
-
logger = Chlog::Logger.new
|
31
|
-
|
32
|
-
case action
|
33
|
-
when "-g" then exit logger.generate_changelog
|
34
|
-
when "-r" then exit logger.release_new_version(args[1])
|
35
|
-
end
|
36
|
-
|
37
|
-
if args[1] =~ /^--(.*)/
|
38
|
-
logger.sub_category = $1
|
39
|
-
logger.log = args[2..].join(' ')
|
40
|
-
else
|
41
|
-
logger.sub_category = nil
|
42
|
-
logger.log = args[1..].join(' ')
|
43
|
-
end
|
44
|
-
|
45
|
-
case action
|
46
|
-
when /-[nebscd]/
|
47
|
-
logger.take_action(action)
|
48
|
-
else
|
49
|
-
# action =~ /^-[^-]*$/
|
50
|
-
abort "chlog: Unknown option!"
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
|
55
|
-
def self.help
|
56
|
-
puts <<~EOH
|
57
|
-
chlog (v#{Chlog::GEM_VERSION}): Help maintain the Changelog of your projects
|
58
|
-
|
59
|
-
Usage:
|
60
|
-
|
61
|
-
chlog -g Generate CHANGELOG.md in git root
|
62
|
-
chlog -r <3.14> Release version to v3.14
|
63
|
-
|
64
|
-
Add log:
|
65
|
-
|
66
|
-
chlog <-main category> [--sub category] <log>
|
67
|
-
|
68
|
-
Main Category:
|
69
|
-
|
70
|
-
-n Add log to New features
|
71
|
-
-e Add log to Enhancements
|
72
|
-
-b Add log to Bug fixes
|
73
|
-
-s Add log to Security
|
74
|
-
-c Add log to Compatibility
|
75
|
-
-d Add log to Deprecations
|
76
|
-
|
77
|
-
EOH
|
78
|
-
end
|
79
|
-
|
80
|
-
end
|
81
|
-
|
82
|
-
Chlog::CLI.run
|
data/lib/chlog/version.rb
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
# ---------------------------------------------------------------
|
2
|
-
# File : version.rb
|
3
|
-
# Authors : Aoran Zeng <ccmywish@qq.com>
|
4
|
-
# Created on : <2023-05-09>
|
5
|
-
# Last modified : <2023-05-09>
|
6
|
-
#
|
7
|
-
# version:
|
8
|
-
#
|
9
|
-
# Lib version
|
10
|
-
# ---------------------------------------------------------------
|
11
|
-
|
12
|
-
module Chlog
|
13
|
-
|
14
|
-
GEM_VERSION = "0.9.0"
|
15
|
-
|
16
|
-
end
|
data/lib/chlog.rb
DELETED
@@ -1,417 +0,0 @@
|
|
1
|
-
# ------------------------------------------------------
|
2
|
-
# File : chlog.rb
|
3
|
-
# Authors : Aoran Zeng <ccmywish@qq.com>
|
4
|
-
# Created on : <2022-04-15>
|
5
|
-
# Last modified : <2023-05-09>
|
6
|
-
#
|
7
|
-
# chlog:
|
8
|
-
#
|
9
|
-
# Maintain your project's Changelog on the cli.
|
10
|
-
# ------------------------------------------------------
|
11
|
-
|
12
|
-
require_relative 'chlog/version'
|
13
|
-
|
14
|
-
class Chlog::Logger
|
15
|
-
|
16
|
-
attr_accessor :sub_category, # 存储次标题
|
17
|
-
:log, # 存储log
|
18
|
-
:highline # HighLine 实例
|
19
|
-
:changelog # CHANGELOG.md 位置
|
20
|
-
|
21
|
-
|
22
|
-
def initialize
|
23
|
-
require 'highline'
|
24
|
-
@highline = HighLine.new
|
25
|
-
|
26
|
-
require 'open3'
|
27
|
-
# Prevent current directory is not git directory
|
28
|
-
Open3.popen3("git rev-parse --show-toplevel") do |i, o, err, t|
|
29
|
-
if err.read.include?("fatal: not a git repository")
|
30
|
-
puts "chlog: Not a git directory!" or exit(false)
|
31
|
-
else
|
32
|
-
@changelog = `git rev-parse --show-toplevel`.chomp + '/CHANGELOG.md'
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
require 'date'
|
38
|
-
TODAY = Date.today.to_s
|
39
|
-
|
40
|
-
UNRELEASED_TITLE = "## [Unreleased](#) (#{TODAY})"
|
41
|
-
|
42
|
-
TEMPLATE = <<~EOT
|
43
|
-
# Changelog
|
44
|
-
|
45
|
-
#{UNRELEASED_TITLE}
|
46
|
-
|
47
|
-
<br>
|
48
|
-
|
49
|
-
## [Initialize](#) (#{TODAY})
|
50
|
-
|
51
|
-
<br>
|
52
|
-
|
53
|
-
<hr>
|
54
|
-
|
55
|
-
This Changelog is maintained with [chlog](https://github.com/ccmywish/chlog)
|
56
|
-
|
57
|
-
EOT
|
58
|
-
|
59
|
-
|
60
|
-
def generate_changelog
|
61
|
-
file = @changelog
|
62
|
-
if File.exist? file
|
63
|
-
puts "chlog: Already exists Changelog (#@changelog)" or return false
|
64
|
-
else
|
65
|
-
File.write(file, TEMPLATE)
|
66
|
-
puts "chlog: Generate #@changelog OK!" or return true
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
|
71
|
-
def get_changelog
|
72
|
-
file = @changelog
|
73
|
-
if File.exist? file
|
74
|
-
return File.read file
|
75
|
-
else
|
76
|
-
abort "chlog: No Changelog exists, use 'chlog -g' to generate!"
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
end
|
81
|
-
|
82
|
-
|
83
|
-
class Chlog::Logger
|
84
|
-
|
85
|
-
def match_unreleased?(str)
|
86
|
-
str =~ /^## \[Unreleased\]\(.*\) \(\d{4}-\d\d-\d\d\)/
|
87
|
-
end
|
88
|
-
|
89
|
-
def match_unreleased_fail!(str)
|
90
|
-
unless match_unreleased?(str)
|
91
|
-
puts "chlog: Unmatched format with chlog"
|
92
|
-
puts
|
93
|
-
# "#{lns[1][1..]}"
|
94
|
-
abort "Unreleased version must be the third line"
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
def match_new_features?(str)
|
99
|
-
str =~ /^### New features:/
|
100
|
-
end
|
101
|
-
|
102
|
-
def match_enhancements?(str)
|
103
|
-
str =~ /^### Enhancements:/
|
104
|
-
end
|
105
|
-
|
106
|
-
def match_bug_fixes?(str)
|
107
|
-
str =~ /^### Bug fixes:/
|
108
|
-
end
|
109
|
-
|
110
|
-
def match_security?(str)
|
111
|
-
str =~ /^### Security:/
|
112
|
-
end
|
113
|
-
|
114
|
-
def match_compatibility?(str)
|
115
|
-
str =~ /^### Compatibility:/
|
116
|
-
end
|
117
|
-
|
118
|
-
def match_deprecations?(str)
|
119
|
-
str =~ /^### Deprecations:/
|
120
|
-
end
|
121
|
-
|
122
|
-
|
123
|
-
def next_version_index(lns_array)
|
124
|
-
nvi = lns_array[3..].each_with_index {break _2 if _1.start_with?("## [") }
|
125
|
-
nvi += 3
|
126
|
-
end
|
127
|
-
|
128
|
-
def next_category_index(lns_array)
|
129
|
-
nci = lns_array[3...nvi].each_with_index {break _2 if _1.start_with?("### ") }
|
130
|
-
|
131
|
-
# The not match return value is not nil!! But an array!!
|
132
|
-
if nci.is_a(Integer) then nci += 3
|
133
|
-
else nil end
|
134
|
-
end
|
135
|
-
|
136
|
-
=begin
|
137
|
-
### New features:
|
138
|
-
|
139
|
-
- xaaaaa
|
140
|
-
- xbbbbb
|
141
|
-
- xccccc [-> this]
|
142
|
-
=end
|
143
|
-
def find_main_category_last_list_item_index(lns,
|
144
|
-
main_cat_index,
|
145
|
-
first_lower_order_category_index)
|
146
|
-
mci = main_cat_index
|
147
|
-
nci = first_lower_order_category_index
|
148
|
-
|
149
|
-
list_i = lns[mci+2..nci].each_with_index do
|
150
|
-
break _2 if _1 !~ /^- .*/
|
151
|
-
end
|
152
|
-
list_i += mci+2 - 1
|
153
|
-
end
|
154
|
-
|
155
|
-
|
156
|
-
LIST__Feature = %w[
|
157
|
-
new_features enhancements bug_fixes
|
158
|
-
security compatibility deprecations
|
159
|
-
]
|
160
|
-
|
161
|
-
# New features
|
162
|
-
# Enhancements
|
163
|
-
# Bug fixes
|
164
|
-
# Security
|
165
|
-
# Compatibility
|
166
|
-
# Deprecations
|
167
|
-
LIST__Main_Category = LIST__Feature.map do
|
168
|
-
_1.split('_').join(' ').capitalize
|
169
|
-
end
|
170
|
-
|
171
|
-
# match_new_features?
|
172
|
-
# match_enhancements?
|
173
|
-
# match_ ...
|
174
|
-
LIST__Match_Method = LIST__Feature.map do
|
175
|
-
('match_' + _1 + '?').to_sym
|
176
|
-
end
|
177
|
-
|
178
|
-
=begin
|
179
|
-
{
|
180
|
-
1 => :add_to_new_features,
|
181
|
-
2 => :add_to_enhancements,
|
182
|
-
...
|
183
|
-
}
|
184
|
-
=end
|
185
|
-
HASH__Order_To_AddTo_Method = ([1,2,3,4,5,6].zip LIST__Feature.map {|m| ('add_to_' + m).to_sym }).to_h
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
def take_action(action)
|
190
|
-
options = "nebscd"
|
191
|
-
|
192
|
-
=begin
|
193
|
-
{
|
194
|
-
"-n" => "new_features", "-e" => "enhancements", "-b" => "bug_fixes",
|
195
|
-
"-s" => "security", "-c" => "compatibility", "-d" => "deprecations"
|
196
|
-
}
|
197
|
-
=end
|
198
|
-
action_table = options.chars.map do |op|
|
199
|
-
'-' + op
|
200
|
-
end.zip(LIST__Feature).to_h
|
201
|
-
|
202
|
-
public_send "add_to_#{action_table[action]}"
|
203
|
-
end
|
204
|
-
|
205
|
-
|
206
|
-
def first_lower_order_category_index(lns_array, category_order)
|
207
|
-
|
208
|
-
o = category_order
|
209
|
-
|
210
|
-
nvi = next_version_index(lns_array)
|
211
|
-
|
212
|
-
while o < LIST__Match_Method.size
|
213
|
-
lns_array[0...nvi].each_with_index do
|
214
|
-
return _2 if send(LIST__Match_Method[o], _1)
|
215
|
-
end
|
216
|
-
o += 1
|
217
|
-
end
|
218
|
-
|
219
|
-
# Next version above
|
220
|
-
return (nvi - 2)
|
221
|
-
end
|
222
|
-
|
223
|
-
|
224
|
-
# A meta function: do the real work other 6 functions delegate
|
225
|
-
#
|
226
|
-
# This function detect the main category, and then handle the
|
227
|
-
# sub category.
|
228
|
-
def meta_add_to_a_category(log, main_category_order, category)
|
229
|
-
|
230
|
-
content = get_changelog
|
231
|
-
lns = content.lines
|
232
|
-
|
233
|
-
match_unreleased_fail!(lns[2])
|
234
|
-
|
235
|
-
nvi = next_version_index(lns)
|
236
|
-
# To find the existing category line
|
237
|
-
main_cat_i = lns[0...nvi].each_with_index do
|
238
|
-
# Adjust to index of the order table
|
239
|
-
break _2 if send(LIST__Match_Method[main_category_order-1], _1)
|
240
|
-
end
|
241
|
-
|
242
|
-
#
|
243
|
-
# Always update to latest time when making a log
|
244
|
-
#
|
245
|
-
# We must add a "\n" because every element of the array
|
246
|
-
# is a sentence with a trailing newline, then they can
|
247
|
-
# be 'joined' to a working long string
|
248
|
-
#
|
249
|
-
lns[2] = UNRELEASED_TITLE + "\n"
|
250
|
-
|
251
|
-
f_l_o_c_i = first_lower_order_category_index(lns, main_category_order)
|
252
|
-
|
253
|
-
if main_cat_i.class != Integer
|
254
|
-
################################################################################
|
255
|
-
# The main category not exists
|
256
|
-
################################################################################
|
257
|
-
|
258
|
-
|
259
|
-
########################################
|
260
|
-
if @sub_category
|
261
|
-
|
262
|
-
# Because the main category not exists,
|
263
|
-
# nor does the sub category
|
264
|
-
#
|
265
|
-
sub_cat_i = f_l_o_c_i
|
266
|
-
to_wr = lns[0...sub_cat_i].join + "### #{category}:\n\n" + "**#{@sub_category}**\n\n" + ' - ' + log + "\n\n"
|
267
|
-
File.write(@changelog, to_wr + lns[sub_cat_i..].join)
|
268
|
-
|
269
|
-
puts "chlog: Add log to #{category}/#{@sub_category}"
|
270
|
-
return
|
271
|
-
end # end of if @sub_category
|
272
|
-
########################################
|
273
|
-
|
274
|
-
# situation: no sub category
|
275
|
-
|
276
|
-
# Not need adjust to the index of the order table
|
277
|
-
log_loc = f_l_o_c_i
|
278
|
-
puts "chlog: Add '#{category}' category"
|
279
|
-
to_wr = lns[0...(log_loc)].join + "### #{category}:\n\n" + '- ' + log + "\n"
|
280
|
-
File.write(@changelog, to_wr + lns[log_loc-1..].join)
|
281
|
-
|
282
|
-
else
|
283
|
-
################################################################################
|
284
|
-
# The main category exists
|
285
|
-
################################################################################
|
286
|
-
|
287
|
-
|
288
|
-
########################################
|
289
|
-
if @sub_category
|
290
|
-
|
291
|
-
# from first list item to next main cat
|
292
|
-
# search if sub cat already exists
|
293
|
-
sub_cat_i = lns[main_cat_i+2...f_l_o_c_i].each_with_index do
|
294
|
-
break _2 if _1 =~ /^\*\*#{@sub_category}\*\*/
|
295
|
-
end
|
296
|
-
|
297
|
-
if !sub_cat_i.is_a?(Integer)
|
298
|
-
# the sub category not exists
|
299
|
-
|
300
|
-
sub_cat_i = 2 + find_main_category_last_list_item_index(lns,main_cat_i,f_l_o_c_i)
|
301
|
-
to_wr = lns[0...sub_cat_i].join + "**#{@sub_category}**\n\n" + ' - ' + log + "\n\n"
|
302
|
-
File.write(@changelog, to_wr + lns[sub_cat_i..].join)
|
303
|
-
else
|
304
|
-
# the sub category exists
|
305
|
-
|
306
|
-
sub_cat_i += main_cat_i+2
|
307
|
-
to_wr = lns[0..sub_cat_i+1].join + ' - ' + log + "\n"
|
308
|
-
File.write(@changelog, to_wr + lns[sub_cat_i+2..].join)
|
309
|
-
end
|
310
|
-
|
311
|
-
puts "chlog: Add log to #{category}/#{@sub_category}"
|
312
|
-
return
|
313
|
-
end # end of if @sub_category
|
314
|
-
########################################
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
# situation: no sub category
|
319
|
-
|
320
|
-
to_wr = lns[0..main_cat_i+1].join + '- ' + log + "\n"
|
321
|
-
|
322
|
-
# main category list should be separated with
|
323
|
-
# sub category
|
324
|
-
if lns[main_cat_i+2] =~ /\*\*.*/
|
325
|
-
to_wr += "\n"
|
326
|
-
end
|
327
|
-
File.write(@changelog, to_wr + lns[main_cat_i+2..].join)
|
328
|
-
end
|
329
|
-
|
330
|
-
puts "chlog: Add log to #{category}"
|
331
|
-
end
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
# main category order: 1
|
336
|
-
def add_to_new_features
|
337
|
-
meta_add_to_a_category(@log, 1, "New features")
|
338
|
-
end
|
339
|
-
|
340
|
-
# main category order: 2
|
341
|
-
def add_to_enhancements
|
342
|
-
meta_add_to_a_category(@log, 2, "Enhancements")
|
343
|
-
end
|
344
|
-
|
345
|
-
# main_category_order: 3
|
346
|
-
def add_to_bug_fixes
|
347
|
-
meta_add_to_a_category(@log, 3, "Bug fixes")
|
348
|
-
end
|
349
|
-
|
350
|
-
# main_category_order: 4
|
351
|
-
def add_to_security
|
352
|
-
meta_add_to_a_category(@log, 4, "Security")
|
353
|
-
end
|
354
|
-
|
355
|
-
# main_category_order: 5
|
356
|
-
def add_to_compatibility
|
357
|
-
meta_add_to_a_category(@log, 5, "Compatibility")
|
358
|
-
end
|
359
|
-
|
360
|
-
# The last of order table
|
361
|
-
# main_category_order: 6
|
362
|
-
def add_to_deprecations
|
363
|
-
meta_add_to_a_category(@log, 6, "Deprecations")
|
364
|
-
end
|
365
|
-
|
366
|
-
# Release a version
|
367
|
-
def release_new_version(ver)
|
368
|
-
if ver.nil?
|
369
|
-
puts "chlog: No version supplied!"; puts; abort "Use chlog -r <version>!"
|
370
|
-
end
|
371
|
-
|
372
|
-
if !ver.downcase.start_with?('v') and ver[0].match? /\d/
|
373
|
-
ver = 'v' + ver
|
374
|
-
end
|
375
|
-
|
376
|
-
content = get_changelog
|
377
|
-
lns = content.lines
|
378
|
-
|
379
|
-
match_unreleased_fail!(lns[2])
|
380
|
-
|
381
|
-
header = <<~EOF
|
382
|
-
# Changelog
|
383
|
-
|
384
|
-
## [Unreleased](#) (#{TODAY})
|
385
|
-
|
386
|
-
<br>
|
387
|
-
|
388
|
-
EOF
|
389
|
-
|
390
|
-
new_version = "## [#{ver}](#) (#{TODAY})\n"
|
391
|
-
new_cont = header + new_version + lns[3..].join('')
|
392
|
-
File.write(@changelog, new_cont)
|
393
|
-
puts "chlog: Release #{ver} in Changelog!" or return true
|
394
|
-
end
|
395
|
-
|
396
|
-
|
397
|
-
# Help user interactively
|
398
|
-
def ask_user_category
|
399
|
-
category = @highline.choose do |menu|
|
400
|
-
menu.index_color = :rgb_77bbff
|
401
|
-
menu.prompt = "What main category?"
|
402
|
-
# return number!!! not string!!!
|
403
|
-
menu.choices(*LIST__Main_Category)
|
404
|
-
end
|
405
|
-
|
406
|
-
option = LIST__Main_Category.index(category)
|
407
|
-
|
408
|
-
if @sub_category.nil?
|
409
|
-
sub = @highline.ask "What sub category? [NIL/sub]"
|
410
|
-
case sub
|
411
|
-
when '' then @sub_category = nil
|
412
|
-
else @sub_category = sub end
|
413
|
-
end
|
414
|
-
return option
|
415
|
-
end
|
416
|
-
|
417
|
-
end
|