-
Notifications
You must be signed in to change notification settings - Fork 650
/
bump.rb
executable file
·138 lines (106 loc) · 3.08 KB
/
bump.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#!/usr/bin/env ruby
require 'date'
Dir.chdir(File.dirname(__FILE__))
NEWS_HEADER_REGEX = /^(\d+)\.(\d+)\.(\d+) \(\d{4}-\d{2}-\d{2}\)$\n-+/
PARTS = ['major', 'minor', 'patch'].freeze
NEWS_HEADER = <<-NEWS
Development
-----------
### NOTICES
- None yet
### Features
- None yet
### Bug fixes / enhancements
- None yet
NEWS
class Version < Array
def initialize(parts)
raise "Expected three version parts" unless parts.count == 3
super(parts.map(&:to_i))
end
def bump(pos)
self[pos] += 1
(pos + 1..2).each { |p| self[p] = 0 }
end
def to_s
join('.')
end
end
def version_from_tag(tag)
m = tag.match(/^v(\d+)\.(\d+)\.(\d+)$/)
raise "Could not parse tag #{tag}" unless m
Version.new(m[1..3])
end
def version_from_news(news)
m = news.match(NEWS_HEADER_REGEX)
raise "Could not find NEWS version" unless m
Version.new(m[1..3])
end
def updated_news(news, next_version)
NEWS_HEADER + tag_header(next_version) + clean_development(news)
end
def tag_header(next_version)
h = "#{next_version} (#{Date.today})"
h + "\n#{'-' * h.length}\n\n"
end
def clean_development(news)
development, header, rest = news.partition(NEWS_HEADER_REGEX)
development_lines = development.split("\n")
development_lines.delete('Development')
development_lines.delete('-----------')
# Write non-empty sections
news_sections(development_lines).map { |name, lines|
if name && lines.any? { |l| !l.strip.empty? }
"### #{name}\n#{lines.join("\n")}\n"
end
}.compact.join('') + "\n#{header}#{rest}"
end
def news_sections(lines)
sections = []
section_lines = []
section_name = nil
lines.each do |line|
if line.start_with?('###')
if section_name
sections << [section_name, section_lines]
end
section_lines = []
section_name = line[4..-1]
elsif line != '- None yet'
# Replace initial `-` for `*`
section_lines << line.sub(/^(\s*)-/, '\1*')
end
end
sections << [section_name, section_lines] if section_name
sections
end
def help
puts 'Usage: '
puts ' bump.rb [ major | minor | patch ] (defaults to `patch`)'
exit(1)
end
ARGV << 'patch' if ARGV.empty?
help unless ARGV.count == 1
# raise 'Not in master branch' unless `git rev-parse --abbrev-ref HEAD`.strip == 'master'
puts 'Pulling and fetching tags...'
`git pull --tags`
news_content = File.read('NEWS.md')
puts 'Calculating current version...'
tag_version = version_from_tag(`git describe --abbrev=0`)
news_version = version_from_news(news_content)
unless tag_version == news_version
raise "Mismatched versions between git tag (#{tag_version}) and NEWS (#{news_version})"
end
part = PARTS.index(ARGV[0])
help unless part
next_version = tag_version.dup
next_version.bump(part)
puts "Bumping from #{tag_version} to #{next_version}. Enter to confirm, Ctrl+C to cancel"
STDIN.getc
puts 'Updating NEWS...'
File.write('NEWS.md', updated_news(news_content, next_version))
puts 'Committing, tagging and pushing...'
`git add NEWS.md`
`git commit -m "Bump to #{next_version}"`
`git tag -a v#{next_version} -m "Version #{next_version}"`
# `git push origin master --follow-tags`