schema-evolution-manager 0.9.24
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/README.md +334 -0
- data/bin/sem-add +46 -0
- data/bin/sem-apply +41 -0
- data/bin/sem-baseline +34 -0
- data/bin/sem-config +1 -0
- data/bin/sem-dist +92 -0
- data/bin/sem-info +43 -0
- data/bin/sem-init +95 -0
- data/lib/schema-evolution-manager.rb +26 -0
- data/lib/schema-evolution-manager/apply_util.rb +60 -0
- data/lib/schema-evolution-manager/args.rb +159 -0
- data/lib/schema-evolution-manager/ask.rb +44 -0
- data/lib/schema-evolution-manager/baseline_util.rb +50 -0
- data/lib/schema-evolution-manager/db.rb +104 -0
- data/lib/schema-evolution-manager/install_template.rb +118 -0
- data/lib/schema-evolution-manager/library.rb +176 -0
- data/lib/schema-evolution-manager/migration_file.rb +93 -0
- data/lib/schema-evolution-manager/preconditions.rb +61 -0
- data/lib/schema-evolution-manager/rdoc_usage.rb +37 -0
- data/lib/schema-evolution-manager/script_error.rb +19 -0
- data/lib/schema-evolution-manager/scripts.rb +95 -0
- data/lib/schema-evolution-manager/sem_info.rb +72 -0
- data/lib/schema-evolution-manager/sem_version.rb +9 -0
- data/lib/schema-evolution-manager/template.rb +39 -0
- data/lib/schema-evolution-manager/version.rb +71 -0
- data/scripts/20130318-105434.sql +64 -0
- data/scripts/20130318-105456.sql +135 -0
- data/template/README.md +28 -0
- data/template/dev.rb +12 -0
- metadata +80 -0
data/bin/sem-config
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
load File.join(File.dirname(__FILE__), '../lib/schema-evolution-manager.rb')
|
data/bin/sem-dist
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# == Creates a tarball containing SQL scripts that might need to be
|
3
|
+
# applied to a specific postgresql database. This tarball can then
|
4
|
+
# be uploaded, unpacked, and schema changes applied using
|
5
|
+
# schema-evolution-manager scripts
|
6
|
+
#
|
7
|
+
# == Usage
|
8
|
+
# sem-dist [--artifact_name <tag> --tag <tag>]
|
9
|
+
#
|
10
|
+
# name
|
11
|
+
# Optional artifact_name - defaults to the current directory name. Used in the
|
12
|
+
# actual artifact name which has the format <artifact_name>-<tag>.tar.gz
|
13
|
+
#
|
14
|
+
# tag
|
15
|
+
# Optional tag - if specified, we create a distribution file for this tag.
|
16
|
+
# If not specified, we create a new tag.
|
17
|
+
#
|
18
|
+
# == Example
|
19
|
+
# sem-dist
|
20
|
+
# Creates a new tag and generates the distribution file
|
21
|
+
#
|
22
|
+
# sem-dist --tag 0.0.1
|
23
|
+
# Creates a distribution file for the specified tag
|
24
|
+
#
|
25
|
+
|
26
|
+
load File.join(File.dirname(__FILE__), 'sem-config')
|
27
|
+
SchemaEvolutionManager::Library.set_verbose(true)
|
28
|
+
|
29
|
+
args = SchemaEvolutionManager::Args.from_stdin(:optional => ['artifact_name', 'tag'])
|
30
|
+
|
31
|
+
# On MAC OS X, use gnutar to avoid warnings like
|
32
|
+
# Ignoring unknown extended header keyword `SCHILY.ino'
|
33
|
+
tar_cmd = `which gnutar 2> /dev/null`.strip
|
34
|
+
if tar_cmd == ""
|
35
|
+
tar_cmd = "tar"
|
36
|
+
end
|
37
|
+
|
38
|
+
if args.tag
|
39
|
+
tag = args.tag
|
40
|
+
else
|
41
|
+
if latest = SchemaEvolutionManager::Library.latest_tag
|
42
|
+
suggested_tag = latest.next_micro.to_version_string
|
43
|
+
else
|
44
|
+
suggested_tag = "0.0.1"
|
45
|
+
end
|
46
|
+
|
47
|
+
tag = SchemaEvolutionManager::Ask.for_string("Version:", :default => suggested_tag)
|
48
|
+
if !SchemaEvolutionManager::Library.tag_exists?(tag)
|
49
|
+
SchemaEvolutionManager::Library.git_create_tag(tag)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
SchemaEvolutionManager::Library.git_assert_tag_exists(tag)
|
53
|
+
|
54
|
+
changes = SchemaEvolutionManager::Library.git_changes(:tag => tag)
|
55
|
+
repo_path = SchemaEvolutionManager::Library.normalize_path(`pwd`.strip)
|
56
|
+
|
57
|
+
if args.artifact_name
|
58
|
+
artifact_name = args.artifact_name
|
59
|
+
else
|
60
|
+
artifact_name = File.basename(repo_path)
|
61
|
+
end
|
62
|
+
|
63
|
+
filename = "%s-%s" % [artifact_name, tag]
|
64
|
+
|
65
|
+
dist_dir = File.join(repo_path, "dist")
|
66
|
+
SchemaEvolutionManager::Library.ensure_dir!(dist_dir)
|
67
|
+
tarball = File.join(dist_dir, "#{filename}.tar")
|
68
|
+
|
69
|
+
SchemaEvolutionManager::Library.with_temp_file do |tmp|
|
70
|
+
tmpdir = File.join(tmp, filename)
|
71
|
+
SchemaEvolutionManager::Library.ensure_dir!(tmpdir)
|
72
|
+
|
73
|
+
SchemaEvolutionManager::Library.system_or_error("cp -R %s %s" % [File.join(repo_path, "scripts"), File.join(tmpdir, "scripts")])
|
74
|
+
File.open(File.join(tmpdir, "CHANGES"), "w") { |out| out << changes }
|
75
|
+
|
76
|
+
Dir.chdir(tmp) do
|
77
|
+
SchemaEvolutionManager::Library.system_or_error("#{tar_cmd} cf #{filename}.tar #{filename}")
|
78
|
+
FileUtils.cp("#{filename}.tar", tarball)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
gzip_file = "#{tarball}.gz"
|
83
|
+
if File.exists?(gzip_file)
|
84
|
+
puts "Removing old gzip file at #{gzip_file}"
|
85
|
+
FileUtils.rm(gzip_file)
|
86
|
+
end
|
87
|
+
|
88
|
+
command = "gzip #{tarball}"
|
89
|
+
SchemaEvolutionManager::Library.system_or_error(command)
|
90
|
+
|
91
|
+
puts ""
|
92
|
+
puts "Created distribution file at #{gzip_file}"
|
data/bin/sem-info
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# Usage
|
3
|
+
#
|
4
|
+
# sem-info command [arg1...]
|
5
|
+
#
|
6
|
+
# sem-info tag exists 1.2.3
|
7
|
+
# Returns true if the specified tag exists,
|
8
|
+
# false otherwise
|
9
|
+
#
|
10
|
+
# sem-info tag latest
|
11
|
+
# Display the latest tag
|
12
|
+
#
|
13
|
+
# sem-info version
|
14
|
+
# Display the version of schema-evolution-manager
|
15
|
+
#
|
16
|
+
# sem-info tag next [major|minor|micro]
|
17
|
+
# Output information on the next tag. Defaults to micro
|
18
|
+
# version increment from latest tag
|
19
|
+
#
|
20
|
+
# Description
|
21
|
+
#
|
22
|
+
# Utility script to pull information from the schema-evolution-manager
|
23
|
+
# libraries. Initially designed to help with wrapper scripts that
|
24
|
+
# needed information (like the next minor tag)
|
25
|
+
#
|
26
|
+
|
27
|
+
load File.join(File.dirname(__FILE__), 'sem-config')
|
28
|
+
|
29
|
+
command = ARGV.shift.to_s.strip
|
30
|
+
|
31
|
+
if command == "tag"
|
32
|
+
puts SchemaEvolutionManager::SemInfo.tag(ARGV)
|
33
|
+
|
34
|
+
elsif command == "version"
|
35
|
+
puts SchemaEvolutionManager::SemInfo.version(ARGV)
|
36
|
+
|
37
|
+
else
|
38
|
+
if command != ""
|
39
|
+
puts "ERROR: Unrecognized command[%s]" % command
|
40
|
+
puts ""
|
41
|
+
end
|
42
|
+
SchemaEvolutionManager::RdocUsage.printAndExit(1)
|
43
|
+
end
|
data/bin/sem-init
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# == Initializes an existing git repository to support schema evolutions managed
|
3
|
+
# by schema-evolution-manager
|
4
|
+
#
|
5
|
+
# == Usage
|
6
|
+
# sem-init --dir <dir> --url <url>
|
7
|
+
# or
|
8
|
+
# sem-init --dir <dir> --host <database host> --user <db user> --name <db name>
|
9
|
+
#
|
10
|
+
# dir: The directory containing a git repository that will contain the schema evolution files
|
11
|
+
# url: The connection string for the psql database
|
12
|
+
#
|
13
|
+
# == Example
|
14
|
+
# git init /tmp/example_repo
|
15
|
+
# bin/sem-init --dir /tmp/example_repo --url postgresql://username@localhost/sample
|
16
|
+
#
|
17
|
+
|
18
|
+
load File.join(File.dirname(__FILE__), 'sem-config')
|
19
|
+
SchemaEvolutionManager::Library.set_verbose(true)
|
20
|
+
|
21
|
+
args = SchemaEvolutionManager::Args.from_stdin(:required => %w(dir), :optional => %w(url host port name user))
|
22
|
+
SchemaEvolutionManager::Preconditions.check_state(File.directory?(args.dir), "Dir[%s] does not exist" % args.dir)
|
23
|
+
|
24
|
+
if args.url.nil? && args.name.nil?
|
25
|
+
puts "Must specify either url or name"
|
26
|
+
exit(1)
|
27
|
+
end
|
28
|
+
|
29
|
+
db = SchemaEvolutionManager::Db.from_args(args)
|
30
|
+
|
31
|
+
def copy_file(source, target, substitutions)
|
32
|
+
template = SchemaEvolutionManager::Template.new
|
33
|
+
substitutions.each do |name, value|
|
34
|
+
template.add(name, value)
|
35
|
+
end
|
36
|
+
final = template.parse(IO.read(source))
|
37
|
+
File.open(target, "w") do |os|
|
38
|
+
os << final
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
template_dir = File.join(SchemaEvolutionManager::Library.base_dir, "template")
|
43
|
+
SchemaEvolutionManager::Preconditions.check_state(File.directory?(template_dir),
|
44
|
+
"Could not find schema-evolution-manager/template subdir. Expected it at[%s]" % [template_dir])
|
45
|
+
|
46
|
+
subs = {
|
47
|
+
"url" => db.url,
|
48
|
+
"add_script_path" => File.join(SchemaEvolutionManager::Library.base_dir, "bin/sem-add")
|
49
|
+
}
|
50
|
+
|
51
|
+
puts "chdir %s" % args.dir
|
52
|
+
Dir.chdir(args.dir) do
|
53
|
+
|
54
|
+
wrappers = []
|
55
|
+
Dir.glob("#{template_dir}/*").each do |path|
|
56
|
+
wrapper = File.basename(path)
|
57
|
+
if !File.exists?(wrapper)
|
58
|
+
puts "Creating wrapper script #{wrapper}"
|
59
|
+
copy_file(path, wrapper, subs)
|
60
|
+
SchemaEvolutionManager::Library.system_or_error("chmod +x #{wrapper}")
|
61
|
+
SchemaEvolutionManager::Library.system_or_error("git add #{wrapper}")
|
62
|
+
wrappers << wrapper
|
63
|
+
end
|
64
|
+
end
|
65
|
+
if !wrappers.empty?
|
66
|
+
SchemaEvolutionManager::Library.system_or_error("git commit -m 'Add schema-evolution-manager wrapper scripts' #{wrappers.join(" ")}")
|
67
|
+
end
|
68
|
+
|
69
|
+
readme = "README.md"
|
70
|
+
if !File.exists?(readme)
|
71
|
+
puts "Creating #{readme}"
|
72
|
+
copy_file("schema-evolution-manager/template/README.md", "README.md", subs)
|
73
|
+
SchemaEvolutionManager::Library.system_or_error("git add #{readme}")
|
74
|
+
SchemaEvolutionManager::Library.system_or_error("git commit -m 'Adding README.md' README.md")
|
75
|
+
end
|
76
|
+
|
77
|
+
if !File.exists?("scripts")
|
78
|
+
SchemaEvolutionManager::Library.system_or_error("mkdir scripts")
|
79
|
+
SchemaEvolutionManager::Library.system_or_error("touch scripts/.exists")
|
80
|
+
SchemaEvolutionManager::Library.system_or_error("git add scripts/.exists")
|
81
|
+
SchemaEvolutionManager::Library.system_or_error("git commit -m 'Adding scripts directory' scripts/.exists")
|
82
|
+
end
|
83
|
+
|
84
|
+
# Create the first git tag if necessary
|
85
|
+
tags = SchemaEvolutionManager::Library.system_or_error("git tag -l")
|
86
|
+
if tags.nil? || tags == ""
|
87
|
+
puts "Creating initial git tag (0.0.1)"
|
88
|
+
SchemaEvolutionManager::Library.git_create_tag("0.0.1")
|
89
|
+
end
|
90
|
+
|
91
|
+
if SchemaEvolutionManager::Library.git_has_remote?
|
92
|
+
SchemaEvolutionManager::Library.system_or_error("git push origin master")
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'pathname'
|
3
|
+
|
4
|
+
dir = File.dirname(__FILE__)
|
5
|
+
lib_dir = File.join(dir, "schema-evolution-manager")
|
6
|
+
|
7
|
+
load File.join(lib_dir, 'preconditions.rb')
|
8
|
+
load File.join(lib_dir, 'rdoc_usage.rb')
|
9
|
+
load File.join(lib_dir, 'library.rb')
|
10
|
+
|
11
|
+
# Need to set base_dir early - version.rb depends on dir being set
|
12
|
+
SchemaEvolutionManager::Library.set_base_dir(File.join(dir, '..'))
|
13
|
+
|
14
|
+
load File.join(lib_dir, 'sem_version.rb')
|
15
|
+
load File.join(lib_dir, 'ask.rb')
|
16
|
+
load File.join(lib_dir, 'version.rb')
|
17
|
+
load File.join(lib_dir, 'args.rb')
|
18
|
+
load File.join(lib_dir, 'scripts.rb')
|
19
|
+
load File.join(lib_dir, 'db.rb')
|
20
|
+
load File.join(lib_dir, 'apply_util.rb')
|
21
|
+
load File.join(lib_dir, 'baseline_util.rb')
|
22
|
+
load File.join(lib_dir, 'template.rb')
|
23
|
+
load File.join(lib_dir, 'install_template.rb')
|
24
|
+
load File.join(lib_dir, 'script_error.rb')
|
25
|
+
load File.join(lib_dir, 'sem_info.rb')
|
26
|
+
load File.join(lib_dir, 'migration_file.rb')
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module SchemaEvolutionManager
|
2
|
+
|
3
|
+
class ApplyUtil
|
4
|
+
|
5
|
+
def initialize(db, opts={})
|
6
|
+
@dry_run = opts.delete(:dry_run)
|
7
|
+
if @dry_run.nil?
|
8
|
+
@dry_run = true
|
9
|
+
end
|
10
|
+
|
11
|
+
@db = Preconditions.assert_class(db, Db)
|
12
|
+
@scripts = Scripts.new(@db, Scripts::SCRIPTS)
|
13
|
+
end
|
14
|
+
|
15
|
+
def dry_run?
|
16
|
+
@dry_run
|
17
|
+
end
|
18
|
+
|
19
|
+
# Applies scripts in order, returning number of scripts applied
|
20
|
+
def apply!(dir)
|
21
|
+
Preconditions.check_state(File.directory?(dir),
|
22
|
+
"Dir[%s] does not exist" % dir)
|
23
|
+
|
24
|
+
count = 0
|
25
|
+
@scripts.each_pending(dir) do |filename, path|
|
26
|
+
count += 1
|
27
|
+
if @dry_run
|
28
|
+
puts "[DRY RUN] Applying #{filename}"
|
29
|
+
apply_dry_run(filename, path)
|
30
|
+
else
|
31
|
+
puts "Applying #{filename}"
|
32
|
+
apply_real(filename, path)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
count
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
def apply_dry_run(filename, path)
|
40
|
+
puts path
|
41
|
+
puts ""
|
42
|
+
end
|
43
|
+
|
44
|
+
def apply_real(filename, path)
|
45
|
+
have_error = true
|
46
|
+
begin
|
47
|
+
@db.psql_file(path)
|
48
|
+
have_error = false
|
49
|
+
ensure
|
50
|
+
if have_error
|
51
|
+
raise ScriptError.new(@db, filename)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
@scripts.record_as_run!(filename)
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
@@ -0,0 +1,159 @@
|
|
1
|
+
module SchemaEvolutionManager
|
2
|
+
|
3
|
+
# Container for common args, mainly to have stricter validation on
|
4
|
+
# inputs. Tried to use GetoptLong but could not write solid unit
|
5
|
+
# tests around it... so we have our own internal simple implementation.
|
6
|
+
class Args
|
7
|
+
|
8
|
+
if !defined?(FLAGS_WITH_ARGUMENTS)
|
9
|
+
FLAGS_WITH_ARGUMENTS = {
|
10
|
+
:artifact_name => "Specifies the name of the artifact. Tag will be appeneded to this name",
|
11
|
+
:user => "Connect to the database as this username instead of the default",
|
12
|
+
:host => "Specifies the host name of the machine on which the server is running",
|
13
|
+
:port => "Specifies the port on which the server is running",
|
14
|
+
:name => "Specifies the name of the database to which to connect",
|
15
|
+
:url => "Connect to the database as this username instead of the default",
|
16
|
+
:dir => "Path to a directory",
|
17
|
+
:tag => "A git tag (e.g. 0.0.1)",
|
18
|
+
:prefix => "Configure installer to use this prefix"
|
19
|
+
}
|
20
|
+
|
21
|
+
FLAGS_NO_ARGUMENTS = {
|
22
|
+
:dry_run => "Include flag to echo commands that will run without actually executing them",
|
23
|
+
:help => "Display help",
|
24
|
+
:verbose => "Enable verbose logging of all system calls",
|
25
|
+
}
|
26
|
+
end
|
27
|
+
|
28
|
+
attr_reader :artifact_name, :host, :port, :name, :prefix, :url, :user, :dir, :dry_run, :tag
|
29
|
+
|
30
|
+
# args: Actual string arguments
|
31
|
+
# :required => list of parameters that are required
|
32
|
+
# :optional => list of parameters that are optional
|
33
|
+
def initialize(args, opts={})
|
34
|
+
Preconditions.assert_class_or_nil(args, String)
|
35
|
+
required = (opts.delete(:required) || []).map { |flag| format_flag(flag) }
|
36
|
+
optional = (opts.delete(:optional) || []).map { |flag| format_flag(flag) }
|
37
|
+
Preconditions.assert_class(required, Array)
|
38
|
+
Preconditions.assert_class(optional, Array)
|
39
|
+
Preconditions.assert_empty_opts(opts)
|
40
|
+
Preconditions.check_state(optional.size + required.size > 0,
|
41
|
+
"Must have at least 1 optional or required parameter")
|
42
|
+
|
43
|
+
if !optional.include?(:help)
|
44
|
+
optional << :help
|
45
|
+
end
|
46
|
+
if !optional.include?(:verbose)
|
47
|
+
optional << :verbose
|
48
|
+
end
|
49
|
+
|
50
|
+
found_arguments = parse_string_arguments(args)
|
51
|
+
missing = required.select { |field| blank?(found_arguments[field]) }
|
52
|
+
|
53
|
+
@artifact_name = found_arguments.delete(:artifact_name)
|
54
|
+
@host = found_arguments.delete(:host)
|
55
|
+
@port = found_arguments.delete(:port)
|
56
|
+
@name = found_arguments.delete(:name)
|
57
|
+
@prefix = found_arguments.delete(:prefix)
|
58
|
+
@url = found_arguments.delete(:url)
|
59
|
+
@user = found_arguments.delete(:user)
|
60
|
+
@dir = found_arguments.delete(:dir)
|
61
|
+
@tag = found_arguments.delete(:tag)
|
62
|
+
|
63
|
+
@dry_run = found_arguments.delete(:dry_run)
|
64
|
+
@help = found_arguments.delete(:help)
|
65
|
+
@verbose = found_arguments.delete(:verbose)
|
66
|
+
|
67
|
+
Preconditions.check_state(found_arguments.empty?,
|
68
|
+
"Did not handle all flags: %s" % found_arguments.keys.join(" "))
|
69
|
+
|
70
|
+
if @help
|
71
|
+
RdocUsage.printAndExit(0)
|
72
|
+
end
|
73
|
+
|
74
|
+
if @verbose
|
75
|
+
Library.set_verbose(true)
|
76
|
+
end
|
77
|
+
|
78
|
+
if !missing.empty?
|
79
|
+
missing_fields_error(required, optional, missing)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# Hack to minimize bleeding from STDIN. Returns an instance of Args class
|
84
|
+
def Args.from_stdin(opts)
|
85
|
+
values = ARGV.join(" ")
|
86
|
+
Args.new(values, opts)
|
87
|
+
end
|
88
|
+
|
89
|
+
private
|
90
|
+
def blank?(value)
|
91
|
+
value.to_s.strip == ""
|
92
|
+
end
|
93
|
+
|
94
|
+
def missing_fields_error(required, optional, fields)
|
95
|
+
Preconditions.assert_class(fields, Array)
|
96
|
+
Preconditions.check_state(!fields.empty?, "Missing fields cannot be empty")
|
97
|
+
|
98
|
+
title = fields.size == 1 ? "Missing parameter" : "Missing parameters"
|
99
|
+
sorted = fields.sort_by { |f| f.to_s }
|
100
|
+
|
101
|
+
puts "**************************************************"
|
102
|
+
puts "ERROR: #{title}: #{sorted.join(", ")}"
|
103
|
+
puts "**************************************************"
|
104
|
+
puts help_parameters("Required parameters", required)
|
105
|
+
puts help_parameters("Optional parameters", optional)
|
106
|
+
exit(1)
|
107
|
+
end
|
108
|
+
|
109
|
+
def help_parameters(title, parameters)
|
110
|
+
docs = []
|
111
|
+
if !parameters.empty?
|
112
|
+
docs << ""
|
113
|
+
docs << title
|
114
|
+
docs << "-------------------"
|
115
|
+
parameters.each do |flag|
|
116
|
+
documentation = FLAGS_WITH_ARGUMENTS[flag] || FLAGS_NO_ARGUMENTS[flag]
|
117
|
+
Preconditions.check_not_null(documentation, "No documentation found for flag[%s]" % flag)
|
118
|
+
docs << " --#{flag}"
|
119
|
+
docs << " " + documentation
|
120
|
+
docs << ""
|
121
|
+
end
|
122
|
+
end
|
123
|
+
docs.join("\n")
|
124
|
+
end
|
125
|
+
|
126
|
+
|
127
|
+
def parse_string_arguments(args)
|
128
|
+
Preconditions.assert_class_or_nil(args, String)
|
129
|
+
found = {}
|
130
|
+
index = 0
|
131
|
+
values = args.to_s.strip.split(/\s+/)
|
132
|
+
while index < values.length do
|
133
|
+
flag = format_flag(values[index])
|
134
|
+
index += 1
|
135
|
+
|
136
|
+
if FLAGS_WITH_ARGUMENTS.has_key?(flag)
|
137
|
+
found[flag] = values[index]
|
138
|
+
index += 1
|
139
|
+
|
140
|
+
elsif FLAGS_NO_ARGUMENTS.has_key?(flag)
|
141
|
+
found[flag] = true
|
142
|
+
|
143
|
+
else
|
144
|
+
raise "Unknown flag[%s]" % flag
|
145
|
+
end
|
146
|
+
|
147
|
+
end
|
148
|
+
found
|
149
|
+
end
|
150
|
+
|
151
|
+
# Strip leading dashes and convert to symbol
|
152
|
+
def format_flag(flag)
|
153
|
+
Preconditions.assert_class(flag, String)
|
154
|
+
flag.sub(/^\-\-/, '').to_sym
|
155
|
+
end
|
156
|
+
|
157
|
+
end
|
158
|
+
|
159
|
+
end
|