hg-port 0.0.0 → 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/hg-port +66 -76
- data/lib/hg-port.rb +12 -0
- data/lib/hg-port/gem_info.rb +12 -0
- data/lib/hg-port/option_parser_with_required_args.rb +48 -0
- data/lib/hg-port/version.rb +54 -0
- data/lib/hg-port/version_template.rb +29 -0
- metadata +7 -2
data/bin/hg-port
CHANGED
@@ -1,12 +1,54 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
require 'pathname'
|
3
|
+
require 'yaml'
|
3
4
|
require 'tempfile'
|
4
|
-
|
5
5
|
THIS_PATH = Pathname.new(__FILE__).realpath
|
6
6
|
THIS_DIR = THIS_PATH.dirname
|
7
7
|
THIS_BASE_NAME = THIS_PATH.basename
|
8
|
+
LIB_DIR = File.join(THIS_DIR, '..', 'lib', 'hg-port')
|
9
|
+
require File.join(LIB_DIR, 'gem_info')
|
10
|
+
require File.join(LIB_DIR, 'option_parser_with_required_args')
|
11
|
+
require File.join(LIB_DIR, 'version')
|
12
|
+
require File.join(LIB_DIR, 'version_template')
|
8
13
|
|
9
14
|
module Helper
|
15
|
+
def self.option_parser
|
16
|
+
@option_parser ||= OptionParserWithRequiredArgs.new do |p|
|
17
|
+
p.banner = "Usage: #{THIS_BASE_NAME} [options]"
|
18
|
+
|
19
|
+
p.on_required(:merge_version, '--merge-version MERGE-VERSION', 'Merge version at which forward port will begin') do |options, value|
|
20
|
+
options.merge_version = value
|
21
|
+
end
|
22
|
+
|
23
|
+
p.on_tail '-h', '--help', 'Show help' do
|
24
|
+
puts p
|
25
|
+
exit
|
26
|
+
end
|
27
|
+
|
28
|
+
p.on_tail '--version', 'Show version' do
|
29
|
+
puts HGPort::GemInfo.version_string
|
30
|
+
exit
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.read_config
|
36
|
+
config_file_name = nil
|
37
|
+
[
|
38
|
+
`hg root`.chomp,
|
39
|
+
ENV['HOME']
|
40
|
+
].each do |path|
|
41
|
+
temp = File.join(path, '.hgportrc')
|
42
|
+
if File.exist?(temp)
|
43
|
+
config_file_name = temp
|
44
|
+
break
|
45
|
+
end
|
46
|
+
end
|
47
|
+
raise RuntimeError.new('No configuration file found') unless config_file_name
|
48
|
+
|
49
|
+
YAML.load(File.open(config_file_name))
|
50
|
+
end
|
51
|
+
|
10
52
|
def self.fail(message, lines)
|
11
53
|
display_output(lines)
|
12
54
|
raise RuntimeError.new(message)
|
@@ -27,7 +69,7 @@ Switches:
|
|
27
69
|
--merge-version <version-branch>
|
28
70
|
|
29
71
|
Available versions:
|
30
|
-
#{versions.collect { |version| " #{version}" }.join("\n")}
|
72
|
+
#{versions.reverse.collect { |version| " #{version}" }.join("\n")}
|
31
73
|
|
32
74
|
EOS
|
33
75
|
end
|
@@ -62,74 +104,8 @@ module HGHelper
|
|
62
104
|
end
|
63
105
|
end
|
64
106
|
|
65
|
-
|
66
|
-
|
67
|
-
include Comparable
|
68
|
-
|
69
|
-
attr_reader :major, :minor
|
70
|
-
|
71
|
-
def self.parse(str)
|
72
|
-
return nil if str !~ /^v([0-9]+)\.([0-9]+)$/
|
73
|
-
new(Integer($1), Integer($2))
|
74
|
-
end
|
75
|
-
|
76
|
-
def <=>(other)
|
77
|
-
return 1 if other.nil?
|
78
|
-
|
79
|
-
delta = major - other.major
|
80
|
-
return 1 if delta > 0
|
81
|
-
return -1 if delta < 0
|
82
|
-
|
83
|
-
delta = minor - other.minor
|
84
|
-
return 1 if delta > 0
|
85
|
-
return -1 if delta < 0
|
86
|
-
0
|
87
|
-
end
|
88
|
-
|
89
|
-
def to_s
|
90
|
-
"v#{major}.#{minor}"
|
91
|
-
end
|
92
|
-
|
93
|
-
private
|
94
|
-
|
95
|
-
def initialize(major, minor)
|
96
|
-
@major = major
|
97
|
-
@minor = minor
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
class Options
|
102
|
-
attr_reader :merge_version
|
103
|
-
|
104
|
-
def self.parse(args, versions)
|
105
|
-
merge_version = nil
|
106
|
-
while arg = args.shift
|
107
|
-
case arg
|
108
|
-
when '--merge-version' then
|
109
|
-
temp = args.shift or raise RuntimeError.new('Value required for --merge-version')
|
110
|
-
merge_version = Version.parse(temp) or raise RuntimeError.new("Invalid value \"#{temp}\" for --merge-version")
|
111
|
-
else
|
112
|
-
raise RuntimeError.new("Unsupported switch \"#{arg}\"")
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
if !merge_version || !versions.include?(merge_version)
|
117
|
-
Helper.display_usage(versions)
|
118
|
-
return nil
|
119
|
-
end
|
120
|
-
|
121
|
-
new(merge_version)
|
122
|
-
end
|
123
|
-
|
124
|
-
private
|
125
|
-
|
126
|
-
def initialize(merge_version)
|
127
|
-
@merge_version = merge_version
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
def get_versions(branches)
|
132
|
-
branches.collect { |branch| Version.parse(branch)}.compact.sort
|
107
|
+
def get_versions(version_template, branches)
|
108
|
+
branches.collect { |branch| HGPort::Version.parse(version_template, branch)}.compact.sort
|
133
109
|
end
|
134
110
|
|
135
111
|
def forward_port(dir, merge_version, version)
|
@@ -138,7 +114,6 @@ def forward_port(dir, merge_version, version)
|
|
138
114
|
|
139
115
|
# Build commit message from preview
|
140
116
|
status, lines = HGHelper.run_hg(dir, "hg merge --preview #{merge_version}")
|
141
|
-
puts "LINES: #{lines.inspect}"
|
142
117
|
commit_message = <<-EOS
|
143
118
|
Automatic forward port from #{merge_version} to #{version}
|
144
119
|
|
@@ -188,15 +163,30 @@ end
|
|
188
163
|
|
189
164
|
dir = '.'
|
190
165
|
|
191
|
-
|
192
|
-
|
193
|
-
|
166
|
+
config = Helper.read_config
|
167
|
+
raise RuntimeError.new('No version template specified') unless config.include?('version_template')
|
168
|
+
|
169
|
+
version_template = HGPort::VersionTemplate.new(config['version_template'])
|
170
|
+
branches = HGHelper.get_branches(dir)
|
171
|
+
versions = get_versions(version_template, branches)
|
172
|
+
|
173
|
+
options = nil
|
174
|
+
begin
|
175
|
+
options, free_args = Helper.option_parser.run(ARGV)
|
176
|
+
rescue OptionParserWithRequiredArgs::RunError => e
|
177
|
+
$stderr.puts e.message
|
178
|
+
exit 1
|
179
|
+
end
|
180
|
+
|
181
|
+
exit 0 if ENV.include?('HG_PORT_TEST')
|
194
182
|
|
195
|
-
|
183
|
+
merge_version = HGPort::Version.parse(version_template, options.merge_version) or raise RuntimeError.new("Invalid merge version \"#{options.merge_version}\"")
|
184
|
+
current_branch_version = HGPort::Version.parse(version_template, HGHelper.current_branch(dir))
|
185
|
+
unless current_branch_version && merge_version == current_branch_version
|
196
186
|
raise RuntimeError.new("Check out merge version \"#{options.merge_version}\" before attempting a forward port")
|
197
187
|
end
|
198
188
|
|
199
|
-
merge_and_later_versions = versions.select { |version| version >=
|
189
|
+
merge_and_later_versions = versions.select { |version| version >= merge_version }
|
200
190
|
merge_and_later_versions.each_with_index do |version, index|
|
201
191
|
next if index == 0
|
202
192
|
unless forward_port(dir, merge_and_later_versions[index - 1], version)
|
data/lib/hg-port.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
require 'ostruct'
|
3
|
+
|
4
|
+
class OptionParserWithRequiredArgs < OptionParser
|
5
|
+
class RunError < Exception; end
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@required_arg_names = []
|
9
|
+
super
|
10
|
+
end
|
11
|
+
|
12
|
+
def on_required(arg_sym, *args, &block)
|
13
|
+
on *args, &block
|
14
|
+
@required_arg_names << arg_sym
|
15
|
+
end
|
16
|
+
|
17
|
+
def on(*args, &block)
|
18
|
+
super *args do |value|
|
19
|
+
block.call(@options, value)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def on_tail(*args, &block)
|
24
|
+
super *args do
|
25
|
+
block.call(@options)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def run(args)
|
30
|
+
@options = OpenStruct.new
|
31
|
+
cloned_args = args.clone
|
32
|
+
begin
|
33
|
+
parse!(cloned_args)
|
34
|
+
rescue OptionParser::InvalidOption, OptionParser::MissingArgument
|
35
|
+
message = $!.to_s + "\n\n" + self.to_s
|
36
|
+
raise RunError.new(message)
|
37
|
+
end
|
38
|
+
|
39
|
+
missing_arg_names = @required_arg_names.select { |arg_name| @options.send(arg_name).nil? }
|
40
|
+
if !missing_arg_names.empty?
|
41
|
+
message = "missing required option: #{missing_arg_names.join(', ')}\n\n" + self.to_s
|
42
|
+
raise RunError.new(message)
|
43
|
+
end
|
44
|
+
|
45
|
+
[@options, cloned_args]
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module HGPort
|
2
|
+
class Version
|
3
|
+
include Comparable
|
4
|
+
|
5
|
+
attr_reader :major, :minor, :patch
|
6
|
+
|
7
|
+
def self.parse(template, str)
|
8
|
+
values = template.parse(str)
|
9
|
+
return nil if values.nil?
|
10
|
+
major = values[:major]
|
11
|
+
minor = values[:minor]
|
12
|
+
patch = values[:patch]
|
13
|
+
return nil if major.nil? || minor.nil? || patch.nil?
|
14
|
+
|
15
|
+
new(template, major, minor, patch)
|
16
|
+
end
|
17
|
+
|
18
|
+
def <=>(other)
|
19
|
+
return 1 if other.nil?
|
20
|
+
|
21
|
+
delta = major - other.major
|
22
|
+
return 1 if delta > 0
|
23
|
+
return -1 if delta < 0
|
24
|
+
|
25
|
+
delta = minor - other.minor
|
26
|
+
return 1 if delta > 0
|
27
|
+
return -1 if delta < 0
|
28
|
+
|
29
|
+
delta = patch - other.patch
|
30
|
+
return 1 if delta > 0
|
31
|
+
return -1 if delta < 0
|
32
|
+
|
33
|
+
0
|
34
|
+
end
|
35
|
+
|
36
|
+
def to_s
|
37
|
+
@template.expand(
|
38
|
+
:major => major,
|
39
|
+
:minor => minor,
|
40
|
+
:patch => patch
|
41
|
+
)
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def initialize(template, major, minor, patch)
|
47
|
+
@template = template
|
48
|
+
@major = major
|
49
|
+
@minor = minor
|
50
|
+
@patch = patch
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module HGPort
|
2
|
+
class VersionTemplate
|
3
|
+
def initialize(template_str)
|
4
|
+
@template_str = template_str
|
5
|
+
|
6
|
+
@keys = []
|
7
|
+
pattern = Regexp.escape(@template_str).gsub(/(:\w+)/) do |colon_key|
|
8
|
+
key = colon_key[1..-1]
|
9
|
+
@keys << key.to_sym
|
10
|
+
"(?<#{key}>[0-9]+)"
|
11
|
+
end
|
12
|
+
|
13
|
+
@regexp = Regexp.new("^#{pattern}$")
|
14
|
+
end
|
15
|
+
|
16
|
+
def expand(values)
|
17
|
+
@template_str.gsub(/(:\w+)/) do |colon_key|
|
18
|
+
key_sym = colon_key[1..-1].to_sym
|
19
|
+
values[key_sym] || $1
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def parse(str)
|
24
|
+
match = @regexp.match(str)
|
25
|
+
match ? @keys.inject({}) { |memo, key| memo[key] = Integer(match[key]); memo } : nil
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hg-port
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-07-
|
12
|
+
date: 2013-07-26 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: Script to automate forward porting in Mercurial
|
15
15
|
email: rcook@rcook.org
|
@@ -19,6 +19,11 @@ extensions: []
|
|
19
19
|
extra_rdoc_files: []
|
20
20
|
files:
|
21
21
|
- MIT-LICENSE.txt
|
22
|
+
- lib/hg-port/option_parser_with_required_args.rb
|
23
|
+
- lib/hg-port/gem_info.rb
|
24
|
+
- lib/hg-port/version_template.rb
|
25
|
+
- lib/hg-port/version.rb
|
26
|
+
- lib/hg-port.rb
|
22
27
|
- bin/hg-port
|
23
28
|
homepage: https://bitbucket.org/rcook/hg-port
|
24
29
|
licenses:
|