hg-port 0.0.0 → 0.0.1

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.
@@ -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
- class Version
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
- versions = get_versions(HGHelper.get_branches(dir))
192
- options = Options.parse(ARGV.clone, versions)
193
- exit 1 if options.nil?
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
- unless options.merge_version.to_s == HGHelper.current_branch(dir)
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 >= options.merge_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)
@@ -0,0 +1,12 @@
1
+ require 'pathname'
2
+
3
+ module HGPort
4
+ autoload :Version, 'hg-port/version'
5
+
6
+ extend self
7
+ end
8
+
9
+ Dir[File.join(Pathname.new(__FILE__).realpath.dirname, 'hg-port', '*.rb')].each do |path|
10
+ require path
11
+ end
12
+
@@ -0,0 +1,12 @@
1
+ module HGPort
2
+ module GemInfo
3
+ MAJOR_VERSION = 0
4
+ MINOR_VERSION = 0
5
+ PATCH_VERSION = 1
6
+
7
+ def self.version_string
8
+ [MAJOR_VERSION, MINOR_VERSION, PATCH_VERSION].join('.')
9
+ end
10
+ end
11
+ end
12
+
@@ -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.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-23 00:00:00.000000000 Z
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: