git-bump 1.0.0
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.
- checksums.yaml +7 -0
- data/bin/git-bump +7 -0
- data/lib/git_bump.rb +257 -0
- metadata +90 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: b5a25a12af0749f43938f0f73f72058606826ccb
|
4
|
+
data.tar.gz: 3e33b5cc7c489af869f1f9948658fd8678252cc3
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5d6c775156eb71ab824bd7a2185359cfaf4d84555a921fa7d1e21b1182b5a281bea751e465925d3690573a854bf45222de30ca6f22db1e7018cdeb5d9343e906
|
7
|
+
data.tar.gz: 0e1968dd66dfab8357336e102977e3d3f697d4915f3bb38d207098b0c684e9135d254ad6054cbd42b1d6156540c2b648c599ba53f1c6c0a44b07d293c8868b47
|
data/bin/git-bump
ADDED
data/lib/git_bump.rb
ADDED
@@ -0,0 +1,257 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'thor'
|
4
|
+
|
5
|
+
class GitBump < Thor
|
6
|
+
|
7
|
+
INITIAL = <<-EOS
|
8
|
+
Looks like this is your first release. Please add the version number to the
|
9
|
+
work tree (e.g., in your Makefile), stage your changes, and run git bump again.
|
10
|
+
|
11
|
+
If this isn't your first release, tag your most recent prior release so that
|
12
|
+
git bump can find it:
|
13
|
+
|
14
|
+
git tag -s v1.2.3 8675309
|
15
|
+
EOS
|
16
|
+
|
17
|
+
def self.start
|
18
|
+
ARGV.unshift('release') if ARGV.first =~ /^v?\d/ || %w(major minor point).include?(ARGV.first)
|
19
|
+
super
|
20
|
+
end
|
21
|
+
|
22
|
+
class Release
|
23
|
+
attr_reader :tag, :sha1, :name, :version
|
24
|
+
|
25
|
+
def initialize(tag, sha1, name, version)
|
26
|
+
@tag, @sha1, @name, @version = tag, sha1, name, Version.new(version)
|
27
|
+
end
|
28
|
+
|
29
|
+
def body
|
30
|
+
@body ||= %x{git log -1 --pretty=format:%b #{sha1}}
|
31
|
+
end
|
32
|
+
|
33
|
+
def format
|
34
|
+
body[/(?:\n |.)*/].sub(/\A([-* ]*)(.*?)(\.?)\z/m, '\1%s\3') unless body.empty?
|
35
|
+
end
|
36
|
+
|
37
|
+
def inverse_diff(context = 1)
|
38
|
+
unless defined?(@inverse_diff)
|
39
|
+
@inverse_diff =
|
40
|
+
if !%x{git rev-parse --verify -q #{sha1}^}.empty?
|
41
|
+
%x{git diff -U#{context} #{sha1}..#{sha1}^}
|
42
|
+
end
|
43
|
+
end
|
44
|
+
@inverse_diff
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
class Version
|
50
|
+
def initialize(string)
|
51
|
+
@components = string.split('.')
|
52
|
+
end
|
53
|
+
|
54
|
+
def to_s
|
55
|
+
@components.join('.')
|
56
|
+
end
|
57
|
+
|
58
|
+
def to_a
|
59
|
+
@components.dup
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
no_tasks do
|
64
|
+
def releases
|
65
|
+
@releases ||=
|
66
|
+
begin
|
67
|
+
out = %x{git for-each-ref "refs/tags/v[0-9]*" --sort="*committerdate" --format="%(refname:short) %(*objectname) %(subject)"}
|
68
|
+
exit 1 unless $?.success?
|
69
|
+
out.scan(/^(\S+) (\w+) (.*) (\d\S*)\s*$/).map do |args|
|
70
|
+
Release.new(*args)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def latest
|
76
|
+
@latest ||= releases.reverse.detect do |release|
|
77
|
+
%x{git merge-base #{release.sha1} HEAD}.chomp == release.sha1
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def increment(pos, components)
|
82
|
+
components[pos].sub!(/^(\d+).*/, '\1')
|
83
|
+
components[pos].succ!
|
84
|
+
(components.size-1).downto(pos+1) do |i|
|
85
|
+
if components[i] =~ /^\d/
|
86
|
+
components[i] = '0'
|
87
|
+
else
|
88
|
+
components.delete_at(i)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def generate_version(request)
|
94
|
+
if request =~ /^v?(\d.*)/
|
95
|
+
$1
|
96
|
+
elsif latest
|
97
|
+
components = latest.version.to_s.split('.')
|
98
|
+
case request
|
99
|
+
when 'major' then increment(0, components)
|
100
|
+
when 'minor' then increment(1, components)
|
101
|
+
when 'point' then increment(2, components)
|
102
|
+
when nil then components.last.succ!
|
103
|
+
else
|
104
|
+
abort "Unrecognized version increment #{request}."
|
105
|
+
end
|
106
|
+
components.join('.')
|
107
|
+
else
|
108
|
+
abort "Appears to be initial release. Version number required."
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def name
|
113
|
+
if latest
|
114
|
+
latest.name
|
115
|
+
else
|
116
|
+
File.basename(Dir.getwd)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def patch(version, force = false)
|
121
|
+
diff = latest.inverse_diff(force ? 0 : 1)
|
122
|
+
return unless diff
|
123
|
+
deletion = /^-(.*)(#{Regexp.escape(latest.version.to_s)})(.*)\n/
|
124
|
+
patch = diff.gsub(/#{deletion}\+\1(.*)\3\n/) do
|
125
|
+
"-#$1#$2#$3\n+#$1#{version}#$3\n"
|
126
|
+
end.gsub(/^(@@ -\d+,\d+ \+\d+,)(\d+) @@\n( .*\n)?#{deletion}(?![+-])/) do
|
127
|
+
"#$1#{$2.succ} @@\n#$3-#$4#$5#$6\n+#$4#{version}#$6\n "
|
128
|
+
end.scan(/^[d@].*\n(?:[^d@].*\n)+/).reject do |v|
|
129
|
+
v[0] == ?@ && !v.include?(version)
|
130
|
+
end.join.gsub(/^diff.*\n([^+-].*\n)*---.*\n\+\+\+.*\n(\Z|diff)/, '\1')
|
131
|
+
patch unless patch =~ /\Aindex.*\Z/
|
132
|
+
end
|
133
|
+
|
134
|
+
def logs
|
135
|
+
if (releases.size < 2 || latest.format) && !@logs
|
136
|
+
@logs = %x{git log --no-merges --reverse --pretty=format:"#{latest.format || '* %s.'}" #{latest.sha1}..}
|
137
|
+
abort unless $?.success?
|
138
|
+
end
|
139
|
+
@logs
|
140
|
+
end
|
141
|
+
|
142
|
+
def tag!(name)
|
143
|
+
subject = %x{git log -1 --pretty=format:%s}.chomp
|
144
|
+
system!('git', 'tag', '-f', '-s', name, '-m', subject)
|
145
|
+
puts <<-EOS
|
146
|
+
Successfully created #{name}. If you made a mistake, use `git bump redo` to
|
147
|
+
try again. Once you are satisfied with the result, run
|
148
|
+
|
149
|
+
git push origin master #{name}
|
150
|
+
EOS
|
151
|
+
end
|
152
|
+
|
153
|
+
def system!(*args)
|
154
|
+
system(*args)
|
155
|
+
abort "Error running Git." unless $?.success?
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
def self.basename
|
160
|
+
'git bump'
|
161
|
+
end
|
162
|
+
|
163
|
+
default_task 'release'
|
164
|
+
desc '[version]', 'Create and tag a release for the given version'
|
165
|
+
method_options %w(force -f) => :boolean
|
166
|
+
def release(request=nil)
|
167
|
+
version = generate_version(request)
|
168
|
+
unless %x{git rev-parse --verify -q v#{version}}.empty? || options[:force]
|
169
|
+
abort "Tag already exists. If it hasn't been pushed yet, use --force to override."
|
170
|
+
end
|
171
|
+
initial_commit = %x{git rev-parse --verify -q HEAD}.empty?
|
172
|
+
if !initial_commit && %x{git diff HEAD}.empty?
|
173
|
+
abort INITIAL unless latest
|
174
|
+
failure = "Couldn't patch. Update the version number in the work tree and try again."
|
175
|
+
abort failure unless patch = patch(version, options[:force])
|
176
|
+
IO.popen(['git', 'apply', '--unidiff-zero', '--index'], 'w') do |o|
|
177
|
+
o.write patch
|
178
|
+
end
|
179
|
+
abort failure unless $?.success?
|
180
|
+
hard = true
|
181
|
+
elsif %x{git diff --cached}.empty?
|
182
|
+
# TODO: what happens on initial with some unstaged changes?
|
183
|
+
abort "Discard or stage your changes."
|
184
|
+
end
|
185
|
+
require 'tempfile'
|
186
|
+
Tempfile.open('git-commit') do |f|
|
187
|
+
f.puts [name, version].join(' ')
|
188
|
+
f.puts
|
189
|
+
f.write logs if latest
|
190
|
+
f.flush
|
191
|
+
system('git', 'commit', '--file', f.path, '--edit', * initial_commit ? [] : ['--verbose'])
|
192
|
+
unless $?.success?
|
193
|
+
system('git', 'reset', '-q', '--hard', 'HEAD') if hard
|
194
|
+
abort
|
195
|
+
end
|
196
|
+
end
|
197
|
+
tag!("v#{version}")
|
198
|
+
end
|
199
|
+
|
200
|
+
desc 'redo', 'amend the previous release and retag'
|
201
|
+
method_options %w(force -f) => :boolean
|
202
|
+
def redo
|
203
|
+
unless %x{git diff}.empty?
|
204
|
+
abort "Discard or stage your changes."
|
205
|
+
end
|
206
|
+
unless latest.sha1 == %x{git rev-parse HEAD}.chomp
|
207
|
+
abort "Can only amend the top-most commit."
|
208
|
+
end
|
209
|
+
system!('git', 'commit', '--amend', '--verbose', '--reset-author')
|
210
|
+
tag!(latest.tag)
|
211
|
+
end
|
212
|
+
|
213
|
+
desc 'log', 'Show the git log since the last release'
|
214
|
+
def log(*args)
|
215
|
+
if latest
|
216
|
+
exec('git', 'log', "#{latest.sha1}..", *args)
|
217
|
+
else
|
218
|
+
exec('git', 'log', *args)
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
desc 'show [version]', 'Show the most recent or given release'
|
223
|
+
method_options :version_only => :boolean
|
224
|
+
def show(version = latest ? latest.version.to_s : nil)
|
225
|
+
release = releases.detect do |r|
|
226
|
+
r.version.to_s == version || r.tag == version
|
227
|
+
end
|
228
|
+
if release
|
229
|
+
if options[:version_only]
|
230
|
+
puts release.version
|
231
|
+
else
|
232
|
+
exec('git', 'log', '-1', '--pretty=format:%B', release.sha1)
|
233
|
+
end
|
234
|
+
else
|
235
|
+
exit 1
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
desc 'next', 'Show the version number that would be released'
|
240
|
+
def next(specifier = nil)
|
241
|
+
puts generate_version(specifier)
|
242
|
+
end
|
243
|
+
|
244
|
+
def self.help(shell, *)
|
245
|
+
super
|
246
|
+
shell.say <<-EOS
|
247
|
+
With no arguments, git bump defaults to creating a release with the least
|
248
|
+
significant component of the version number incremented. For example,
|
249
|
+
1.2.3-rc4 becomes 1.2.3-rc5, while 6.7 becomes 6.8. To override, provide a
|
250
|
+
version number argument, or one of the following keywords:
|
251
|
+
|
252
|
+
major: bump the most significant component
|
253
|
+
minor: bump the second most significant component
|
254
|
+
point: bump the third most significant component
|
255
|
+
EOS
|
256
|
+
end
|
257
|
+
end
|
metadata
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: git-bump
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Tim Pope
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-04-24 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.3'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: thor
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: Git based release management
|
56
|
+
email:
|
57
|
+
- code@tpope.net
|
58
|
+
executables:
|
59
|
+
- git-bump
|
60
|
+
extensions: []
|
61
|
+
extra_rdoc_files: []
|
62
|
+
files:
|
63
|
+
- bin/git-bump
|
64
|
+
- lib/git_bump.rb
|
65
|
+
homepage: https://tpo.pe/git-bump
|
66
|
+
licenses:
|
67
|
+
- MIT
|
68
|
+
metadata: {}
|
69
|
+
post_install_message:
|
70
|
+
rdoc_options: []
|
71
|
+
require_paths:
|
72
|
+
- lib
|
73
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
requirements: []
|
84
|
+
rubyforge_project:
|
85
|
+
rubygems_version: 2.0.3
|
86
|
+
signing_key:
|
87
|
+
specification_version: 4
|
88
|
+
summary: Create Git release commits and tags with changelogs
|
89
|
+
test_files: []
|
90
|
+
has_rdoc:
|