git-lite-version-bump 0.17.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/.gitignore +3 -0
- data/Gemfile +3 -0
- data/LICENCE +674 -0
- data/README.md +157 -0
- data/Rakefile +17 -0
- data/bin/git-version-bump +55 -0
- data/git-version-bump.gemspec +26 -0
- data/lib/git-version-bump.rb +324 -0
- data/lib/git-version-bump/rake-tasks.rb +49 -0
- data/lib/git-version-bump/version.rb +8 -0
- metadata +109 -0
data/README.md
ADDED
@@ -0,0 +1,157 @@
|
|
1
|
+
Maintain your program versions entirely within git. No local files
|
2
|
+
required! All versioning information is stored using git tags.
|
3
|
+
|
4
|
+
This gem contains a command-line tool and set of Rake tasks to increment
|
5
|
+
and display your version numbers via git tags, and some associated Ruby code to use
|
6
|
+
inside a gemspec or your program to retrieve the current version number, for
|
7
|
+
use in builds and at runtime.
|
8
|
+
|
9
|
+
|
10
|
+
# Usage
|
11
|
+
|
12
|
+
Most of your day-to-day usage of `git-version-bump` will be via the command
|
13
|
+
line. When you bump a version, a new tag will be created representing the newly
|
14
|
+
incremented version number at the current commit. If no tags currently
|
15
|
+
exist, the previous version will be taken to be `0.0.0` and then incremented
|
16
|
+
accordingly.
|
17
|
+
|
18
|
+
|
19
|
+
## On the command line
|
20
|
+
|
21
|
+
Pretty damned trivial:
|
22
|
+
|
23
|
+
git version-bump <major|minor|patch|show>
|
24
|
+
|
25
|
+
You can also shorten the specifier to any unique substring:
|
26
|
+
|
27
|
+
git version-bump ma
|
28
|
+
git version-bump mi
|
29
|
+
git version-bump p
|
30
|
+
git version-bump s
|
31
|
+
|
32
|
+
I recommend adding an alias to your `~/.gitconfig` file, for less typing:
|
33
|
+
|
34
|
+
[alias]
|
35
|
+
vb = version-bump
|
36
|
+
|
37
|
+
You can also add your own release notes to your release tags, by using the
|
38
|
+
`-n` (or `--notes`, if you like typing) option:
|
39
|
+
|
40
|
+
git version-bump -n minor
|
41
|
+
|
42
|
+
This will open an editor, containing a list of the commits since the last
|
43
|
+
release tag, in which you can type your release notes. If you follow
|
44
|
+
standard git commit style (a "heading" line, then a blank line, followed by
|
45
|
+
free-form text) you're perfectly positioned to use
|
46
|
+
[github-release](http://theshed.hezmatt.org/github-release) to make
|
47
|
+
gorgeous-looking release announcements to Github.
|
48
|
+
|
49
|
+
|
50
|
+
## In your `Rakefile`
|
51
|
+
|
52
|
+
If you'd like to have access to the version-bumping goodness via `rake`, add
|
53
|
+
the following line to your `Rakefile`:
|
54
|
+
|
55
|
+
require 'git-version-bump/rake-tasks'
|
56
|
+
|
57
|
+
You will now have the following rake tasks available:
|
58
|
+
|
59
|
+
rake version:bump:major # bump major version (x.y.z -> x+1.0.0)
|
60
|
+
rake version:bump:minor # bump minor version (x.y.z -> x.y+1.0)
|
61
|
+
rake version:bump:patch # bump patch version (x.y.z -> x.y.z+1)
|
62
|
+
rake version:bump:show # Print current version number
|
63
|
+
|
64
|
+
(Since `version:bump:major` is a lot of typing, there are also shortcuts:
|
65
|
+
`v:b:major`, `v:b:maj`, `v:b:minor`, `v:b:min`, `v:b:patch`, `v:b:pat`, and
|
66
|
+
`v:b:p`)
|
67
|
+
|
68
|
+
|
69
|
+
## In your Ruby code
|
70
|
+
|
71
|
+
To get access to this version information in your code (such as in your
|
72
|
+
`gemspec`, or the definition of a `::VERSION` constant), you can `require
|
73
|
+
'git-version-bump'` and use the following methods:
|
74
|
+
|
75
|
+
GVB.version # Return the entire version string
|
76
|
+
GVB.major_version # Return just the 'major' portion of the version
|
77
|
+
GVB.minor_version # Return just the 'minor' portion of the version
|
78
|
+
GVB.patch_version # Return just the 'patch' portion of the version
|
79
|
+
GVB.internal_revision # Return "internal revision" information, or nil
|
80
|
+
GVB.date # Return the date of the most recent commit, or
|
81
|
+
# today's date if the tree is dirty
|
82
|
+
|
83
|
+
The "internal revision" is set when the tree is dirty, or when the latest
|
84
|
+
git commit doesn't correspond with a tag. In that case, the internal
|
85
|
+
revision will describe, in the manner of `git describe`, the full details of
|
86
|
+
the version of the code in use. This information will be part of the
|
87
|
+
version string provided by `gvb_version`.
|
88
|
+
|
89
|
+
If any of these methods are called when there isn't a tag or other version
|
90
|
+
information available, the version will be assumed to be `0.0.0.1.ENOTAG`
|
91
|
+
with a date of `1970-01-01`.
|
92
|
+
|
93
|
+
|
94
|
+
### In your gemspec
|
95
|
+
|
96
|
+
Typically, you want to encode your version and commit date into your
|
97
|
+
gemspec, like this:
|
98
|
+
|
99
|
+
Gem::Specification.new do |s|
|
100
|
+
s.version = GVB.version
|
101
|
+
s.date = GVB.date
|
102
|
+
|
103
|
+
...
|
104
|
+
end
|
105
|
+
|
106
|
+
The beauty of this method is that whenever you run a `rake build`, you'll
|
107
|
+
get a gem which is *accurately* versioned for the current state of your
|
108
|
+
repository. No more wondering if the `foobar-1.2.3` gem installed on your
|
109
|
+
system was built from pristine sources, or with that experimental patch you
|
110
|
+
were trying out...
|
111
|
+
|
112
|
+
|
113
|
+
### In your gem
|
114
|
+
|
115
|
+
If, like me, you're one of those people who likes to be able to easily see
|
116
|
+
what version of a library you're running, then you probably like to define a
|
117
|
+
`VERSION` constant somewhere in your gem's namespace. That, too, is simple
|
118
|
+
to do:
|
119
|
+
|
120
|
+
require 'git-version-bump'
|
121
|
+
|
122
|
+
class Foobar
|
123
|
+
VERSION = GVB.version
|
124
|
+
end
|
125
|
+
|
126
|
+
This will work correctly inside your git tree, and also in your installed
|
127
|
+
gem. Magical!
|
128
|
+
|
129
|
+
#### For projects using lite tags
|
130
|
+
|
131
|
+
If you are using GitHub releases for your project or some other method that
|
132
|
+
involves light tags (tags with no annotations), you might notice that these
|
133
|
+
tags are not detected by git-version-bump by default. If you want these
|
134
|
+
commits to be detected then use the following configuration:
|
135
|
+
|
136
|
+
require 'git-version-bump'
|
137
|
+
|
138
|
+
class Foobar
|
139
|
+
# First parameter is use_local_git, second is include_lite_tags
|
140
|
+
VERSION = GVB.version(false, true)
|
141
|
+
end
|
142
|
+
|
143
|
+
|
144
|
+
# Contributing
|
145
|
+
|
146
|
+
Send your pull requests to the [Github
|
147
|
+
repo](https://github.com/mpalmer/git-version-bump), or send patches to
|
148
|
+
`theshed+git-version-bump@hezmatt.org`. Bug reports can be sent to the same
|
149
|
+
place, although I greatly prefer patches.
|
150
|
+
|
151
|
+
|
152
|
+
# Licence
|
153
|
+
|
154
|
+
Unless otherwise specified, all code in this repository is licenced under
|
155
|
+
the terms of the GNU Public Licence, version 3, as published by the Free
|
156
|
+
Software Foundation. The full terms of this licence can be found in the
|
157
|
+
file LICENCE.
|
data/Rakefile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
|
4
|
+
Bundler::GemHelper.install_tasks
|
5
|
+
|
6
|
+
require 'rdoc/task'
|
7
|
+
|
8
|
+
Rake::RDocTask.new do |rd|
|
9
|
+
rd.main = "README.md"
|
10
|
+
rd.title = 'git-version-bump'
|
11
|
+
rd.rdoc_files.include("README.md", "lib/**/*.rb")
|
12
|
+
end
|
13
|
+
|
14
|
+
task :release do
|
15
|
+
sh "git push --follow-tags"
|
16
|
+
sh "git release"
|
17
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'git-version-bump'
|
4
|
+
|
5
|
+
if ARGV[0].nil? or
|
6
|
+
ARGV[0].empty? or
|
7
|
+
(ARGV.length == 1 && (ARGV[0] == "-d" || ARGV[0] == "--dry-run")) or
|
8
|
+
ARGV[0] == '-h' or
|
9
|
+
ARGV[0] == '--help'
|
10
|
+
$stderr.puts <<-EOF.gsub(/^\t\t/, '')
|
11
|
+
Usage: git version-bump [-n|--notes] [-d|--dry-run] <major|minor|patch|show>
|
12
|
+
|
13
|
+
'major': x.y.z -> x+1.0.0
|
14
|
+
'minor': x.y.z -> x.y+1.0
|
15
|
+
'patch': x.y.z -> x.y.z+1
|
16
|
+
|
17
|
+
'show': Display the current GVB version
|
18
|
+
|
19
|
+
-d, --dry-run: Calculate and return the bump value, but don't update git workspace or remote
|
20
|
+
-n, --notes: Prompt for "release notes" to add to the release tag
|
21
|
+
-l, --lite-tags: Include non-annotated git tags
|
22
|
+
EOF
|
23
|
+
end
|
24
|
+
|
25
|
+
release_notes = ARGV.delete('-n') || ARGV.delete('--notes')
|
26
|
+
dry_run = ARGV.delete('-d') || ARGV.delete('--dry-run')
|
27
|
+
lite_tags = ARGV.delete('-l') || ARGV.delete('--lite-tags')
|
28
|
+
|
29
|
+
if ARGV[0].nil? or ARGV[0].empty?
|
30
|
+
exit 1
|
31
|
+
elsif ARGV[0] == '-h' or ARGV[0] == '--help'
|
32
|
+
exit 0
|
33
|
+
end
|
34
|
+
|
35
|
+
result = case ARGV[0].downcase
|
36
|
+
when /^maj?o?r?$/
|
37
|
+
"#{GVB.major_version(true) + 1}.0.0"
|
38
|
+
when /^min?o?r?$/
|
39
|
+
"#{GVB.major_version(true)}.#{GVB.minor_version(true)+1}.0"
|
40
|
+
when /^pa?t?c?h?$/
|
41
|
+
"#{GVB.major_version(true)}.#{GVB.minor_version(true)}.#{GVB.patch_version(true)+1}"
|
42
|
+
when /^sh?o?w?$/
|
43
|
+
puts GVB.version(true)
|
44
|
+
exit 0
|
45
|
+
else
|
46
|
+
$stderr.puts "Unknown argument: #{ARGV[0]}. Try --help."
|
47
|
+
exit 1
|
48
|
+
end
|
49
|
+
|
50
|
+
if dry_run
|
51
|
+
puts result
|
52
|
+
else
|
53
|
+
GVB.tag_version result, release_notes, lite_tags
|
54
|
+
puts "Version is now #{GVB.version(true)}."
|
55
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
lib = File.expand_path('../lib', __FILE__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
require 'git-version-bump'
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "git-lite-version-bump"
|
7
|
+
|
8
|
+
s.version = GVB.version
|
9
|
+
s.date = GVB.date
|
10
|
+
|
11
|
+
s.platform = Gem::Platform::RUBY
|
12
|
+
s.required_ruby_version = ">= 1.8.7"
|
13
|
+
|
14
|
+
s.homepage = "http://github.com/rbclark/git-version-bump"
|
15
|
+
s.summary = "Manage your app version entirely via git tags (even lite tags)"
|
16
|
+
s.authors = ["Matt Palmer"]
|
17
|
+
|
18
|
+
s.extra_rdoc_files = ["README.md"]
|
19
|
+
s.files = `git ls-files`.split("\n")
|
20
|
+
s.executables = ["git-version-bump"]
|
21
|
+
|
22
|
+
s.add_development_dependency 'github-release'
|
23
|
+
s.add_development_dependency 'rake'
|
24
|
+
s.add_development_dependency 'bundler'
|
25
|
+
s.add_development_dependency 'rdoc'
|
26
|
+
end
|
@@ -0,0 +1,324 @@
|
|
1
|
+
require 'tempfile'
|
2
|
+
require 'digest/sha1'
|
3
|
+
require 'pathname'
|
4
|
+
|
5
|
+
module GitVersionBump
|
6
|
+
class VersionUnobtainable < StandardError; end
|
7
|
+
|
8
|
+
DEVNULL = Gem.win_platform? ? "NUL" : "/dev/null"
|
9
|
+
|
10
|
+
def self.version(use_local_git=false, include_lite_tags=false)
|
11
|
+
if use_local_git
|
12
|
+
unless git_available?
|
13
|
+
raise RuntimeError,
|
14
|
+
"GVB.version(use_local_git=true) called, but git isn't installed"
|
15
|
+
end
|
16
|
+
|
17
|
+
sq_git_dir = shell_quoted_string(Dir.pwd)
|
18
|
+
else
|
19
|
+
sq_git_dir = shell_quoted_string((File.dirname(caller_file) rescue nil || Dir.pwd))
|
20
|
+
end
|
21
|
+
|
22
|
+
git_cmd = "git -C #{sq_git_dir} describe --dirty='.1.dirty.#{Time.now.strftime("%Y%m%d.%H%M%S")}' --match='v[0-9]*.[0-9]*.*[0-9]'"
|
23
|
+
git_cmd << " --tags" if include_lite_tags
|
24
|
+
|
25
|
+
git_ver = `#{git_cmd} 2> #{DEVNULL}`.
|
26
|
+
strip.
|
27
|
+
gsub(/^v/, '').
|
28
|
+
gsub('-', '.')
|
29
|
+
|
30
|
+
# If git returned success, then it gave us a described version.
|
31
|
+
# Success!
|
32
|
+
return git_ver if $? == 0
|
33
|
+
|
34
|
+
# git failed us; we're either not in a git repo or else we've never
|
35
|
+
# tagged anything before.
|
36
|
+
|
37
|
+
# Are we in a git repo with no tags? If so, dump out our
|
38
|
+
# super-special version and be done with it, otherwise try to use the
|
39
|
+
# gem version.
|
40
|
+
system("git -C #{sq_git_dir} status > #{DEVNULL} 2>&1")
|
41
|
+
$? == 0 ? "0.0.0.1.ENOTAG" : gem_version(use_local_git)
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.major_version(use_local_git=false, include_lite_tags=false)
|
45
|
+
ver = version(use_local_git, include_lite_tags)
|
46
|
+
v = ver.split('.')[0]
|
47
|
+
|
48
|
+
unless v =~ /^[0-9]+$/
|
49
|
+
raise ArgumentError,
|
50
|
+
"#{v} (part of #{ver.inspect}) is not a numeric version component. Abandon ship!"
|
51
|
+
end
|
52
|
+
|
53
|
+
return v.to_i
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.minor_version(use_local_git=false, include_lite_tags=false)
|
57
|
+
ver = version(use_local_git, include_lite_tags)
|
58
|
+
v = ver.split('.')[1]
|
59
|
+
|
60
|
+
unless v =~ /^[0-9]+$/
|
61
|
+
raise ArgumentError,
|
62
|
+
"#{v} (part of #{ver.inspect}) is not a numeric version component. Abandon ship!"
|
63
|
+
end
|
64
|
+
|
65
|
+
return v.to_i
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.patch_version(use_local_git=false, include_lite_tags=false)
|
69
|
+
ver = version(use_local_git, include_lite_tags)
|
70
|
+
v = ver.split('.')[2]
|
71
|
+
|
72
|
+
unless v =~ /^[0-9]+$/
|
73
|
+
raise ArgumentError,
|
74
|
+
"#{v} (part of #{ver.inspect}) is not a numeric version component. Abandon ship!"
|
75
|
+
end
|
76
|
+
|
77
|
+
return v.to_i
|
78
|
+
end
|
79
|
+
|
80
|
+
def self.internal_revision(use_local_git=false, include_lite_tags=false)
|
81
|
+
version(use_local_git, include_lite_tags).split('.', 4)[3].to_s
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.date(use_local_git=false)
|
85
|
+
if use_local_git
|
86
|
+
unless git_available?
|
87
|
+
raise RuntimeError,
|
88
|
+
"GVB.date(use_local_git=true), but git is not installed"
|
89
|
+
end
|
90
|
+
|
91
|
+
sq_git_dir = shell_quoted_string(Dir.pwd)
|
92
|
+
else
|
93
|
+
sq_git_dir = shell_quoted_string((File.dirname(caller_file) rescue nil || Dir.pwd))
|
94
|
+
end
|
95
|
+
|
96
|
+
# Are we in a git tree?
|
97
|
+
system("git -C #{sq_git_dir} status > #{DEVNULL} 2>&1")
|
98
|
+
if $? == 0
|
99
|
+
# Yes, we're in git.
|
100
|
+
|
101
|
+
if dirty_tree?
|
102
|
+
return Time.now.strftime("%F")
|
103
|
+
else
|
104
|
+
# Clean tree. Date of last commit is needed.
|
105
|
+
return `git -C #{sq_git_dir} show --no-show-signature --format=format:%cd --date=short`.lines.first.strip
|
106
|
+
end
|
107
|
+
else
|
108
|
+
if use_local_git
|
109
|
+
raise RuntimeError,
|
110
|
+
"GVB.date(use_local_git=true) called from non-git location"
|
111
|
+
end
|
112
|
+
|
113
|
+
# Not in git; time to hit the gemspecs
|
114
|
+
if spec = caller_gemspec
|
115
|
+
return spec.date.strftime("%F")
|
116
|
+
end
|
117
|
+
|
118
|
+
raise RuntimeError,
|
119
|
+
"GVB.date called from mysterious, non-gem location."
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def self.tag_version(v, release_notes = false, include_lite_tags=false)
|
124
|
+
if dirty_tree?
|
125
|
+
puts "You have uncommitted files. Refusing to tag a dirty tree."
|
126
|
+
else
|
127
|
+
if release_notes
|
128
|
+
# We need to find the tag before this one, so we can list all the commits
|
129
|
+
# between the two. This is not a trivial operation.
|
130
|
+
git_cmd = 'git describe --always'
|
131
|
+
git_cmd << ' --tags' if include_lite_tags
|
132
|
+
prev_tag = `#{git_cmd}`.strip.gsub(/-\d+-g[0-9a-f]+$/, '')
|
133
|
+
|
134
|
+
log_file = Tempfile.new('gvb')
|
135
|
+
|
136
|
+
log_file.puts <<-EOF.gsub(/^\t\t\t\t\t/, '')
|
137
|
+
|
138
|
+
|
139
|
+
|
140
|
+
# Write your release notes above. The first line should be the release name.
|
141
|
+
# To help you remember what's in here, the commits since your last release
|
142
|
+
# are listed below. This will become v#{v}
|
143
|
+
#
|
144
|
+
EOF
|
145
|
+
|
146
|
+
log_file.close
|
147
|
+
system("git log --no-show-signature --format='# %h %s' #{prev_tag}..HEAD >>#{log_file.path}")
|
148
|
+
|
149
|
+
pre_hash = Digest::SHA1.hexdigest(File.read(log_file.path))
|
150
|
+
system("git config -e -f #{log_file.path}")
|
151
|
+
if Digest::SHA1.hexdigest(File.read(log_file.path)) == pre_hash
|
152
|
+
puts "Release notes not edited; aborting"
|
153
|
+
log_file.unlink
|
154
|
+
return
|
155
|
+
end
|
156
|
+
|
157
|
+
puts "Tagging version #{v}..."
|
158
|
+
system("git tag -a -F #{log_file.path} v#{v}")
|
159
|
+
log_file.unlink
|
160
|
+
else
|
161
|
+
# Crikey this is a lot simpler
|
162
|
+
system("git tag -a -m 'Version v#{v}' v#{v}")
|
163
|
+
end
|
164
|
+
|
165
|
+
system("git push > #{DEVNULL} 2>&1")
|
166
|
+
system("git push --tags > #{DEVNULL} 2>&1")
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
# Calculate a version number based on the date of the most recent git commit.
|
171
|
+
#
|
172
|
+
# Return a version format string of the form `"0.YYYYMMDD.N"`, where
|
173
|
+
# `YYYYMMDD` is the date of the "top-most" commit in the tree, and `N` is
|
174
|
+
# the number of other commits also made on that date.
|
175
|
+
#
|
176
|
+
# This version format is not recommented for general use. It has benefit
|
177
|
+
# only in situations where the principles of Semantic Versioning have no
|
178
|
+
# real meaning, such as packages where there is little or no concept of
|
179
|
+
# "backwards compatibility" (eg packages which only contain images and
|
180
|
+
# other assets), or where the package can, for reasons outside that of
|
181
|
+
# the package itself, never break backwards compatibility (definitions of
|
182
|
+
# binary-packed structures shared amongst multiple systems).
|
183
|
+
#
|
184
|
+
# The format of this commit-date-based version format allows for a strictly
|
185
|
+
# monotonically-increasing version number, aligned with the progression of the
|
186
|
+
# underlying git commit log.
|
187
|
+
#
|
188
|
+
# One limitation of the format is that it doesn't deal with the issue of
|
189
|
+
# package builds made from multiple divergent trees. Unlike
|
190
|
+
# `git-describe`-based output, there is no "commit hash" identity
|
191
|
+
# included in the version string. This is because of (ludicrous)
|
192
|
+
# limitations of the Rubygems format definition -- the moment there's a
|
193
|
+
# letter in the version number, the package is considered a "pre-release"
|
194
|
+
# version. Since hashes are hex, we're boned. Sorry about that. Don't
|
195
|
+
# make builds off a branch, basically.
|
196
|
+
#
|
197
|
+
def self.commit_date_version(use_local_git = false)
|
198
|
+
if use_local_git
|
199
|
+
unless git_available?
|
200
|
+
raise RuntimeError,
|
201
|
+
"GVB.commit_date_version(use_local_git=true) called, but git isn't installed"
|
202
|
+
end
|
203
|
+
|
204
|
+
sq_git_dir = shell_quoted_string(Dir.pwd)
|
205
|
+
else
|
206
|
+
sq_git_dir = shell_quoted_string((File.dirname(caller_file) rescue nil || Dir.pwd))
|
207
|
+
end
|
208
|
+
|
209
|
+
commit_dates = `git -C #{sq_git_dir} log --format=%at`.
|
210
|
+
split("\n").
|
211
|
+
map { |l| Time.at(Integer(l)).strftime("%Y%m%d") }
|
212
|
+
|
213
|
+
if $? == 0
|
214
|
+
# We got a log; calculate our version number and we're done.
|
215
|
+
version_date = commit_dates.first
|
216
|
+
commit_count = commit_dates.select { |d| d == version_date }.length - 1
|
217
|
+
dirty_suffix = if dirty_tree?
|
218
|
+
".dirty.#{Time.now.strftime("%Y%m%d.%H%M%S")}"
|
219
|
+
else
|
220
|
+
""
|
221
|
+
end
|
222
|
+
|
223
|
+
return "0.#{version_date}.#{commit_count}#{dirty_suffix}"
|
224
|
+
end
|
225
|
+
|
226
|
+
# git failed us; either we're not in a git repo or else it's a git
|
227
|
+
# repo that's not got any commits.
|
228
|
+
|
229
|
+
# Are we in a git repo with no tags? If so, dump out our
|
230
|
+
# super-special version and be done with it.
|
231
|
+
system("git -C #{sq_git_dir} status > #{DEVNULL} 2>&1")
|
232
|
+
$? == 0 ? "0.0.0.1.ENOCOMMITS" : gem_version(use_local_git)
|
233
|
+
end
|
234
|
+
|
235
|
+
private
|
236
|
+
|
237
|
+
def self.git_available?
|
238
|
+
system("git --version > #{DEVNULL} 2>&1")
|
239
|
+
|
240
|
+
$? == 0
|
241
|
+
end
|
242
|
+
|
243
|
+
def self.dirty_tree?
|
244
|
+
# Are we in a dirty, dirty tree?
|
245
|
+
system("! git diff --no-ext-diff --quiet --exit-code 2> #{DEVNULL} || ! git diff-index --cached --quiet HEAD 2> #{DEVNULL}")
|
246
|
+
|
247
|
+
$? == 0
|
248
|
+
end
|
249
|
+
|
250
|
+
def self.caller_file
|
251
|
+
# Who called us? Because this method gets called from other methods
|
252
|
+
# within this file, we can't just look at Gem.location_of_caller, but
|
253
|
+
# instead we need to parse the caller stack ourselves to find which
|
254
|
+
# gem we're trying to version all over.
|
255
|
+
Pathname(
|
256
|
+
caller.
|
257
|
+
map { |l| l.split(':')[0] }.
|
258
|
+
find { |l| l != __FILE__ }
|
259
|
+
).realpath.to_s rescue nil
|
260
|
+
end
|
261
|
+
|
262
|
+
def self.caller_gemspec
|
263
|
+
cf = caller_file or return nil
|
264
|
+
|
265
|
+
# Grovel through all the loaded gems to try and find the gem
|
266
|
+
# that contains the caller's file.
|
267
|
+
Gem.loaded_specs.values.each do |spec|
|
268
|
+
search_dirs = spec.require_paths.map { |d| "#{spec.full_gem_path}/#{d}" } +
|
269
|
+
[File.join(spec.full_gem_path, spec.bindir)]
|
270
|
+
search_dirs.map! do |d|
|
271
|
+
begin
|
272
|
+
Pathname(d).realpath.to_s
|
273
|
+
rescue Errno::ENOENT
|
274
|
+
nil
|
275
|
+
end
|
276
|
+
end.compact!
|
277
|
+
|
278
|
+
if search_dirs.find { |d| cf.index(d) == 0 }
|
279
|
+
return spec
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
raise VersionUnobtainable,
|
284
|
+
"Unable to find gemspec for caller file #{cf}"
|
285
|
+
end
|
286
|
+
|
287
|
+
def self.gem_version(use_local_git = false)
|
288
|
+
if use_local_git
|
289
|
+
raise VersionUnobtainable,
|
290
|
+
"Unable to determine version from local git repo. This should never happen."
|
291
|
+
end
|
292
|
+
|
293
|
+
if spec = caller_gemspec
|
294
|
+
return spec.version.to_s
|
295
|
+
else
|
296
|
+
# If we got here, something went *badly* wrong -- presumably, we
|
297
|
+
# weren't called from within a loaded gem, and so we've got *no*
|
298
|
+
# idea what's going on. Time to bail!
|
299
|
+
if git_available?
|
300
|
+
raise VersionUnobtainable,
|
301
|
+
"GVB.version(#{use_local_git.inspect}) failed, and I really don't know why."
|
302
|
+
else
|
303
|
+
raise VersionUnobtainable,
|
304
|
+
"GVB.version(#{use_local_git.inspect}) failed; perhaps you need to install git?"
|
305
|
+
end
|
306
|
+
end
|
307
|
+
end
|
308
|
+
|
309
|
+
def self.shell_quoted_string(dir_string)
|
310
|
+
if Gem.win_platform?
|
311
|
+
return "\"#{dir_string}\""
|
312
|
+
else
|
313
|
+
# Shell Quoted, for your convenience
|
314
|
+
return "'#{dir_string.gsub("'", "'\\''")}'"
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
318
|
+
private_class_method :shell_quoted_string
|
319
|
+
|
320
|
+
end
|
321
|
+
|
322
|
+
GVB = GitVersionBump unless defined? GVB
|
323
|
+
|
324
|
+
require 'git-version-bump/version'
|