git-version-bump 0.1.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.
- data/.gitignore +2 -0
- data/Gemfile +3 -0
- data/README.md +82 -0
- data/Rakefile +21 -0
- data/git-version-bump.gemspec +21 -0
- data/lib/git-version-bump.rb +138 -0
- data/lib/git-version-bump/rake-tasks.rb +26 -0
- metadata +106 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
Maintain your program versions entirely within git. No local files
|
2
|
+
required!
|
3
|
+
|
4
|
+
This gem contains a set of Rake tasks and associated code to manage the
|
5
|
+
versioning of your code via git tags. No in-repo file is required to store
|
6
|
+
your version, which reduces unnecessary duplication of information.
|
7
|
+
|
8
|
+
|
9
|
+
# Usage
|
10
|
+
|
11
|
+
In your `Rakefile`, add the following line:
|
12
|
+
|
13
|
+
require 'git-version-bump/rake-tasks'
|
14
|
+
|
15
|
+
You will now have the following rake tasks available:
|
16
|
+
|
17
|
+
rake version:bump:major # bump major version (x.y.z -> x+1.0.0)
|
18
|
+
rake version:bump:minor # bump minor version (x.y.z -> x.y+1.0)
|
19
|
+
rake version:bump:patch # bump patch version (x.y.z -> x.y.z+1)
|
20
|
+
|
21
|
+
By running any of those, a new tag will be created representing the newly
|
22
|
+
incremented version number at the current commit. If no tags currently
|
23
|
+
exist, the previous version will be taken to be `0.0.0` and then incremented
|
24
|
+
accordingly.
|
25
|
+
|
26
|
+
To get access to this version information in your code (such as in your
|
27
|
+
`gemspec`, or the definition of a `::VERSION` constant), you can `require
|
28
|
+
'git-version-bump'` and use the following methods:
|
29
|
+
|
30
|
+
GVB.version # Return the entire version string
|
31
|
+
GVB.major_version # Return just the 'major' portion of the version
|
32
|
+
GVB.minor_version # Return just the 'minor' portion of the version
|
33
|
+
GVB.patch_version # Return just the 'patch' portion of the version
|
34
|
+
GVB.internal_revision # Return "internal revision" information, or nil
|
35
|
+
GVB.date # Return the date of the most recent commit, or
|
36
|
+
# today's date if the tree is dirty
|
37
|
+
|
38
|
+
The "internal revision" is set when the tree is dirty, or when the latest
|
39
|
+
git commit doesn't correspond with a tag. In that case, the internal
|
40
|
+
revision will describe, in the manner of `git describe`, the full details of
|
41
|
+
the version of the code in use. This information will be part of the
|
42
|
+
version string provided by `gvb_version`.
|
43
|
+
|
44
|
+
If any of these methods are called when there isn't a tag or other version
|
45
|
+
information available, the version will be assumed to be `0.0.0.1.ENOTAG`
|
46
|
+
with a date of `1970-01-01`.
|
47
|
+
|
48
|
+
|
49
|
+
## In your gemspec
|
50
|
+
|
51
|
+
Typically, you want to encode your version and commit date into your
|
52
|
+
gemspec, like this:
|
53
|
+
|
54
|
+
Gem::Specification.new do |s|
|
55
|
+
s.version = GVB.version
|
56
|
+
s.date = GVB.date
|
57
|
+
|
58
|
+
...
|
59
|
+
end
|
60
|
+
|
61
|
+
The beauty of this method is that whenever you run a `rake build`, you'll
|
62
|
+
get a gem which is *accurately* versioned for the current state of your
|
63
|
+
repository. No more wondering if the `foobar-1.2.3` gem installed on your
|
64
|
+
system was built from pristine sources, or with that experimental patch you
|
65
|
+
were trying out...
|
66
|
+
|
67
|
+
|
68
|
+
## In your gem
|
69
|
+
|
70
|
+
If, like me, you're one of those people who likes to be able to easily see
|
71
|
+
what version of a library I'm running, then you probably like to define a
|
72
|
+
`VERSION` constant somewhere in your gem's namespace. That, too, is simple
|
73
|
+
to do:
|
74
|
+
|
75
|
+
require 'git-version-bump'
|
76
|
+
|
77
|
+
class Foobar
|
78
|
+
VERSION = GVB.version
|
79
|
+
end
|
80
|
+
|
81
|
+
This will work correctly inside your git tree, and also in your installed
|
82
|
+
gem. Magical!
|
data/Rakefile
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
require_relative 'lib/git-version-bump/rake-tasks'
|
4
|
+
|
5
|
+
begin
|
6
|
+
Bundler.setup(:default, :development)
|
7
|
+
rescue Bundler::BundlerError => e
|
8
|
+
$stderr.puts e.message
|
9
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
10
|
+
exit e.status_code
|
11
|
+
end
|
12
|
+
|
13
|
+
Bundler::GemHelper.install_tasks
|
14
|
+
|
15
|
+
require 'rdoc/task'
|
16
|
+
|
17
|
+
Rake::RDocTask.new do |rd|
|
18
|
+
rd.main = "README.md"
|
19
|
+
rd.title = 'git-version-bump'
|
20
|
+
rd.rdoc_files.include("README.md", "lib/**/*.rb")
|
21
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require File.expand_path('../lib/git-version-bump', __FILE__)
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = "git-version-bump"
|
5
|
+
|
6
|
+
s.version = GVB.version
|
7
|
+
s.date = GVB.date
|
8
|
+
|
9
|
+
s.platform = Gem::Platform::RUBY
|
10
|
+
|
11
|
+
s.homepage = "http://theshed.hezmatt.org/git-version-bump"
|
12
|
+
s.summary = "Manage your app version entirely via git tags"
|
13
|
+
s.authors = ["Matt Palmer"]
|
14
|
+
|
15
|
+
s.extra_rdoc_files = ["README.md"]
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
|
18
|
+
s.add_development_dependency 'rake'
|
19
|
+
s.add_development_dependency 'bundler'
|
20
|
+
s.add_development_dependency 'rdoc'
|
21
|
+
end
|
@@ -0,0 +1,138 @@
|
|
1
|
+
module GitVersionBump
|
2
|
+
def self.version
|
3
|
+
git_ver = `git describe --dirty --match='v[0-9]*.[0-9]*.*[0-9]' 2>/dev/null`.
|
4
|
+
strip.
|
5
|
+
gsub(/^v/, '').
|
6
|
+
gsub('-', '.')
|
7
|
+
|
8
|
+
# If git returned success, then it gave us a described version.
|
9
|
+
# Success!
|
10
|
+
return git_ver if $? == 0
|
11
|
+
|
12
|
+
# git failed us; we're either not in a git repo or else we've never
|
13
|
+
# tagged anything before.
|
14
|
+
|
15
|
+
# Are we in a git repo with no tags? If so, dump out our
|
16
|
+
# super-special version and be done with it.
|
17
|
+
system("git status >/dev/null 2>&1")
|
18
|
+
return "0.0.0.1.ENOTAG" if $? == 0
|
19
|
+
|
20
|
+
# We're not in a git repo. This means that we need to get version
|
21
|
+
# information out of rubygems, given only the filename of who called
|
22
|
+
# us. This takes a little bit of effort.
|
23
|
+
|
24
|
+
if spec = GVB.caller_gemspec
|
25
|
+
return spec.version.to_s
|
26
|
+
else
|
27
|
+
# If we got here, something went *badly* wrong -- presumably, we
|
28
|
+
# weren't called from within a loaded gem, and so we've got *no*
|
29
|
+
# idea what's going on. Time to bail!
|
30
|
+
raise RuntimeError,
|
31
|
+
"GVB.version called from mysterious, non-gem location."
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.major_version
|
36
|
+
ver = GVB.version
|
37
|
+
v = ver.split('.')[0]
|
38
|
+
|
39
|
+
unless v =~ /^[0-9]+$/
|
40
|
+
raise ArgumentError,
|
41
|
+
"#{v} (part of #{ver.inspect}) is not a numeric version component. Abandon ship!"
|
42
|
+
end
|
43
|
+
|
44
|
+
return v.to_i
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.minor_version
|
48
|
+
ver = GVB.version
|
49
|
+
v = ver.split('.')[1]
|
50
|
+
|
51
|
+
unless v =~ /^[0-9]+$/
|
52
|
+
raise ArgumentError,
|
53
|
+
"#{v} (part of #{ver.inspect}) is not a numeric version component. Abandon ship!"
|
54
|
+
end
|
55
|
+
|
56
|
+
return v.to_i
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.patch_version
|
60
|
+
ver = GVB.version
|
61
|
+
v = ver.split('.')[2]
|
62
|
+
|
63
|
+
unless v =~ /^[0-9]+$/
|
64
|
+
raise ArgumentError,
|
65
|
+
"#{v} (part of #{ver.inspect}) is not a numeric version component. Abandon ship!"
|
66
|
+
end
|
67
|
+
|
68
|
+
return v.to_i
|
69
|
+
end
|
70
|
+
|
71
|
+
def self.internal_revision
|
72
|
+
GVB.version.split('.', 4)[3].to_s
|
73
|
+
end
|
74
|
+
|
75
|
+
def self.date
|
76
|
+
# Are we in a git tree?
|
77
|
+
system("git status >/dev/null 2>&1")
|
78
|
+
if $? == 0
|
79
|
+
# Yes, we're in git.
|
80
|
+
|
81
|
+
if GVB.dirty_tree?
|
82
|
+
return Time.now.strftime("%F")
|
83
|
+
else
|
84
|
+
# Clean tree. Date of last commit is needed.
|
85
|
+
return `git show --format=format:%ad --date=short | head -n 1`.strip
|
86
|
+
end
|
87
|
+
else
|
88
|
+
# Not in git; time to hit the gemspecs
|
89
|
+
if spec = GVB.caller_gemspec
|
90
|
+
return spec.version.to_s
|
91
|
+
else
|
92
|
+
raise RuntimeError,
|
93
|
+
"GVB.date called from mysterious, non-gem location."
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def self.tag_version(v)
|
99
|
+
if GVB.dirty_tree?
|
100
|
+
puts "You have uncommitted files. Refusing to tag a dirty tree."
|
101
|
+
else
|
102
|
+
puts "Tagging version #{v}..."
|
103
|
+
system("git tag -a -m 'Version v#{v}' v#{v}")
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def self.caller_gemspec
|
108
|
+
# First up, who called us? Because this method gets called from other
|
109
|
+
# methods within this file, we can't just look at Gem.location_of_caller,
|
110
|
+
# but instead we need to parse the whole caller stack ourselves.
|
111
|
+
caller_file = caller.
|
112
|
+
map { |l| l.split(':')[0] }.
|
113
|
+
find { |l| l != __FILE__ }
|
114
|
+
|
115
|
+
# Next we grovel through all the loaded gems to try and find the gem
|
116
|
+
# that contains the caller's file.
|
117
|
+
Gem.loaded_specs.values.each do |spec|
|
118
|
+
if Dir.
|
119
|
+
glob(spec.lib_dirs_glob).
|
120
|
+
find { |d| caller_file.index(d) == 0 }
|
121
|
+
# The caller_file is in this
|
122
|
+
# gem! Woohoo!
|
123
|
+
return spec
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
nil
|
128
|
+
end
|
129
|
+
|
130
|
+
def self.dirty_tree?
|
131
|
+
# Are we in a dirty, dirty tree?
|
132
|
+
system("! git diff --no-ext-diff --quiet --exit-code || ! git diff-index --cached --quiet HEAD")
|
133
|
+
|
134
|
+
$? == 0
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
GVB = GitVersionBump
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require_relative '../git-version-bump'
|
2
|
+
|
3
|
+
namespace :version do
|
4
|
+
namespace :bump do
|
5
|
+
desc "bump major version (x.y.z -> x+1.0.0)"
|
6
|
+
task :major do
|
7
|
+
GVB.tag_version "#{GVB.major_version + 1}.0.0"
|
8
|
+
|
9
|
+
puts "Version is now #{GVB.version}"
|
10
|
+
end
|
11
|
+
|
12
|
+
desc "bump minor version (x.y.z -> x.y+1.0)"
|
13
|
+
task :minor do
|
14
|
+
GVB.tag_version "#{GVB.major_version}.#{GVB.minor_version+1}.0"
|
15
|
+
|
16
|
+
puts "Version is now #{GVB.version}"
|
17
|
+
end
|
18
|
+
|
19
|
+
desc "bump patch version (x.y.z -> x.y.z+1)"
|
20
|
+
task :patch do
|
21
|
+
GVB.tag_version "#{GVB.major_version}.#{GVB.minor_version}.#{GVB.patch_version+1}"
|
22
|
+
|
23
|
+
puts "Version is now #{GVB.version}"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
metadata
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: git-version-bump
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Matt Palmer
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2014-02-11 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rake
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: bundler
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rdoc
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
description:
|
63
|
+
email:
|
64
|
+
executables: []
|
65
|
+
extensions: []
|
66
|
+
extra_rdoc_files:
|
67
|
+
- README.md
|
68
|
+
files:
|
69
|
+
- .gitignore
|
70
|
+
- Gemfile
|
71
|
+
- README.md
|
72
|
+
- Rakefile
|
73
|
+
- git-version-bump.gemspec
|
74
|
+
- lib/git-version-bump.rb
|
75
|
+
- lib/git-version-bump/rake-tasks.rb
|
76
|
+
homepage: http://theshed.hezmatt.org/git-version-bump
|
77
|
+
licenses: []
|
78
|
+
post_install_message:
|
79
|
+
rdoc_options: []
|
80
|
+
require_paths:
|
81
|
+
- lib
|
82
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
84
|
+
requirements:
|
85
|
+
- - ! '>='
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
88
|
+
segments:
|
89
|
+
- 0
|
90
|
+
hash: 4544833629882770877
|
91
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
92
|
+
none: false
|
93
|
+
requirements:
|
94
|
+
- - ! '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
segments:
|
98
|
+
- 0
|
99
|
+
hash: 4544833629882770877
|
100
|
+
requirements: []
|
101
|
+
rubyforge_project:
|
102
|
+
rubygems_version: 1.8.23
|
103
|
+
signing_key:
|
104
|
+
specification_version: 3
|
105
|
+
summary: Manage your app version entirely via git tags
|
106
|
+
test_files: []
|