vershunt 2.0.4
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/vershunt +19 -0
- data/lib/msp_release.rb +153 -0
- data/lib/msp_release/build.rb +64 -0
- data/lib/msp_release/cli.rb +90 -0
- data/lib/msp_release/cli/branch.rb +97 -0
- data/lib/msp_release/cli/build.rb +99 -0
- data/lib/msp_release/cli/bump.rb +49 -0
- data/lib/msp_release/cli/checkout.rb +196 -0
- data/lib/msp_release/cli/distrib.rb +7 -0
- data/lib/msp_release/cli/help.rb +14 -0
- data/lib/msp_release/cli/new.rb +62 -0
- data/lib/msp_release/cli/push.rb +29 -0
- data/lib/msp_release/cli/reset.rb +17 -0
- data/lib/msp_release/cli/status.rb +46 -0
- data/lib/msp_release/debian.rb +229 -0
- data/lib/msp_release/exec.rb +120 -0
- data/lib/msp_release/git.rb +145 -0
- data/lib/msp_release/log.rb +48 -0
- data/lib/msp_release/make_branch.rb +29 -0
- data/lib/msp_release/options.rb +35 -0
- data/lib/msp_release/project.rb +41 -0
- data/lib/msp_release/project/base.rb +63 -0
- data/lib/msp_release/project/debian.rb +168 -0
- data/lib/msp_release/project/gem.rb +74 -0
- data/lib/msp_release/project/git.rb +76 -0
- data/lib/msp_release/project/ruby.rb +40 -0
- data/lib/msp_release/version.rb +3 -0
- metadata +116 -0
@@ -0,0 +1,49 @@
|
|
1
|
+
module MSPRelease
|
2
|
+
class CLI::Bump < CLI::Command
|
3
|
+
|
4
|
+
include CLI::WorkingCopyCommand
|
5
|
+
|
6
|
+
description "Increase the version number of the project"
|
7
|
+
|
8
|
+
arg :segment, "One of major, minor or bugfix"
|
9
|
+
|
10
|
+
opt :force, "Force bumping of version segments other than bugfix " +
|
11
|
+
"if you are not on master. By default, you bump minor and major from" +
|
12
|
+
" master, and you bump the bugfix version while on a branch.",
|
13
|
+
{
|
14
|
+
:short => 'f',
|
15
|
+
:default => false
|
16
|
+
}
|
17
|
+
|
18
|
+
def run
|
19
|
+
segment = arguments[:segment]
|
20
|
+
|
21
|
+
check_bump_allowed!(segment)
|
22
|
+
|
23
|
+
new_version, *changed_files = project.bump_version(segment)
|
24
|
+
|
25
|
+
files = [project.config_file, *changed_files].compact
|
26
|
+
|
27
|
+
files.each do |file|
|
28
|
+
exec "git add #{file}"
|
29
|
+
end
|
30
|
+
exec "git commit -m 'BUMPED VERSION TO #{new_version}'"
|
31
|
+
puts "New version: #{new_version}"
|
32
|
+
end
|
33
|
+
|
34
|
+
def check_bump_allowed!(segment)
|
35
|
+
force = options[:force]
|
36
|
+
not_on_master = !git.on_master?
|
37
|
+
|
38
|
+
if not_on_master && segment != 'bugfix' && ! force
|
39
|
+
raise CLI::Exit, "You must be on master to bump the #{segment} version" +
|
40
|
+
", or pass --force if you are sure this is what you want to do"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def revert_bump(changed_files)
|
45
|
+
exec "git checkout -- #{project.config_file} #{changed_files.join(' ')}"
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,196 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module MSPRelease
|
4
|
+
class CLI::Checkout < CLI::Command
|
5
|
+
include Debian::Versions
|
6
|
+
|
7
|
+
# When cloning repositories, limit to this many commits from each head
|
8
|
+
CLONE_DEPTH = 5
|
9
|
+
|
10
|
+
description """Checkout a specific commit from a git repository suitable
|
11
|
+
for building.
|
12
|
+
|
13
|
+
When no BRANCH_NAME is given, or that branch is not a release branch, the
|
14
|
+
latest commit is checked out and the changelog version is adjusted to signify
|
15
|
+
this will be a development build.
|
16
|
+
|
17
|
+
If BRANCH_NAME denotes a release branch (i.e release-1.0.2) then the latest
|
18
|
+
/release/ commit is checked out, even if there are commits after it.
|
19
|
+
The changelog remains unaltered in this case - the release commit would have
|
20
|
+
updated all version information.
|
21
|
+
"""
|
22
|
+
|
23
|
+
arg :git_url, "URL used to clone the git repository"
|
24
|
+
arg :branch_name, "Name of a branch on master to switch to once checked out",
|
25
|
+
:required => false
|
26
|
+
|
27
|
+
opt :build, "Build a debian package immediately after checking " +
|
28
|
+
"out, using the dpkg-buildpackage command",
|
29
|
+
{
|
30
|
+
:short => 'b',
|
31
|
+
:default => false
|
32
|
+
}
|
33
|
+
|
34
|
+
opt :noise, "Print output to stdout",
|
35
|
+
{
|
36
|
+
:short => 'n',
|
37
|
+
:default => true
|
38
|
+
}
|
39
|
+
|
40
|
+
opt :print_files, "Print out built files to stdout",
|
41
|
+
{
|
42
|
+
:short => 'p',
|
43
|
+
:default => false
|
44
|
+
}
|
45
|
+
|
46
|
+
opt :sign, "Pass options to dpkg-buildpackage to tell it whether or not to sign the build products",
|
47
|
+
{
|
48
|
+
:short => 'S',
|
49
|
+
:default => false
|
50
|
+
}
|
51
|
+
|
52
|
+
opt :tar, "Create a tarfile containing all the debian build " +
|
53
|
+
"products when using --build",
|
54
|
+
{
|
55
|
+
:short => 't',
|
56
|
+
:default => false
|
57
|
+
}
|
58
|
+
|
59
|
+
opt :shallow, "Only perform a shallow checkout to a depth of five" +
|
60
|
+
"commits from each head. See git documentation for more details",
|
61
|
+
{
|
62
|
+
:short => 's',
|
63
|
+
:default => false
|
64
|
+
}
|
65
|
+
|
66
|
+
opt :distribution, "Specify the debian distribution to put in the " +
|
67
|
+
"changelog when checking out a development version",
|
68
|
+
{
|
69
|
+
:short => 'd',
|
70
|
+
:long => 'debian-distribution',
|
71
|
+
:type => :string
|
72
|
+
}
|
73
|
+
|
74
|
+
def run
|
75
|
+
git_url = arguments[:git_url]
|
76
|
+
release_spec_arg = arguments[:branch_name]
|
77
|
+
|
78
|
+
do_build = options[:build]
|
79
|
+
tar_it = options[:tar]
|
80
|
+
clone_depth = options[:shallow] ? CLONE_DEPTH : nil
|
81
|
+
|
82
|
+
LOG.verbose if options[:noise]
|
83
|
+
|
84
|
+
branch_name = release_spec_arg || 'master'
|
85
|
+
pathspec = "origin/#{branch_name}"
|
86
|
+
branch_is_release_branch = !! /^release-.+$/.match(branch_name)
|
87
|
+
|
88
|
+
shallow_output = clone_depth.nil?? '' : ' (shallow)'
|
89
|
+
if release_spec_arg && branch_is_release_branch
|
90
|
+
LOG.debug("Checking out latest release commit from #{pathspec}#{shallow_output}")
|
91
|
+
else
|
92
|
+
LOG.debug("Checking out latest commit from #{pathspec}#{shallow_output}")
|
93
|
+
end
|
94
|
+
|
95
|
+
tmp_dir = "vershunt-#{Time.now.to_i}.tmp"
|
96
|
+
Git.clone(git_url, {:depth => clone_depth, :out_to => tmp_dir,
|
97
|
+
:exec => {:quiet => true}})
|
98
|
+
|
99
|
+
project = Project.new_from_project_file(tmp_dir + "/" + Helpers::PROJECT_FILE)
|
100
|
+
distribution = options[:distribution] || project.changelog.distribution
|
101
|
+
|
102
|
+
src_dir = Dir.chdir(tmp_dir) do
|
103
|
+
|
104
|
+
if pathspec != "origin/master"
|
105
|
+
move_to(pathspec)
|
106
|
+
end
|
107
|
+
|
108
|
+
if branch_is_release_branch
|
109
|
+
first_commit_hash, commit_message =
|
110
|
+
find_first_release_commit(project)
|
111
|
+
|
112
|
+
if first_commit_hash.nil?
|
113
|
+
raise CLI::Exit, "Could not find a release commit on #{pathspec}"
|
114
|
+
end
|
115
|
+
|
116
|
+
exec "git reset --hard #{first_commit_hash}"
|
117
|
+
else
|
118
|
+
dev_version = Development.
|
119
|
+
new_from_working_directory(branch_name, latest_commit_hash)
|
120
|
+
|
121
|
+
project.changelog.amend(dev_version, distribution)
|
122
|
+
end
|
123
|
+
src_dir = project.source_package_name + "-" + project.changelog.version.to_s
|
124
|
+
end
|
125
|
+
|
126
|
+
FileUtils.mv(tmp_dir, src_dir)
|
127
|
+
project = Project.new_from_project_file(src_dir + "/" + Helpers::PROJECT_FILE)
|
128
|
+
LOG.debug("Checked out to #{src_dir}")
|
129
|
+
|
130
|
+
if do_build
|
131
|
+
LOG.debug("Building package...")
|
132
|
+
build = Build.new(src_dir, project, :sign => options[:sign])
|
133
|
+
|
134
|
+
result = build.perform_from_cli!
|
135
|
+
if print_files?
|
136
|
+
result.files.each {|f| stdout.puts(f) }
|
137
|
+
end
|
138
|
+
tar_it_up(project, result) if tar_it
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
private
|
143
|
+
|
144
|
+
def tar_it_up(project, result)
|
145
|
+
files = result.files
|
146
|
+
tarfile = "#{project.source_package_name}-#{project.changelog.version}.tar"
|
147
|
+
exec("tar -cf #{tarfile} #{files.join(' ')}")
|
148
|
+
LOG.debug("Build products archived in to #{tarfile}")
|
149
|
+
stdout.puts(tarfile) if print_files?
|
150
|
+
end
|
151
|
+
|
152
|
+
def print_files?
|
153
|
+
options[:print_files]
|
154
|
+
end
|
155
|
+
|
156
|
+
def oneline_pattern
|
157
|
+
/^([a-z0-9]+) (.+)$/i
|
158
|
+
end
|
159
|
+
|
160
|
+
def log_command
|
161
|
+
"git --no-pager log --no-color --full-index"
|
162
|
+
end
|
163
|
+
|
164
|
+
def latest_commit_hash
|
165
|
+
output = exec(log_command + " --pretty=oneline -1").split("\n").first
|
166
|
+
oneline_pattern.match(output)[1]
|
167
|
+
end
|
168
|
+
|
169
|
+
def find_first_release_commit(project)
|
170
|
+
all_commits = exec(log_command + " --pretty=oneline").
|
171
|
+
split("\n")
|
172
|
+
|
173
|
+
all_commits.map { |commit_line|
|
174
|
+
match = oneline_pattern.match(commit_line)
|
175
|
+
[match[1], match[2]]
|
176
|
+
}.find {|hash, message|
|
177
|
+
project.release_name_from_message(message)
|
178
|
+
}
|
179
|
+
end
|
180
|
+
|
181
|
+
def move_to(pathspec)
|
182
|
+
begin
|
183
|
+
exec("git show #{pathspec} --")
|
184
|
+
rescue Exec::UnexpectedExitStatus => e
|
185
|
+
if /^fatal: bad revision/.match(e.stderr)
|
186
|
+
raise CLI::Exit, "Git pathspec '#{pathspec}' does not exist"
|
187
|
+
else
|
188
|
+
raise
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
exec("git checkout --track #{pathspec}")
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module MSPRelease
|
2
|
+
class CLI::Help < CLI::Command
|
3
|
+
|
4
|
+
description "Show help for vershunt and its sub-commands"
|
5
|
+
|
6
|
+
arg :command_name, "Name of command to see help for", :required => false
|
7
|
+
|
8
|
+
def run
|
9
|
+
command_name = arguments[:command_name]
|
10
|
+
command_class = MSPRelease::CLI.commands[command_name]
|
11
|
+
raise Climate::HelpNeeded.new(command_class || self)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module MSPRelease
|
2
|
+
class CLI::New < CLI::Command
|
3
|
+
|
4
|
+
include CLI::WorkingCopyCommand
|
5
|
+
|
6
|
+
description "Prepare master or a release branch for a release push"
|
7
|
+
|
8
|
+
opt :distribution, "Specify a new debian distribution to put in the " +
|
9
|
+
"changelog for this new version",
|
10
|
+
{
|
11
|
+
:short => 'd',
|
12
|
+
:long => 'debian-distribution',
|
13
|
+
:type => :string
|
14
|
+
}
|
15
|
+
|
16
|
+
opt :force, "Force creation of a release commit from a non-release branch", {
|
17
|
+
:short => 'f',
|
18
|
+
:long => 'force',
|
19
|
+
:default => false
|
20
|
+
}
|
21
|
+
|
22
|
+
def run
|
23
|
+
fail_if_push_pending
|
24
|
+
fail_if_modified_wc
|
25
|
+
fail_unless_on_release_branch
|
26
|
+
|
27
|
+
LOG.verbose
|
28
|
+
|
29
|
+
new_version = project.next_version_for_release(options)
|
30
|
+
|
31
|
+
self.data = {:version => new_version}
|
32
|
+
save_data
|
33
|
+
end
|
34
|
+
|
35
|
+
def not_on_release_branch_msg
|
36
|
+
"You must be on a release branch to create " +
|
37
|
+
"release commits, or use --force.\nSwitch to a release branch, or build " +
|
38
|
+
"from any branch without creating a release commit for development builds"
|
39
|
+
end
|
40
|
+
|
41
|
+
def fail_unless_on_release_branch
|
42
|
+
if git.cur_branch != project.branch_name
|
43
|
+
if options[:force]
|
44
|
+
LOG.error("Not on a release branch, forcing creation of release " +
|
45
|
+
"commit. #{git.cur_branch} != #{project.branch_name}")
|
46
|
+
else
|
47
|
+
raise CLI::Exit, not_on_release_branch_msg
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def get_next_release_number(suffix)
|
53
|
+
suffix_pattern = /([0-9]+)/
|
54
|
+
if suffix.nil? || suffix_pattern.match(suffix)
|
55
|
+
suffix.to_i + 1
|
56
|
+
else
|
57
|
+
raise CLI::Exit, "malformed suffix: #{suffix}\n" +
|
58
|
+
"Fix the changelog and try again"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module MSPRelease
|
2
|
+
class CLI::Push < CLI::Command
|
3
|
+
|
4
|
+
include CLI::WorkingCopyCommand
|
5
|
+
|
6
|
+
description "Push a new release to origin"
|
7
|
+
|
8
|
+
def run
|
9
|
+
unless data_exists?
|
10
|
+
raise CLI::Exit, "You need to stage a new release before you can push it"
|
11
|
+
end
|
12
|
+
|
13
|
+
load_data
|
14
|
+
release_name = "#{data[:version]}"
|
15
|
+
tagname = "release-#{release_name}"
|
16
|
+
|
17
|
+
if project.respond_to?(:project_specific_push)
|
18
|
+
project.project_specific_push(release_name)
|
19
|
+
end
|
20
|
+
|
21
|
+
exec "git tag #{tagname}"
|
22
|
+
exec "git push origin #{git.cur_branch}"
|
23
|
+
stdout.puts "Pushing new release tag: #{tagname}"
|
24
|
+
exec "git push origin #{tagname}"
|
25
|
+
|
26
|
+
remove_data
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module MSPRelease
|
2
|
+
class CLI::Reset < CLI::Command
|
3
|
+
|
4
|
+
include CLI::WorkingCopyCommand
|
5
|
+
|
6
|
+
description "Reset changes made by vershunt new"
|
7
|
+
|
8
|
+
def run
|
9
|
+
|
10
|
+
raise CLI::Exit, "No waiting changes" unless data_exists?
|
11
|
+
|
12
|
+
exec "git checkout #{project.changelog_path}"
|
13
|
+
remove_data
|
14
|
+
puts "Reset"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module MSPRelease
|
2
|
+
class CLI::Status < CLI::Command
|
3
|
+
|
4
|
+
include CLI::WorkingCopyCommand
|
5
|
+
|
6
|
+
description "Print out discovered release state"
|
7
|
+
|
8
|
+
def run
|
9
|
+
bits = []
|
10
|
+
|
11
|
+
if data_exists?
|
12
|
+
load_data
|
13
|
+
puts "Awaiting push. Please update the changelog, then run vershunt push "
|
14
|
+
bits.push(["Pending", data[:version]])
|
15
|
+
else
|
16
|
+
bits.push(["Project says", msp_version]) if msp_version
|
17
|
+
bits.push(["Release branch", on_release_branch?? git_version : nil])
|
18
|
+
|
19
|
+
if changelog
|
20
|
+
changelog_version = changelog.version
|
21
|
+
bits.push(["Changelog says", changelog_version])
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
bits.push(["Release commit", release_name_for_output])
|
27
|
+
|
28
|
+
format_bits(bits)
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def format_bits(bits)
|
34
|
+
bits = bits.map {|header, value| [header, value.nil?? '<none>' : value.to_s ]}
|
35
|
+
widths = bits.transpose.map { |column| column.map {|v| v.length }.max }
|
36
|
+
bits.each do |row|
|
37
|
+
puts row.zip(widths).map {|val, width| val.ljust(width) }.join(" : ").strip
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def release_name_for_output
|
42
|
+
commit = git.latest_commit(project)
|
43
|
+
commit.release_commit? && commit.release_name || nil
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,229 @@
|
|
1
|
+
class Debian
|
2
|
+
|
3
|
+
module Versions
|
4
|
+
|
5
|
+
module Versionable
|
6
|
+
def to_version
|
7
|
+
MSPRelease::Version.new(@major, @minor, @bugfix)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class Base
|
12
|
+
|
13
|
+
def self.new_if_matches(string)
|
14
|
+
pattern.match(string) && new_from_string(string)
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.new_from_string(string)
|
18
|
+
match = pattern.match(string)
|
19
|
+
parts = (1...match.length).map {|idx| match[idx] }
|
20
|
+
begin
|
21
|
+
new(*parts)
|
22
|
+
rescue => e
|
23
|
+
raise "Unable to construct #{self} from #{string}\n#{e.to_s}"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
class Unreleased < Base
|
30
|
+
|
31
|
+
include Versionable
|
32
|
+
|
33
|
+
def self.pattern
|
34
|
+
/^([0-9]+)\.([0-9]+)\.([0-9]+)$/
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.new_from_version(version)
|
38
|
+
new(version.major, version.minor, version.bugfix)
|
39
|
+
end
|
40
|
+
|
41
|
+
def initialize(major, minor, bugfix)
|
42
|
+
@major = major
|
43
|
+
@minor = minor
|
44
|
+
@bugfix = bugfix
|
45
|
+
end
|
46
|
+
|
47
|
+
def bump
|
48
|
+
Stable.new(@major, @minor, @bugfix, "1")
|
49
|
+
end
|
50
|
+
|
51
|
+
def to_s
|
52
|
+
[@major, @minor, @bugfix].join(".")
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
class Stable < Base
|
57
|
+
|
58
|
+
include Versionable
|
59
|
+
|
60
|
+
def self.pattern
|
61
|
+
/^([0-9]+)\.([0-9]+)\.([0-9]+)-([0-9]+)$/
|
62
|
+
end
|
63
|
+
|
64
|
+
def initialize(major, minor, bugfix, revision)
|
65
|
+
@major = major
|
66
|
+
@minor = minor
|
67
|
+
@bugfix = bugfix
|
68
|
+
@revision = revision
|
69
|
+
end
|
70
|
+
|
71
|
+
def bump
|
72
|
+
self.class.new(@major, @minor, @bugfix, @revision.to_i + 1).to_s
|
73
|
+
end
|
74
|
+
|
75
|
+
def to_s
|
76
|
+
[@major, @minor, @bugfix].join(".") + "-#{@revision}"
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
class Development < Base
|
82
|
+
|
83
|
+
class << self
|
84
|
+
include MSPRelease::Helpers
|
85
|
+
|
86
|
+
def pattern
|
87
|
+
/^([0-9]+)-git\+([a-f0-9]+)~([a-z0-9\+\.]+)$/
|
88
|
+
end
|
89
|
+
|
90
|
+
def new_from_working_directory(branch_name, commit_hash)
|
91
|
+
safe_branch_name = branch_name.gsub(/[^a-z0-9]/i, ".")
|
92
|
+
new(timestamp, commit_hash[0...6], safe_branch_name)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def initialize(timestamp, hash, branch_name)
|
97
|
+
@timestamp = timestamp
|
98
|
+
@hash = hash
|
99
|
+
@branch_name = branch_name
|
100
|
+
end
|
101
|
+
|
102
|
+
def to_s
|
103
|
+
"#{@timestamp}-git+#{@hash}~#{@branch_name}"
|
104
|
+
end
|
105
|
+
|
106
|
+
def bump
|
107
|
+
Stable.new(@major, @minor, @bugfix, "1")
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
class Unrecognized < Base
|
112
|
+
|
113
|
+
def self.pattern
|
114
|
+
/^(.+)$/
|
115
|
+
end
|
116
|
+
|
117
|
+
def initialize(chunk)
|
118
|
+
@chunk = chunk
|
119
|
+
end
|
120
|
+
|
121
|
+
def to_s ; @chunk ; end
|
122
|
+
def to_version ; nil ; end
|
123
|
+
end
|
124
|
+
|
125
|
+
|
126
|
+
end
|
127
|
+
|
128
|
+
def default_distribution ; "msp" ; end
|
129
|
+
|
130
|
+
def initialize(basedir, fname)
|
131
|
+
@fname = File.join(basedir, fname)
|
132
|
+
end
|
133
|
+
|
134
|
+
attr_reader :fname
|
135
|
+
|
136
|
+
def read_top_line
|
137
|
+
File.open(@fname, 'r') {|f|f.readline}
|
138
|
+
end
|
139
|
+
|
140
|
+
def version_classes
|
141
|
+
[Versions::Unreleased, Versions::Stable, Versions::Development]
|
142
|
+
end
|
143
|
+
|
144
|
+
def version
|
145
|
+
version_classes.each do |c|
|
146
|
+
v = c.new_if_matches(version_string_from_top_line) and
|
147
|
+
return v
|
148
|
+
end
|
149
|
+
Versions::Unrecognized.new(version_string_from_top_line)
|
150
|
+
end
|
151
|
+
|
152
|
+
def distribution_pattern
|
153
|
+
/([^ ]+ [^ ]+ )([^;]+)/
|
154
|
+
end
|
155
|
+
|
156
|
+
def distribution
|
157
|
+
(m = distribution_pattern.match(read_top_line)) && m[2]
|
158
|
+
end
|
159
|
+
|
160
|
+
def package_name
|
161
|
+
/[a-z0-9\-]+/.match(read_top_line)
|
162
|
+
end
|
163
|
+
|
164
|
+
def version_string_from_top_line
|
165
|
+
tline = read_top_line
|
166
|
+
match = /[a-z\-]+ \(([^\)]+)\)/.match(tline)
|
167
|
+
|
168
|
+
match && match[1] or
|
169
|
+
raise "could not parse version info from #{tline}"
|
170
|
+
end
|
171
|
+
|
172
|
+
def matches(version)
|
173
|
+
self.version == version
|
174
|
+
end
|
175
|
+
|
176
|
+
def amend(version, distribution=self.distribution)
|
177
|
+
# replace the first line
|
178
|
+
tline, *all = File.open(@fname, 'r') {|f|f.readlines}
|
179
|
+
cur_version = /^[^\(]+\(([^\)]+).+/.match(tline)[1]
|
180
|
+
tline = tline.gsub(cur_version, "#{version}").
|
181
|
+
gsub(distribution_pattern) {|m|"#{$1}#{distribution}" }
|
182
|
+
|
183
|
+
all.unshift(tline)
|
184
|
+
|
185
|
+
signoff_idx = all.index {|l| /^ -- .+$/.match(l) }
|
186
|
+
all[signoff_idx] = create_signoff
|
187
|
+
|
188
|
+
File.open(@fname, 'w') { |f| all.each {|l|f.puts(l) } }
|
189
|
+
|
190
|
+
version
|
191
|
+
end
|
192
|
+
|
193
|
+
def add(version, stub, distribution=self.distribution)
|
194
|
+
tline = create_top_line(version, distribution)
|
195
|
+
all = File.open(@fname, 'r') {|f| f.readlines }
|
196
|
+
new =
|
197
|
+
[
|
198
|
+
tline,
|
199
|
+
"",
|
200
|
+
" * #{stub}",
|
201
|
+
"",
|
202
|
+
create_signoff + "\n",
|
203
|
+
""
|
204
|
+
]
|
205
|
+
|
206
|
+
File.open(@fname, 'w') {|f| f.write(new.join("\n")); f.write(all.join) }
|
207
|
+
|
208
|
+
version
|
209
|
+
end
|
210
|
+
|
211
|
+
def reset_at(project_version)
|
212
|
+
Versions::Unreleased.new_from_version(project_version).bump
|
213
|
+
end
|
214
|
+
|
215
|
+
def create_signoff
|
216
|
+
date = MSPRelease.time_rfc
|
217
|
+
author = MSPRelease.author
|
218
|
+
" -- #{author.name} <#{author.email}> #{date}"
|
219
|
+
end
|
220
|
+
|
221
|
+
def create_top_line(v, distribution)
|
222
|
+
tline = "#{package_name} (#{v})"
|
223
|
+
|
224
|
+
# FIXME, un-hardcode this?
|
225
|
+
tline + " #{distribution}; urgency=low"
|
226
|
+
end
|
227
|
+
|
228
|
+
|
229
|
+
end
|