torque 0.3.1 → 0.4.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/README.md +79 -3
- data/VERSION +2 -2
- data/bin/config +24 -13
- data/bin/email +10 -20
- data/bin/format +170 -0
- data/bin/project +14 -23
- data/bin/torque +27 -21
- data/lib/torque.rb +20 -34
- data/lib/torque/date_settings.rb +2 -2
- data/lib/torque/field_filter.rb +8 -9
- data/lib/torque/file_system.rb +6 -6
- data/lib/torque/format_string.rb +107 -0
- data/lib/torque/iteration.rb +1 -1
- data/lib/torque/mailer.rb +0 -5
- data/lib/torque/pivotal.rb +8 -8
- data/lib/torque/pivotal_html_parser.rb +2 -2
- data/lib/torque/project/project.rb +4 -0
- data/lib/torque/project/project_manager.rb +4 -5
- data/lib/torque/record_pathname_settings.rb +1 -1
- data/lib/torque/settings.rb +19 -11
- data/lib/torque/story.rb +32 -21
- data/lib/torque/torque_info_parser.rb +20 -8
- data/lib/torque/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4b758a1a40b981493fc10c574974eddb9d65aa6c
|
4
|
+
data.tar.gz: 9e937f2bbeb8e3af7b6b1939d61014c8b5f96d29
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 74e771fe69f47007a1badc7cd1b33e24dc1f077ef1025a433549abe4e8f42ab6b1876196d1f8fcfd0380138fbbb06b6f30b29a40730f6ba57e8ab3d4731860db
|
7
|
+
data.tar.gz: 16205617e5a71c342f41611cb74b103ff966111970098c59f7121ba29d6ce1448fa11503f6b82be0f3260e201f99660bd40ba8c9fafc2525a69860084d2ccbc2
|
data/README.md
CHANGED
@@ -91,17 +91,22 @@ To filter your results by story label, owner or type:
|
|
91
91
|
# torque --owner "list + of , owners"
|
92
92
|
# torque --type "list, of + story types"
|
93
93
|
|
94
|
-
When using filters
|
94
|
+
When using filters:
|
95
|
+
* "," => OR
|
96
|
+
* "+" => AND
|
97
|
+
* "+" is evaluated before ","
|
98
|
+
|
99
|
+
For example, "ios + android, ios + web" becomes
|
95
100
|
|
96
101
|
("ios" AND "android") OR ("ios" AND "web")
|
97
102
|
|
98
|
-
|
103
|
+
The "owner" filter will try to match against first/middle/last names as well as full names. For instance, '--owner Lee' will match stories owned by (eg) "Lee Grant", "Jake Lee", or "John Lee Jones".
|
99
104
|
|
100
105
|
To email the release notes from a personal email to Torque's mailing list:
|
101
106
|
|
102
107
|
# torque --email
|
103
108
|
|
104
|
-
Running with
|
109
|
+
Running with '-v/--verbose' will print a running list of stories as they are added. Running with '-s/--silent' will silence all output.
|
105
110
|
|
106
111
|
To display all available Pivotal Tracker projects or change your current project:
|
107
112
|
|
@@ -111,6 +116,77 @@ To set up automatic emailing of the notes and add/remove from the mailing list:
|
|
111
116
|
|
112
117
|
# torque email
|
113
118
|
|
119
|
+
To view/change the format of the notes that Torque generates:
|
120
|
+
|
121
|
+
# torque format
|
122
|
+
|
123
|
+
Formatting
|
124
|
+
----------
|
125
|
+
|
126
|
+
By default, stories are formatted like this:
|
127
|
+
|
128
|
+
12345678
|
129
|
+
Story Name
|
130
|
+
Accepted on 2012/12/21
|
131
|
+
https://www.pivotaltracker.com/story/show/12345678
|
132
|
+
Short description of story goes here
|
133
|
+
- This is a side note
|
134
|
+
- This is another side note
|
135
|
+
|
136
|
+
To change the way that stories are formatted, use 'torque format -s/--set'. Alternately, use 'torque format -e/--example' to see some sample output from a new format.
|
137
|
+
|
138
|
+
The format is set by way of a "formatting string", a mix of plain text and parameters (eg "%a") that act as placeholders for elements of a story.
|
139
|
+
|
140
|
+
Parameters:
|
141
|
+
* %a => Date accepted (MM/DD)
|
142
|
+
* %A => Date accepted (YYYY/MM/DD)
|
143
|
+
* %d => Description
|
144
|
+
* %D => Description (tabbed once on each newline)
|
145
|
+
* %e => Estimate
|
146
|
+
* %i => ID
|
147
|
+
* %l => Labels (separated by ", ")
|
148
|
+
* %n => Newline character
|
149
|
+
* %N => Name
|
150
|
+
* %o => Owner of the story
|
151
|
+
* %p => ID of the story's project
|
152
|
+
* %u => URL pointing to the story
|
153
|
+
* %t => Tab character
|
154
|
+
* %T => Type (feature, bug, etc)
|
155
|
+
|
156
|
+
Exit Codes
|
157
|
+
----------
|
158
|
+
|
159
|
+
The following is a list of exit codes that are thrown on various errors for each of the Torque scripts.
|
160
|
+
|
161
|
+
(general)
|
162
|
+
3 Invalid arguments
|
163
|
+
4 Cannot connect to Pivotal Tracker API
|
164
|
+
|
165
|
+
torque
|
166
|
+
5 Missing torque info file
|
167
|
+
6 Missing output directory
|
168
|
+
7 Missing token
|
169
|
+
8 Invalid token
|
170
|
+
9 Missing project
|
171
|
+
10 Invalid project
|
172
|
+
11 Misc. Pivotal Tracker API request error
|
173
|
+
12 Misc argument error
|
174
|
+
|
175
|
+
torque config
|
176
|
+
5 Pre-existing output directory
|
177
|
+
6 Pre-existing torque info file
|
178
|
+
7 Invalid output directory
|
179
|
+
|
180
|
+
torque email
|
181
|
+
5 Missing torque info file
|
182
|
+
|
183
|
+
torque format
|
184
|
+
5 Missing torque info file
|
185
|
+
|
186
|
+
torque project
|
187
|
+
5 Missing torque info file
|
188
|
+
6 Project not found
|
189
|
+
|
114
190
|
License
|
115
191
|
-------
|
116
192
|
|
data/VERSION
CHANGED
@@ -1,3 +1,3 @@
|
|
1
1
|
major:0
|
2
|
-
minor:
|
3
|
-
patch:
|
2
|
+
minor:4
|
3
|
+
patch:0
|
data/bin/config
CHANGED
@@ -11,6 +11,7 @@ require 'highline/import'
|
|
11
11
|
require 'net/http'
|
12
12
|
require 'optparse'
|
13
13
|
require 'pathname'
|
14
|
+
require "#{lib_dir}/torque/format_string"
|
14
15
|
require "#{lib_dir}/torque/pivotal"
|
15
16
|
require "#{lib_dir}/torque/torque_info_parser"
|
16
17
|
require "#{lib_dir}/torque/project/project"
|
@@ -62,7 +63,7 @@ begin
|
|
62
63
|
rescue OptionParser::InvalidOption, OptionParser::MissingArgument
|
63
64
|
puts $!.to_s
|
64
65
|
puts option_parser
|
65
|
-
exit
|
66
|
+
exit 3
|
66
67
|
end
|
67
68
|
|
68
69
|
# Handles special cases and exceptions
|
@@ -74,7 +75,7 @@ if ((ARGV.member? "help") || options[:help])
|
|
74
75
|
elsif !ARGV.empty?
|
75
76
|
puts "Unknown arguments: #{ARGV.join(", ")}"
|
76
77
|
puts option_parser.help
|
77
|
-
exit
|
78
|
+
exit 3
|
78
79
|
end
|
79
80
|
|
80
81
|
# Checks for a connection to Pivotal Tracker
|
@@ -82,7 +83,7 @@ end
|
|
82
83
|
if !Torque::Pivotal.connection?
|
83
84
|
puts "ABORTING"
|
84
85
|
puts "Cannot connect to www.pivotaltracker.com. A connection is required to configure Torque"
|
85
|
-
exit
|
86
|
+
exit 4
|
86
87
|
end
|
87
88
|
|
88
89
|
# Configures the directory
|
@@ -102,7 +103,7 @@ if !options[:token]
|
|
102
103
|
puts "The default output directory, #{default_output_dir}, already exists."
|
103
104
|
puts "(Use -o to manually choose an existing output directory or create a new one)"
|
104
105
|
puts "(Use -f to overwrite an existing directory)"
|
105
|
-
exit
|
106
|
+
exit 5
|
106
107
|
end
|
107
108
|
|
108
109
|
|
@@ -113,7 +114,7 @@ if !options[:token]
|
|
113
114
|
puts "A .torqueinfo.yaml file already exists in this directory."
|
114
115
|
puts "(Use -o to ignore this file and change only the output directory)"
|
115
116
|
puts "(Use -f to overwrite this file)"
|
116
|
-
exit
|
117
|
+
exit 6
|
117
118
|
end
|
118
119
|
|
119
120
|
|
@@ -132,7 +133,13 @@ if !options[:token]
|
|
132
133
|
puts "- Creating directory #{output_dir}"
|
133
134
|
end
|
134
135
|
|
135
|
-
|
136
|
+
begin
|
137
|
+
FileUtils.mkdir_p("#{output_dir}/previous")
|
138
|
+
rescue Errno::EACCES => e
|
139
|
+
puts "ABORTING"
|
140
|
+
puts "Cannot use output directory \"#{output_dir}\""
|
141
|
+
exit 7
|
142
|
+
end
|
136
143
|
|
137
144
|
if options[:force] && torque_info_path.exist?
|
138
145
|
puts "- Overwriting file .torqueinfo.yaml"
|
@@ -157,7 +164,7 @@ end
|
|
157
164
|
|
158
165
|
# Determines whether to set up a new API token and project ID
|
159
166
|
|
160
|
-
|
167
|
+
should_setup_torque_info = true
|
161
168
|
if retained_torque_info_file
|
162
169
|
valid = /^\s*(y|Y|n|N)\s*$/
|
163
170
|
setup_info_prompt = ask("Existing Torque info file found. Would you like to set up a new API token? [y/n]") {
|
@@ -165,11 +172,11 @@ if retained_torque_info_file
|
|
165
172
|
q.validate = valid
|
166
173
|
}
|
167
174
|
setup_info_prompt.strip!
|
168
|
-
|
175
|
+
should_setup_torque_info = (setup_info_prompt =~ /y|Y/)
|
169
176
|
end
|
170
177
|
|
171
178
|
|
172
|
-
if
|
179
|
+
if should_setup_torque_info
|
173
180
|
|
174
181
|
# Adds the API token to the torque info file
|
175
182
|
|
@@ -247,12 +254,16 @@ if should_setup_info
|
|
247
254
|
end
|
248
255
|
end
|
249
256
|
|
250
|
-
# Finishes
|
251
257
|
|
258
|
+
# Sets the default format string
|
259
|
+
|
260
|
+
Torque::TorqueInfoParser.new.set("format", Torque::FormatString.default)
|
261
|
+
|
262
|
+
# Finishes
|
252
263
|
|
253
264
|
puts
|
254
265
|
puts "Configuration complete!"
|
255
|
-
|
266
|
+
unless options[:token] || (options[:output_dir] && !should_setup_torque_info)
|
256
267
|
puts "WARNING: Do not check .torqueinfo.yaml into your version control system! (Contains sensitive information)"
|
257
|
-
|
258
|
-
|
268
|
+
puts
|
269
|
+
end
|
data/bin/email
CHANGED
@@ -10,8 +10,8 @@ working_dir = "."
|
|
10
10
|
require 'highline/import'
|
11
11
|
require 'mail'
|
12
12
|
require 'optparse'
|
13
|
-
require "#{lib_dir}/torque/torque_info_parser"
|
14
13
|
require "#{lib_dir}/torque/pivotal"
|
14
|
+
require "#{lib_dir}/torque/torque_info_parser"
|
15
15
|
|
16
16
|
# Parses the options
|
17
17
|
options = {}
|
@@ -60,7 +60,7 @@ begin
|
|
60
60
|
rescue OptionParser::InvalidOption, OptionParser::MissingArgument
|
61
61
|
puts $!.to_s
|
62
62
|
puts option_parser
|
63
|
-
exit
|
63
|
+
exit 3
|
64
64
|
end
|
65
65
|
|
66
66
|
# Handles special cases and exceptions
|
@@ -72,15 +72,7 @@ if ((ARGV.member? "help") || options[:help])
|
|
72
72
|
elsif !ARGV.empty?
|
73
73
|
puts "Unknown arguments: #{ARGV.join(", ")}"
|
74
74
|
puts option_parser.help
|
75
|
-
exit
|
76
|
-
end
|
77
|
-
|
78
|
-
# Checks for a connection to Pivotal Tracker
|
79
|
-
|
80
|
-
if !Torque::Pivotal.connection?
|
81
|
-
puts "ABORTING"
|
82
|
-
puts "Cannot connect to www.pivotaltracker.com. A connection is required to use Torque"
|
83
|
-
exit 1
|
75
|
+
exit 3
|
84
76
|
end
|
85
77
|
|
86
78
|
# Parses the torque info file
|
@@ -92,7 +84,7 @@ rescue Torque::MissingTorqueInfoFileError => e
|
|
92
84
|
puts "ABORTING"
|
93
85
|
puts e.message
|
94
86
|
puts "Run 'torque config' in this directory, or change your working directory"
|
95
|
-
exit
|
87
|
+
exit 5
|
96
88
|
end
|
97
89
|
|
98
90
|
# Util method to display the current email settings
|
@@ -137,12 +129,6 @@ if options[:setup]
|
|
137
129
|
|
138
130
|
end
|
139
131
|
|
140
|
-
# Validates all emails to be added
|
141
|
-
|
142
|
-
options[:add].each do |email|
|
143
|
-
|
144
|
-
end
|
145
|
-
|
146
132
|
# Adds and removes emails from the email list
|
147
133
|
|
148
134
|
unless (options[:add].empty? && options[:rm].empty?)
|
@@ -169,9 +155,13 @@ unless (options[:add].empty? && options[:rm].empty?)
|
|
169
155
|
|
170
156
|
end
|
171
157
|
|
172
|
-
#
|
158
|
+
# Displays the current email settings
|
159
|
+
|
160
|
+
options_empty = options.size == 2 && options[:add].empty? && options[:rm].empty?
|
173
161
|
|
174
162
|
torque_info.parse
|
163
|
+
puts "(When torque is run with the '--email' option, these addresses will receive a copy of the notes)" \
|
164
|
+
if options_empty
|
175
165
|
puts
|
176
166
|
disp_email(torque_info)
|
177
|
-
puts
|
167
|
+
puts
|
data/bin/format
ADDED
@@ -0,0 +1,170 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Controls the format of the release notes that Torque generates.
|
4
|
+
# Prompts for/sets the format string, and/or prints an example of the current format settings
|
5
|
+
|
6
|
+
lib_dir = File.expand_path("../lib", File.dirname(__FILE__))
|
7
|
+
template_dir = File.expand_path("../template", File.dirname(__FILE__))
|
8
|
+
working_dir = "."
|
9
|
+
|
10
|
+
require 'highline/import'
|
11
|
+
require 'optparse'
|
12
|
+
require "#{lib_dir}/torque/format_string"
|
13
|
+
require "#{lib_dir}/torque/story"
|
14
|
+
require "#{lib_dir}/torque/torque_info_parser"
|
15
|
+
require "#{lib_dir}/torque/error/missing_torque_info_file_error"
|
16
|
+
|
17
|
+
# Parses the options
|
18
|
+
options = {}
|
19
|
+
option_parser = OptionParser.new do |opts|
|
20
|
+
|
21
|
+
help_message = "Sets the format string that Torque uses to generate release notes, or prints the current format " \
|
22
|
+
"string settings if run with no arguments"
|
23
|
+
help_message += "\nThe format string consists of plain text as well as a series of parameters (eg. \"%a\") that " \
|
24
|
+
"act as placeholders for elements of a story"
|
25
|
+
help_message += "\n"
|
26
|
+
help_message += "\nA format string of \"default\" will return the format string to its default value " \
|
27
|
+
"(\"#{Torque::FormatString.default}\")"
|
28
|
+
help_message += "\n"
|
29
|
+
help_message += "\n"
|
30
|
+
help_message +=
|
31
|
+
<<-END_STR
|
32
|
+
Parameters:
|
33
|
+
%a => Date accepted (MM/DD)
|
34
|
+
%A => Date accepted (YYYY/MM/DD)
|
35
|
+
%d => Description
|
36
|
+
%D => Description (tabbed once on each newline)
|
37
|
+
%e => Estimate
|
38
|
+
%i => ID
|
39
|
+
%l => Labels (separated by ", ")
|
40
|
+
%n => Newline character
|
41
|
+
%N => Name
|
42
|
+
%o => Owner of the story
|
43
|
+
%p => ID of the story's project
|
44
|
+
%u => URL pointing to the story
|
45
|
+
%t => Tab character
|
46
|
+
%T => Type (feature, bug, etc)
|
47
|
+
END_STR
|
48
|
+
|
49
|
+
opts.banner = "\nUsage:"
|
50
|
+
opts.banner += "\n torque format [options]"
|
51
|
+
opts.banner += "\n"
|
52
|
+
opts.banner += "\n#{help_message}"
|
53
|
+
opts.banner += "\n"
|
54
|
+
|
55
|
+
opts.on("-e", "--example", "Optionally sets your format string after printing an example story") do
|
56
|
+
|arg|
|
57
|
+
options[:example] = arg
|
58
|
+
end
|
59
|
+
|
60
|
+
opts.on("-h", "--help", "Displays this help screen") do
|
61
|
+
|arg|
|
62
|
+
options[:help] = arg
|
63
|
+
end
|
64
|
+
|
65
|
+
opts.on("-s", "--set", "Sets your format string") do
|
66
|
+
|arg|
|
67
|
+
options[:set] = arg
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
# Parses options and handles exceptions
|
73
|
+
|
74
|
+
begin
|
75
|
+
option_parser.parse!
|
76
|
+
|
77
|
+
rescue OptionParser::InvalidOption, OptionParser::MissingArgument
|
78
|
+
puts $!.to_s
|
79
|
+
puts option_parser
|
80
|
+
exit 3
|
81
|
+
end
|
82
|
+
|
83
|
+
# Handles special cases and exceptions
|
84
|
+
|
85
|
+
if ((ARGV.member? "help") || options[:help])
|
86
|
+
puts "(Ran with 'help' option; other options ignored)"
|
87
|
+
puts option_parser
|
88
|
+
exit
|
89
|
+
elsif !ARGV.empty?
|
90
|
+
puts "Unknown arguments: #{ARGV.join(", ")}"
|
91
|
+
puts option_parser.help
|
92
|
+
exit 3
|
93
|
+
elsif (options.has_key? :example) && (options.has_key? :set)
|
94
|
+
puts "Conflicting options: -e/--example and -s/--set. Choose either 'example' or 'set'."
|
95
|
+
exit 3
|
96
|
+
end
|
97
|
+
|
98
|
+
# An example story for display purposes
|
99
|
+
|
100
|
+
sample_story = Torque::Story.new({})
|
101
|
+
|
102
|
+
sample_story.current_state = "accepted"
|
103
|
+
sample_story.date_accepted = Date.new(2012, 12, 21)
|
104
|
+
sample_story.description = "Short description of story goes here\n- This is a side note\n- This is another side note"
|
105
|
+
sample_story.estimate = 3
|
106
|
+
sample_story.id = 12345678
|
107
|
+
sample_story.labels = ["label-1", "label-2"]
|
108
|
+
sample_story.name = "Story Name"
|
109
|
+
sample_story.owner = "Owner Smith"
|
110
|
+
sample_story.project_id = 123456
|
111
|
+
sample_story.type = "feature"
|
112
|
+
|
113
|
+
# Instantiates a TorqueInfoParser
|
114
|
+
|
115
|
+
begin
|
116
|
+
torque_info = Torque::TorqueInfoParser.new.parse
|
117
|
+
rescue Torque::MissingTorqueInfoFileError => e
|
118
|
+
puts "ABORTING"
|
119
|
+
puts e.message
|
120
|
+
puts "Run 'torque config' in this directory, or change your working directory"
|
121
|
+
exit 5
|
122
|
+
end
|
123
|
+
|
124
|
+
# If run with -e/--example or -s/--setup: Takes in a string, optionally verifies format settings, sets format string
|
125
|
+
|
126
|
+
if options[:example] || options[:set]
|
127
|
+
|
128
|
+
default = false # True if the default format string should be used
|
129
|
+
should_set = true # True if the format string should be changed on file
|
130
|
+
|
131
|
+
format = (ask("Enter a format string below:") {|q| q.readline = true}).to_s
|
132
|
+
|
133
|
+
if format == 'default'
|
134
|
+
default = true
|
135
|
+
format = Torque::FormatString.default
|
136
|
+
end
|
137
|
+
|
138
|
+
# If -e/--example, prints and validates the new settings
|
139
|
+
|
140
|
+
if options[:example]
|
141
|
+
puts "---"
|
142
|
+
puts Torque::FormatString.new(format).apply(sample_story)
|
143
|
+
puts "---"
|
144
|
+
|
145
|
+
valid = /^\s*(y|Y|n|N)\s*$/
|
146
|
+
should_set_prompt = ask("Would you like to set this as your format? [y/n]") {
|
147
|
+
|q|
|
148
|
+
q.validate = valid
|
149
|
+
}
|
150
|
+
should_set_prompt.strip!
|
151
|
+
should_set = (should_set_prompt =~ /y|Y/)
|
152
|
+
end
|
153
|
+
|
154
|
+
if should_set
|
155
|
+
torque_info.set("format", format)
|
156
|
+
|
157
|
+
to_print = "Set format string to "
|
158
|
+
to_print += (default ? "default" : "\"#{format}\"")
|
159
|
+
puts to_print
|
160
|
+
end
|
161
|
+
|
162
|
+
# If run with no arguments, displays the current format settings
|
163
|
+
|
164
|
+
else
|
165
|
+
puts
|
166
|
+
puts "Current format string: \"#{torque_info.format}\""
|
167
|
+
puts "---"
|
168
|
+
puts Torque::FormatString.new(torque_info.format).apply(sample_story)
|
169
|
+
puts "---"
|
170
|
+
end
|