locabulary 0.3.1 → 0.5.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 +4 -4
- data/.fasterer.yml +4 -0
- data/.hound.yml +1 -0
- data/.started-issues +0 -0
- data/Gemfile +0 -3
- data/README.md +4 -0
- data/Rakefile +11 -1
- data/data/administrative_units.json +27 -2
- data/data/college.json +10 -10
- data/data/spec.json +24 -0
- data/data/underclass_level.json +1 -1
- data/lib/locabulary.rb +85 -93
- data/lib/locabulary/commands/active_hierarchical_roots_command.rb +78 -0
- data/lib/locabulary/commands/active_items_for_command.rb +58 -0
- data/lib/locabulary/commands/build_ordered_hierarchical_tree_command.rb +80 -0
- data/lib/locabulary/exceptions.rb +11 -8
- data/lib/locabulary/facet_wrapper_for_item.rb +58 -0
- data/lib/locabulary/item.rb +40 -0
- data/lib/locabulary/items.rb +6 -27
- data/lib/locabulary/items/administrative_unit.rb +9 -37
- data/lib/locabulary/items/base.rb +43 -3
- data/lib/locabulary/json_creator.rb +4 -5
- data/lib/locabulary/schema.rb +4 -4
- data/lib/locabulary/utility.rb +42 -0
- data/lib/locabulary/version.rb +1 -1
- data/locabulary.gemspec +3 -2
- data/script/build-multi-commit-message +2 -0
- data/script/close-issue +125 -0
- data/script/start-issue +174 -0
- metadata +43 -16
|
@@ -52,9 +52,10 @@ module Locabulary
|
|
|
52
52
|
|
|
53
53
|
def initialize(attributes = {})
|
|
54
54
|
attribute_names.each do |key|
|
|
55
|
-
value = attributes
|
|
55
|
+
value = attributes[key] || attributes[key.to_s]
|
|
56
56
|
send("#{key}=", value)
|
|
57
57
|
end
|
|
58
|
+
@children = []
|
|
58
59
|
end
|
|
59
60
|
|
|
60
61
|
def to_h
|
|
@@ -89,9 +90,9 @@ module Locabulary
|
|
|
89
90
|
|
|
90
91
|
def <=>(other)
|
|
91
92
|
predicate_name_sort = predicate_name <=> other.predicate_name
|
|
92
|
-
return predicate_name_sort unless predicate_name_sort
|
|
93
|
+
return predicate_name_sort unless predicate_name_sort.zero?
|
|
93
94
|
presentation_sequence_sort = presentation_sequence <=> other.presentation_sequence
|
|
94
|
-
return presentation_sequence_sort unless presentation_sequence_sort
|
|
95
|
+
return presentation_sequence_sort unless presentation_sequence_sort.zero?
|
|
95
96
|
term_label <=> other.term_label
|
|
96
97
|
end
|
|
97
98
|
|
|
@@ -100,6 +101,45 @@ module Locabulary
|
|
|
100
101
|
def presentation_sequence
|
|
101
102
|
default_presentation_sequence || SORT_SEQUENCE_FOR_NIL
|
|
102
103
|
end
|
|
104
|
+
|
|
105
|
+
def children
|
|
106
|
+
@children.sort
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def add_child(*input)
|
|
110
|
+
@children += input
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
HIERARCHY_DELIMITER = '::'.freeze
|
|
114
|
+
def slugs
|
|
115
|
+
term_label.split(HIERARCHY_DELIMITER)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def self.hierarchy_delimiter
|
|
119
|
+
HIERARCHY_DELIMITER
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def parent_slugs
|
|
123
|
+
slugs[0..-2]
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def parent_term_label
|
|
127
|
+
parent_slugs.join(HIERARCHY_DELIMITER)
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def root_slug
|
|
131
|
+
slugs[0]
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def selectable?
|
|
135
|
+
children.count.zero?
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def selectable_label
|
|
139
|
+
slugs[-1]
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
alias selectable_id id
|
|
103
143
|
end
|
|
104
144
|
end
|
|
105
145
|
end
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
require "google/api_client"
|
|
2
1
|
require "google_drive"
|
|
3
2
|
require 'highline/import'
|
|
4
|
-
require 'locabulary'
|
|
5
|
-
require 'locabulary/
|
|
3
|
+
require 'locabulary/utility'
|
|
4
|
+
require 'locabulary/item'
|
|
6
5
|
require 'json'
|
|
7
6
|
|
|
8
7
|
module Locabulary
|
|
@@ -11,7 +10,7 @@ module Locabulary
|
|
|
11
10
|
def initialize(document_key, predicate_name, data_fetcher = default_data_fetcher)
|
|
12
11
|
@document_key = document_key
|
|
13
12
|
@predicate_name = predicate_name
|
|
14
|
-
@output_filepath =
|
|
13
|
+
@output_filepath = Utility.filename_for_predicate_name(predicate_name)
|
|
15
14
|
@data_fetcher = data_fetcher
|
|
16
15
|
end
|
|
17
16
|
|
|
@@ -54,7 +53,7 @@ module Locabulary
|
|
|
54
53
|
|
|
55
54
|
def convert_to_json(data)
|
|
56
55
|
json_array = data.map do |row|
|
|
57
|
-
Locabulary::
|
|
56
|
+
Locabulary::Item.build(row).to_h
|
|
58
57
|
end
|
|
59
58
|
@json_data = JSON.pretty_generate("predicate_name" => predicate_name, "values" => json_array)
|
|
60
59
|
end
|
data/lib/locabulary/schema.rb
CHANGED
|
@@ -4,14 +4,14 @@ require 'dry/validation/schema'
|
|
|
4
4
|
module Locabulary
|
|
5
5
|
# Responsible for providing a defined and clear schema for each of the locabulary items.
|
|
6
6
|
Schema = Dry::Validation.Schema do
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
required(:predicate_name).filled(format?: /\A[a-z_]+\Z/)
|
|
8
|
+
required(:values).each do
|
|
9
|
+
required(:term_label).filled(:str?)
|
|
10
10
|
optional(:description).maybe(:str?)
|
|
11
11
|
optional(:grouping).maybe(:str?)
|
|
12
12
|
optional(:affiliation).maybe(:str?)
|
|
13
13
|
optional(:default_presentation_sequence).maybe(:int?)
|
|
14
|
-
|
|
14
|
+
required(:activated_on).filled(format?: /\A\d{4}-\d{2}-\d{2}\Z/)
|
|
15
15
|
optional(:deactivated_on).maybe(format?: /\A\d{4}-\d{2}-\d{2}\Z/)
|
|
16
16
|
end
|
|
17
17
|
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
require 'date'
|
|
2
|
+
require 'json'
|
|
3
|
+
require 'locabulary/exceptions'
|
|
4
|
+
|
|
5
|
+
# :nodoc:
|
|
6
|
+
module Locabulary
|
|
7
|
+
# A service module providing methods that are common and useful for querying the
|
|
8
|
+
# underlying data sources.
|
|
9
|
+
module Utility
|
|
10
|
+
DATA_DIRECTORY = File.expand_path("../../../data/", __FILE__).freeze
|
|
11
|
+
def self.with_active_extraction_for(predicate_name, as_of)
|
|
12
|
+
json = JSON.parse(File.read(filename_for_predicate_name(predicate_name)))
|
|
13
|
+
json.fetch('values').each do |data|
|
|
14
|
+
yield(data) if data_is_active?(data, as_of)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def self.with_extraction_for(predicate_name)
|
|
19
|
+
json = JSON.parse(File.read(filename_for_predicate_name(predicate_name)))
|
|
20
|
+
json.fetch('values').each do |data|
|
|
21
|
+
yield(data)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def self.data_is_active?(data, as_of)
|
|
26
|
+
activated_on = Date.parse(data.fetch('activated_on'))
|
|
27
|
+
return false unless activated_on < as_of
|
|
28
|
+
deactivated_on_value = data['deactivated_on']
|
|
29
|
+
return true if deactivated_on_value.nil?
|
|
30
|
+
deactivated_on = Date.parse(deactivated_on_value)
|
|
31
|
+
return false unless deactivated_on >= as_of
|
|
32
|
+
true
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def self.filename_for_predicate_name(predicate_name)
|
|
36
|
+
filename = File.join(DATA_DIRECTORY, "#{File.basename(predicate_name)}.json")
|
|
37
|
+
return filename if File.exist?(filename)
|
|
38
|
+
raise Locabulary::Exceptions::MissingPredicateNameError, "Unable to find predicate_name: #{predicate_name}"
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
private_constant :Utility
|
|
42
|
+
end
|
data/lib/locabulary/version.rb
CHANGED
data/locabulary.gemspec
CHANGED
|
@@ -21,7 +21,7 @@ Gem::Specification.new do |spec|
|
|
|
21
21
|
|
|
22
22
|
spec.add_dependency "json", "~> 1.8"
|
|
23
23
|
spec.add_dependency "dry-configurable"
|
|
24
|
-
spec.add_dependency "
|
|
24
|
+
spec.add_dependency "activesupport", '~>4.0'
|
|
25
25
|
|
|
26
26
|
spec.add_development_dependency "dry-validation"
|
|
27
27
|
spec.add_development_dependency "bundler"
|
|
@@ -30,8 +30,9 @@ Gem::Specification.new do |spec|
|
|
|
30
30
|
spec.add_development_dependency "rake", "~> 10.0"
|
|
31
31
|
spec.add_development_dependency 'google_drive'
|
|
32
32
|
spec.add_development_dependency 'highline'
|
|
33
|
-
spec.add_development_dependency "activesupport", "~>4.0"
|
|
34
33
|
spec.add_development_dependency "rubocop"
|
|
35
34
|
spec.add_development_dependency "simplecov"
|
|
36
35
|
spec.add_development_dependency "codeclimate-test-reporter"
|
|
36
|
+
spec.add_development_dependency "fasterer"
|
|
37
|
+
spec.add_development_dependency "shoulda-matchers"
|
|
37
38
|
end
|
data/script/close-issue
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
#!/usr/bin/env ruby -wU
|
|
2
|
+
|
|
3
|
+
#*******************************************************************************
|
|
4
|
+
#
|
|
5
|
+
# CONFIGURATION OPTIONS
|
|
6
|
+
#
|
|
7
|
+
#*******************************************************************************
|
|
8
|
+
|
|
9
|
+
CONFIG_KEYS = [:REMOTE, :REPOSITORY_PATH, :STARTED_ISSUES_FILE].freeze
|
|
10
|
+
|
|
11
|
+
REPOSITORY_PATH = ENV.fetch('REPOSITORY_PATH') { File.expand_path(File.join(File.dirname(__FILE__), '../')) }
|
|
12
|
+
REMOTE = ENV.fetch('REMOTE', 'origin')
|
|
13
|
+
|
|
14
|
+
# TODO: Retrieve the dasherized issue from Github's API
|
|
15
|
+
STARTED_ISSUES_FILE = ENV.fetch('STARTED_ISSUES_FILE', '.started-issues')
|
|
16
|
+
|
|
17
|
+
#*******************************************************************************
|
|
18
|
+
#
|
|
19
|
+
# HELP OPTIONS
|
|
20
|
+
#
|
|
21
|
+
#*******************************************************************************
|
|
22
|
+
|
|
23
|
+
if ARGV.grep(/-h/i).size == 1
|
|
24
|
+
$stdout.puts ""
|
|
25
|
+
$stdout.puts "$ ./#{File.basename(__FILE__)} 123"
|
|
26
|
+
$stdout.puts ""
|
|
27
|
+
$stdout.puts "This script will close the current issue branch."
|
|
28
|
+
$stdout.puts ""
|
|
29
|
+
$stdout.puts "* Remove the started issue from the #{STARTED_ISSUES_FILE}"
|
|
30
|
+
$stdout.puts "* Make a commit closing the issue"
|
|
31
|
+
$stdout.puts ""
|
|
32
|
+
$stdout.puts "Note: There are steps to insure you have a clean working directory."
|
|
33
|
+
$stdout.puts "Note: If you have spaces in your configuration all bets are off!"
|
|
34
|
+
$stdout.puts ""
|
|
35
|
+
$stdout.puts "Current Configuration:"
|
|
36
|
+
CONFIG_KEYS.each do |key|
|
|
37
|
+
$stdout.puts "\t#{key}='#{Object.const_get(key)}'"
|
|
38
|
+
end
|
|
39
|
+
$stdout.puts ""
|
|
40
|
+
$stdout.puts "You can override the configuration option by adding the corresponding"
|
|
41
|
+
$stdout.puts "ENV variable."
|
|
42
|
+
$stdout.puts ""
|
|
43
|
+
$stdout.puts "Example:"
|
|
44
|
+
$stdout.puts "$ REMOTE=origin ./scripts/#{File.basename(__FILE__)}"
|
|
45
|
+
exit(0)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
#*******************************************************************************
|
|
49
|
+
#
|
|
50
|
+
# GUARD
|
|
51
|
+
#
|
|
52
|
+
#*******************************************************************************
|
|
53
|
+
|
|
54
|
+
# Guard that directories exist
|
|
55
|
+
[:REPOSITORY_PATH].each do |key|
|
|
56
|
+
repository_path = Object.const_get(key)
|
|
57
|
+
unless File.directory?(repository_path)
|
|
58
|
+
$stderr.puts "Expected directory for #{key} @ #{repository_path} to exist.\n\n"
|
|
59
|
+
$stderr.puts "See help for details on specifying #{key}.\n\n"
|
|
60
|
+
$stderr.puts "$ ./#{File.basename(__FILE__)} -h"
|
|
61
|
+
exit!(1)
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Guard that I know what the issue number is
|
|
66
|
+
current_branch = `cd #{REPOSITORY_PATH} && git branch | grep '^*'`.sub(/^\*\s*/, '').strip
|
|
67
|
+
|
|
68
|
+
if current_branch =~ /^(\d+)[^\d]/
|
|
69
|
+
ISSUE_NUMBER = $1.to_i
|
|
70
|
+
else
|
|
71
|
+
$stderr.puts "Expected to be able to determine issue number from branch #{current_branch} name @ #{REPOSITORY_PATH}.\n\n"
|
|
72
|
+
$stderr.puts "See help for more information.\n\n"
|
|
73
|
+
$stderr.puts "$ ./#{File.basename(__FILE__)} -h"
|
|
74
|
+
exit!(2)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Guard that we have a clean working directory
|
|
78
|
+
if `cd #{REPOSITORY_PATH} && git status --porcelain`.strip.size > 0
|
|
79
|
+
$stderr.puts "Repository @ #{REPOSITORY_PATH} did not have a clean working directory"
|
|
80
|
+
exit!(3)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Guard that the tests all pass
|
|
84
|
+
unless system("cd #{REPOSITORY_PATH} && bundle exec rake")
|
|
85
|
+
$stderr.puts "Your tests failed. Please review the above output."
|
|
86
|
+
exit!(4)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
#*******************************************************************************
|
|
90
|
+
#
|
|
91
|
+
# DO STUFF
|
|
92
|
+
#
|
|
93
|
+
#*******************************************************************************
|
|
94
|
+
|
|
95
|
+
started_issues_file_lines = File.read(File.join(REPOSITORY_PATH, STARTED_ISSUES_FILE)).split("\n")
|
|
96
|
+
|
|
97
|
+
File.open(STARTED_ISSUES_FILE, 'w+') do |file|
|
|
98
|
+
started_issues_file_lines.each do |line|
|
|
99
|
+
file.puts line unless line.to_i == ISSUE_NUMBER.to_i
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
`cd #{REPOSITORY_PATH}; git add #{STARTED_ISSUES_FILE}`
|
|
104
|
+
|
|
105
|
+
path_to_commit_message = File.expand_path(File.join(REPOSITORY_PATH, '../COMMIT.msg'))
|
|
106
|
+
begin
|
|
107
|
+
File.open(path_to_commit_message, 'w+') do |file|
|
|
108
|
+
file.puts "Closing issue #{ISSUE_NUMBER}"
|
|
109
|
+
file.puts ""
|
|
110
|
+
file.puts "Closes ##{ISSUE_NUMBER}"
|
|
111
|
+
file.puts ""
|
|
112
|
+
|
|
113
|
+
message = "$ ./script/#{File.basename(__FILE__)} #{ISSUE_NUMBER}"
|
|
114
|
+
CONFIG_KEYS.each_with_object(message) do |key, mem|
|
|
115
|
+
if ENV.key?(key.to_s)
|
|
116
|
+
mem = "#{key}=\"#{ENV[key.to_s].to_s}\" #{mem}"
|
|
117
|
+
end
|
|
118
|
+
mem
|
|
119
|
+
end
|
|
120
|
+
file.puts message
|
|
121
|
+
end
|
|
122
|
+
$stdout.puts `cd #{REPOSITORY_PATH} && git commit -F #{path_to_commit_message}`
|
|
123
|
+
ensure
|
|
124
|
+
File.unlink(path_to_commit_message) rescue true
|
|
125
|
+
end
|
data/script/start-issue
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
#!/usr/bin/env ruby -wU
|
|
2
|
+
|
|
3
|
+
#*******************************************************************************
|
|
4
|
+
#
|
|
5
|
+
# INTENT
|
|
6
|
+
#
|
|
7
|
+
# This script codifies the "moment" that someone starts "working" on an issue.
|
|
8
|
+
# The goal is leveraging git to capture both the opening and closing moments
|
|
9
|
+
# From those moments we can compute the elapsed time for resolving an issue.
|
|
10
|
+
#
|
|
11
|
+
# The script is "close" to where the developers are working, and is hopefully
|
|
12
|
+
# easier to incorporate with developer workflow. Without using this script, we
|
|
13
|
+
# have less precise "starting moment", if at all.
|
|
14
|
+
#
|
|
15
|
+
# The result is that we can now report two time-based attributes for issues:
|
|
16
|
+
#
|
|
17
|
+
# * Elapsed time: How long an issue took to complete
|
|
18
|
+
# * Estimated effort: How much time we think it will take to complete; This is
|
|
19
|
+
# not elapsed time but instead an amount of focused time.
|
|
20
|
+
#
|
|
21
|
+
# The conjecture is given those two time-based attributes we can begin
|
|
22
|
+
# improving the interpretation of our Feature estimates.
|
|
23
|
+
#
|
|
24
|
+
# Features will likely be comprised of a collection of issues; The estimate for
|
|
25
|
+
# a feature is much less precise and I believe is equal parts "Estimated Effort"
|
|
26
|
+
# and "Estimated Complexity".
|
|
27
|
+
#
|
|
28
|
+
#*******************************************************************************
|
|
29
|
+
|
|
30
|
+
#*******************************************************************************
|
|
31
|
+
#
|
|
32
|
+
# CONFIGURATION OPTIONS
|
|
33
|
+
#
|
|
34
|
+
#*******************************************************************************
|
|
35
|
+
|
|
36
|
+
CONFIG_KEYS = [:REMOTE, :FROM_BRANCH, :REPOSITORY_PATH, :ISSUE_TITLE, :STARTED_ISSUES_FILE].freeze
|
|
37
|
+
|
|
38
|
+
REPOSITORY_PATH = ENV.fetch('REPOSITORY_PATH') { File.expand_path(File.join(File.dirname(__FILE__), '../')) }
|
|
39
|
+
REMOTE = ENV.fetch('REMOTE', 'origin')
|
|
40
|
+
FROM_BRANCH = ENV.fetch('FROM_BRANCH', 'master')
|
|
41
|
+
|
|
42
|
+
issue_title_fetcher = lambda do
|
|
43
|
+
begin
|
|
44
|
+
remote_url = `cd #{REPOSITORY_PATH} && git config --get remote.#{REMOTE}.url`.strip
|
|
45
|
+
match = remote_url.match(/(\w+)\/(\w+)(?:\.git)?\Z/)
|
|
46
|
+
if match
|
|
47
|
+
require 'open-uri'
|
|
48
|
+
require 'json'
|
|
49
|
+
owner, repository = match.captures
|
|
50
|
+
document = open("https://api.github.com/repos/#{owner}/#{repository}/issues/#{ISSUE_NUMBER}.json").read
|
|
51
|
+
json = JSON.parse(document)
|
|
52
|
+
json.fetch('title').gsub(/\W+/, '-')
|
|
53
|
+
else
|
|
54
|
+
'issue-on-github'
|
|
55
|
+
end
|
|
56
|
+
rescue
|
|
57
|
+
'issue-on-github'
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# TODO: Retrieve the dasherized issue from Github's API
|
|
62
|
+
ISSUE_TITLE = ENV.fetch('ISSUE_TITLE', issue_title_fetcher)
|
|
63
|
+
STARTED_ISSUES_FILE = ENV.fetch('STARTED_ISSUES_FILE', '.started-issues')
|
|
64
|
+
|
|
65
|
+
#*******************************************************************************
|
|
66
|
+
#
|
|
67
|
+
# HELP OPTIONS
|
|
68
|
+
#
|
|
69
|
+
#*******************************************************************************
|
|
70
|
+
|
|
71
|
+
if ARGV.grep(/-h/i).size == 1
|
|
72
|
+
$stdout.puts ""
|
|
73
|
+
$stdout.puts "$ ./#{File.basename(__FILE__)} 123"
|
|
74
|
+
$stdout.puts ""
|
|
75
|
+
$stdout.puts "This script will create an issue branch and update the remote repository."
|
|
76
|
+
$stdout.puts ""
|
|
77
|
+
$stdout.puts "* Create a new branch for the given issue number"
|
|
78
|
+
$stdout.puts "* Touch and append the issue number to a tracking file"
|
|
79
|
+
$stdout.puts "* Write a rudimentary commit message"
|
|
80
|
+
$stdout.puts "* Push that commit up to #{REMOTE}"
|
|
81
|
+
$stdout.puts ""
|
|
82
|
+
$stdout.puts "Note: There are steps to insure you have a clean working directory."
|
|
83
|
+
$stdout.puts "Note: If you have spaces in your configuration all bets are off!"
|
|
84
|
+
$stdout.puts ""
|
|
85
|
+
$stdout.puts "Current Configuration:"
|
|
86
|
+
CONFIG_KEYS.each do |key|
|
|
87
|
+
$stdout.puts "\t#{key}='#{Object.const_get(key)}'"
|
|
88
|
+
end
|
|
89
|
+
$stdout.puts ""
|
|
90
|
+
$stdout.puts "You can override the configuration option by adding the corresponding"
|
|
91
|
+
$stdout.puts "ENV variable."
|
|
92
|
+
$stdout.puts ""
|
|
93
|
+
$stdout.puts "Example:"
|
|
94
|
+
$stdout.puts "$ REMOTE=origin ./scripts/#{File.basename(__FILE__)}"
|
|
95
|
+
exit(0)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
#*******************************************************************************
|
|
99
|
+
#
|
|
100
|
+
# GUARD
|
|
101
|
+
#
|
|
102
|
+
#*******************************************************************************
|
|
103
|
+
|
|
104
|
+
# Guard that I have an issue number
|
|
105
|
+
|
|
106
|
+
ISSUE_NUMBER = ARGV.shift
|
|
107
|
+
|
|
108
|
+
unless ISSUE_NUMBER =~ /^\d+$/
|
|
109
|
+
$stderr.puts "Expected first parameter to be an issue number for REPOSITORY.\n\n"
|
|
110
|
+
$stderr.puts "See help for details on specifying an issue number.\n\n"
|
|
111
|
+
$stderr.puts "$ ./#{File.basename(__FILE__)} -h"
|
|
112
|
+
exit!(1)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# Capture the issue_title
|
|
116
|
+
issue_title = ISSUE_TITLE.respond_to?(:call) ? ISSUE_TITLE.call : ISSUE_TITLE
|
|
117
|
+
|
|
118
|
+
# Guard that directories exist
|
|
119
|
+
[:REPOSITORY_PATH].each do |key|
|
|
120
|
+
repository_path = Object.const_get(key)
|
|
121
|
+
unless File.directory?(repository_path)
|
|
122
|
+
$stderr.puts "Expected directory for #{key} @ #{repository_path} to exist.\n\n"
|
|
123
|
+
$stderr.puts "See help for details on specifying #{key}.\n\n"
|
|
124
|
+
$stderr.puts "$ ./#{File.basename(__FILE__)} -h"
|
|
125
|
+
exit!(2)
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# Guard that we have a clean working directory
|
|
130
|
+
if `cd #{REPOSITORY_PATH} && git status --porcelain`.strip.size > 0
|
|
131
|
+
$stderr.puts "Repository @ #{REPOSITORY_PATH} did not have a clean working directory"
|
|
132
|
+
exit!(3)
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
#*******************************************************************************
|
|
136
|
+
#
|
|
137
|
+
# DO STUFF
|
|
138
|
+
#
|
|
139
|
+
#*******************************************************************************
|
|
140
|
+
|
|
141
|
+
`cd #{REPOSITORY_PATH} && git checkout #{FROM_BRANCH}`
|
|
142
|
+
`cd #{REPOSITORY_PATH} && git pull --rebase`
|
|
143
|
+
|
|
144
|
+
TO_BRANCH = "#{ISSUE_NUMBER}-#{issue_title.gsub(/\W+/, '-')}"
|
|
145
|
+
if `cd #{REPOSITORY_PATH} && git branch -l | grep '#{TO_BRANCH}$'`.strip.size > 0
|
|
146
|
+
$stderr.puts "ERROR: Branch #{TO_BRANCH} already exists"
|
|
147
|
+
exit!(4)
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
`cd #{REPOSITORY_PATH} && git checkout -b #{TO_BRANCH} && echo "#{ISSUE_NUMBER}" >> #{STARTED_ISSUES_FILE} && git add #{STARTED_ISSUES_FILE}`
|
|
151
|
+
|
|
152
|
+
path_to_commit_message = File.expand_path(File.join(REPOSITORY_PATH, '../COMMIT.msg'))
|
|
153
|
+
begin
|
|
154
|
+
File.open(path_to_commit_message, 'w+') do |file|
|
|
155
|
+
file.puts "Claiming issue #{ISSUE_NUMBER}"
|
|
156
|
+
file.puts ""
|
|
157
|
+
file.puts "relates to ##{ISSUE_NUMBER}"
|
|
158
|
+
file.puts ""
|
|
159
|
+
|
|
160
|
+
message = "$ ./script/#{File.basename(__FILE__)} #{ISSUE_NUMBER}"
|
|
161
|
+
CONFIG_KEYS.each_with_object(message) do |key, mem|
|
|
162
|
+
if ENV.key?(key.to_s)
|
|
163
|
+
mem = "#{key}=\"#{ENV[key.to_s].to_s}\" #{mem}"
|
|
164
|
+
end
|
|
165
|
+
mem
|
|
166
|
+
end
|
|
167
|
+
file.puts message
|
|
168
|
+
file.puts ""
|
|
169
|
+
file.puts "[skip ci]"
|
|
170
|
+
end
|
|
171
|
+
$stdout.puts `cd #{REPOSITORY_PATH} && git commit -F #{path_to_commit_message}`
|
|
172
|
+
ensure
|
|
173
|
+
File.unlink(path_to_commit_message) rescue true
|
|
174
|
+
end
|