mongo-jira 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- checksums.yaml.gz.sig +4 -0
- data.tar.gz.sig +0 -0
- data/.gitignore +24 -0
- data/Gemfile +4 -0
- data/LICENSE +191 -0
- data/README.md +44 -0
- data/Rakefile +1 -0
- data/bin/jira +408 -0
- data/lib/mongo/jira.rb +53 -0
- data/lib/mongo/jira/config.rb +109 -0
- data/lib/mongo/jira/config_exception.rb +5 -0
- data/lib/mongo/jira/patch.rb +35 -0
- data/lib/mongo/jira/version.rb +5 -0
- data/mongo-jira.gemspec +29 -0
- data/test/test_jira_mongo.rb +9 -0
- metadata +129 -0
- metadata.gz.sig +0 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
ODRhOTNkZDY1NjBiNDUwMTg4MmZmN2U2YWNlYTUxNTNiN2EyYjg4Zg==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
YmQ3OGYyMWIxMzcwODFhZjkzNzIzNGQzMDZkMjU1NTljZWU4Yzg3Mg==
|
7
|
+
!binary "U0hBNTEy":
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
MDBiOTc1MmMxMGQ0N2VlMmQ4MDMzMDgzMzY3MWUzMWJjYzBiMDBhY2VlNzY0
|
10
|
+
ZTRhZWE2NjI2ODE4YzczZjZhMWZkNTZkMzM4ZTViMjVlMjg3MTllYzBjNzU2
|
11
|
+
ZTY4ZDY1ZTNhZjIwZmIzNmJhODRmZjI2NDVhMDQyNjJjZmZkMjc=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
YzFlZDA0YjhhMTkzZWM0NzU1ODBiYzQxNGFlZGRjYjE4ODFkOTAwOGYxYjM2
|
14
|
+
OTBlNGFjOWUwNDdiMWVhMGYwYTU2NzRhZTUxZjI5M2U2NmU2MjAwMjAwNjli
|
15
|
+
NGI5YmI3NjgyNGNmNzg5ZWZhMzQ4MDk2MWIzN2RkYjY0YzRiNTc=
|
checksums.yaml.gz.sig
ADDED
data.tar.gz.sig
ADDED
Binary file
|
data/.gitignore
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
Gemfile.lock
|
6
|
+
coverage
|
7
|
+
InstalledFiles
|
8
|
+
lib/bundler/man
|
9
|
+
pkg
|
10
|
+
rdoc
|
11
|
+
spec/reports
|
12
|
+
test/tmp
|
13
|
+
test/version_tmp
|
14
|
+
tmp
|
15
|
+
|
16
|
+
# YARD artifacts
|
17
|
+
.yardoc
|
18
|
+
_yardoc
|
19
|
+
doc/
|
20
|
+
|
21
|
+
.idea/*
|
22
|
+
*#
|
23
|
+
.#*
|
24
|
+
*~
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,191 @@
|
|
1
|
+
Apache License
|
2
|
+
Version 2.0, January 2004
|
3
|
+
http://www.apache.org/licenses/
|
4
|
+
|
5
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
6
|
+
|
7
|
+
1. Definitions.
|
8
|
+
|
9
|
+
"License" shall mean the terms and conditions for use, reproduction, and
|
10
|
+
distribution as defined by Sections 1 through 9 of this document.
|
11
|
+
|
12
|
+
"Licensor" shall mean the copyright owner or entity authorized by the copyright
|
13
|
+
owner that is granting the License.
|
14
|
+
|
15
|
+
"Legal Entity" shall mean the union of the acting entity and all other entities
|
16
|
+
that control, are controlled by, or are under common control with that entity.
|
17
|
+
For the purposes of this definition, "control" means (i) the power, direct or
|
18
|
+
indirect, to cause the direction or management of such entity, whether by
|
19
|
+
contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
20
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
21
|
+
|
22
|
+
"You" (or "Your") shall mean an individual or Legal Entity exercising
|
23
|
+
permissions granted by this License.
|
24
|
+
|
25
|
+
"Source" form shall mean the preferred form for making modifications, including
|
26
|
+
but not limited to software source code, documentation source, and configuration
|
27
|
+
files.
|
28
|
+
|
29
|
+
"Object" form shall mean any form resulting from mechanical transformation or
|
30
|
+
translation of a Source form, including but not limited to compiled object code,
|
31
|
+
generated documentation, and conversions to other media types.
|
32
|
+
|
33
|
+
"Work" shall mean the work of authorship, whether in Source or Object form, made
|
34
|
+
available under the License, as indicated by a copyright notice that is included
|
35
|
+
in or attached to the work (an example is provided in the Appendix below).
|
36
|
+
|
37
|
+
"Derivative Works" shall mean any work, whether in Source or Object form, that
|
38
|
+
is based on (or derived from) the Work and for which the editorial revisions,
|
39
|
+
annotations, elaborations, or other modifications represent, as a whole, an
|
40
|
+
original work of authorship. For the purposes of this License, Derivative Works
|
41
|
+
shall not include works that remain separable from, or merely link (or bind by
|
42
|
+
name) to the interfaces of, the Work and Derivative Works thereof.
|
43
|
+
|
44
|
+
"Contribution" shall mean any work of authorship, including the original version
|
45
|
+
of the Work and any modifications or additions to that Work or Derivative Works
|
46
|
+
thereof, that is intentionally submitted to Licensor for inclusion in the Work
|
47
|
+
by the copyright owner or by an individual or Legal Entity authorized to submit
|
48
|
+
on behalf of the copyright owner. For the purposes of this definition,
|
49
|
+
"submitted" means any form of electronic, verbal, or written communication sent
|
50
|
+
to the Licensor or its representatives, including but not limited to
|
51
|
+
communication on electronic mailing lists, source code control systems, and
|
52
|
+
issue tracking systems that are managed by, or on behalf of, the Licensor for
|
53
|
+
the purpose of discussing and improving the Work, but excluding communication
|
54
|
+
that is conspicuously marked or otherwise designated in writing by the copyright
|
55
|
+
owner as "Not a Contribution."
|
56
|
+
|
57
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
|
58
|
+
of whom a Contribution has been received by Licensor and subsequently
|
59
|
+
incorporated within the Work.
|
60
|
+
|
61
|
+
2. Grant of Copyright License.
|
62
|
+
|
63
|
+
Subject to the terms and conditions of this License, each Contributor hereby
|
64
|
+
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
|
65
|
+
irrevocable copyright license to reproduce, prepare Derivative Works of,
|
66
|
+
publicly display, publicly perform, sublicense, and distribute the Work and such
|
67
|
+
Derivative Works in Source or Object form.
|
68
|
+
|
69
|
+
3. Grant of Patent License.
|
70
|
+
|
71
|
+
Subject to the terms and conditions of this License, each Contributor hereby
|
72
|
+
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
|
73
|
+
irrevocable (except as stated in this section) patent license to make, have
|
74
|
+
made, use, offer to sell, sell, import, and otherwise transfer the Work, where
|
75
|
+
such license applies only to those patent claims licensable by such Contributor
|
76
|
+
that are necessarily infringed by their Contribution(s) alone or by combination
|
77
|
+
of their Contribution(s) with the Work to which such Contribution(s) was
|
78
|
+
submitted. If You institute patent litigation against any entity (including a
|
79
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work or a
|
80
|
+
Contribution incorporated within the Work constitutes direct or contributory
|
81
|
+
patent infringement, then any patent licenses granted to You under this License
|
82
|
+
for that Work shall terminate as of the date such litigation is filed.
|
83
|
+
|
84
|
+
4. Redistribution.
|
85
|
+
|
86
|
+
You may reproduce and distribute copies of the Work or Derivative Works thereof
|
87
|
+
in any medium, with or without modifications, and in Source or Object form,
|
88
|
+
provided that You meet the following conditions:
|
89
|
+
|
90
|
+
You must give any other recipients of the Work or Derivative Works a copy of
|
91
|
+
this License; and
|
92
|
+
You must cause any modified files to carry prominent notices stating that You
|
93
|
+
changed the files; and
|
94
|
+
You must retain, in the Source form of any Derivative Works that You distribute,
|
95
|
+
all copyright, patent, trademark, and attribution notices from the Source form
|
96
|
+
of the Work, excluding those notices that do not pertain to any part of the
|
97
|
+
Derivative Works; and
|
98
|
+
If the Work includes a "NOTICE" text file as part of its distribution, then any
|
99
|
+
Derivative Works that You distribute must include a readable copy of the
|
100
|
+
attribution notices contained within such NOTICE file, excluding those notices
|
101
|
+
that do not pertain to any part of the Derivative Works, in at least one of the
|
102
|
+
following places: within a NOTICE text file distributed as part of the
|
103
|
+
Derivative Works; within the Source form or documentation, if provided along
|
104
|
+
with the Derivative Works; or, within a display generated by the Derivative
|
105
|
+
Works, if and wherever such third-party notices normally appear. The contents of
|
106
|
+
the NOTICE file are for informational purposes only and do not modify the
|
107
|
+
License. You may add Your own attribution notices within Derivative Works that
|
108
|
+
You distribute, alongside or as an addendum to the NOTICE text from the Work,
|
109
|
+
provided that such additional attribution notices cannot be construed as
|
110
|
+
modifying the License.
|
111
|
+
You may add Your own copyright statement to Your modifications and may provide
|
112
|
+
additional or different license terms and conditions for use, reproduction, or
|
113
|
+
distribution of Your modifications, or for any such Derivative Works as a whole,
|
114
|
+
provided Your use, reproduction, and distribution of the Work otherwise complies
|
115
|
+
with the conditions stated in this License.
|
116
|
+
|
117
|
+
5. Submission of Contributions.
|
118
|
+
|
119
|
+
Unless You explicitly state otherwise, any Contribution intentionally submitted
|
120
|
+
for inclusion in the Work by You to the Licensor shall be under the terms and
|
121
|
+
conditions of this License, without any additional terms or conditions.
|
122
|
+
Notwithstanding the above, nothing herein shall supersede or modify the terms of
|
123
|
+
any separate license agreement you may have executed with Licensor regarding
|
124
|
+
such Contributions.
|
125
|
+
|
126
|
+
6. Trademarks.
|
127
|
+
|
128
|
+
This License does not grant permission to use the trade names, trademarks,
|
129
|
+
service marks, or product names of the Licensor, except as required for
|
130
|
+
reasonable and customary use in describing the origin of the Work and
|
131
|
+
reproducing the content of the NOTICE file.
|
132
|
+
|
133
|
+
7. Disclaimer of Warranty.
|
134
|
+
|
135
|
+
Unless required by applicable law or agreed to in writing, Licensor provides the
|
136
|
+
Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
|
137
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
|
138
|
+
including, without limitation, any warranties or conditions of TITLE,
|
139
|
+
NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
|
140
|
+
solely responsible for determining the appropriateness of using or
|
141
|
+
redistributing the Work and assume any risks associated with Your exercise of
|
142
|
+
permissions under this License.
|
143
|
+
|
144
|
+
8. Limitation of Liability.
|
145
|
+
|
146
|
+
In no event and under no legal theory, whether in tort (including negligence),
|
147
|
+
contract, or otherwise, unless required by applicable law (such as deliberate
|
148
|
+
and grossly negligent acts) or agreed to in writing, shall any Contributor be
|
149
|
+
liable to You for damages, including any direct, indirect, special, incidental,
|
150
|
+
or consequential damages of any character arising as a result of this License or
|
151
|
+
out of the use or inability to use the Work (including but not limited to
|
152
|
+
damages for loss of goodwill, work stoppage, computer failure or malfunction, or
|
153
|
+
any and all other commercial damages or losses), even if such Contributor has
|
154
|
+
been advised of the possibility of such damages.
|
155
|
+
|
156
|
+
9. Accepting Warranty or Additional Liability.
|
157
|
+
|
158
|
+
While redistributing the Work or Derivative Works thereof, You may choose to
|
159
|
+
offer, and charge a fee for, acceptance of support, warranty, indemnity, or
|
160
|
+
other liability obligations and/or rights consistent with this License. However,
|
161
|
+
in accepting such obligations, You may act only on Your own behalf and on Your
|
162
|
+
sole responsibility, not on behalf of any other Contributor, and only if You
|
163
|
+
agree to indemnify, defend, and hold each Contributor harmless for any liability
|
164
|
+
incurred by, or claims asserted against, such Contributor by reason of your
|
165
|
+
accepting any such warranty or additional liability.
|
166
|
+
|
167
|
+
END OF TERMS AND CONDITIONS
|
168
|
+
|
169
|
+
APPENDIX: How to apply the Apache License to your work
|
170
|
+
|
171
|
+
To apply the Apache License to your work, attach the following boilerplate
|
172
|
+
notice, with the fields enclosed by brackets "[]" replaced with your own
|
173
|
+
identifying information. (Don't include the brackets!) The text should be
|
174
|
+
enclosed in the appropriate comment syntax for the file format. We also
|
175
|
+
recommend that a file or class name and description of purpose be included on
|
176
|
+
the same "printed page" as the copyright notice for easier identification within
|
177
|
+
third-party archives.
|
178
|
+
|
179
|
+
Copyright [yyyy] [name of copyright owner]
|
180
|
+
|
181
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
182
|
+
you may not use this file except in compliance with the License.
|
183
|
+
You may obtain a copy of the License at
|
184
|
+
|
185
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
186
|
+
|
187
|
+
Unless required by applicable law or agreed to in writing, software
|
188
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
189
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
190
|
+
See the License for the specific language governing permissions and
|
191
|
+
limitations under the License.
|
data/README.md
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
mongo-jira
|
2
|
+
==========
|
3
|
+
|
4
|
+
Simple Jira command line tool
|
5
|
+
|
6
|
+
This is a stub for a set of very simple command lines tools to access Jira tickets through the
|
7
|
+
REST api
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
Install it yourself as:
|
12
|
+
|
13
|
+
$ gem install mongo-jira
|
14
|
+
|
15
|
+
## Usage
|
16
|
+
|
17
|
+
### Initial configuration
|
18
|
+
|
19
|
+
Create a file called **.mongo-jira.json** in your home dir (alternatively use the -c flag to set different location). Add the following :
|
20
|
+
|
21
|
+
{
|
22
|
+
"username": "jim.oleary@10gen.com",
|
23
|
+
"password": "Base64EncodedPassword==",
|
24
|
+
"site": "https://jira.mongodb.org",
|
25
|
+
"auth_type": "basic",
|
26
|
+
"context_path": ""
|
27
|
+
}
|
28
|
+
|
29
|
+
If you omit the password, then you will be asked for one.
|
30
|
+
|
31
|
+
Change **<your username>** and **<your password>** ;-)
|
32
|
+
|
33
|
+
Execute the following command, if your config is correct you should see all your Jira projects:
|
34
|
+
|
35
|
+
jira test
|
36
|
+
|
37
|
+
|
38
|
+
## Contributing
|
39
|
+
|
40
|
+
1. Fork it
|
41
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
42
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
43
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
44
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/bin/jira
ADDED
@@ -0,0 +1,408 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require "mongo/jira/version"
|
3
|
+
|
4
|
+
require 'commander/import'
|
5
|
+
require 'jira'
|
6
|
+
require 'mongo/jira'
|
7
|
+
require 'json'
|
8
|
+
require 'ruby-progressbar'
|
9
|
+
|
10
|
+
$config = "#{ENV['HOME']}/.mongo-jira.json"
|
11
|
+
$level = 0
|
12
|
+
tengen = HighLine::ColorScheme.new do |cs|
|
13
|
+
cs[:released] = [:bold, :green]
|
14
|
+
cs[:rc] = [:bold, :cyan]
|
15
|
+
cs[:error] = [:bold, :red]
|
16
|
+
cs[:password] = [:red]
|
17
|
+
cs[:dev_only] = [:bold, :reverse]
|
18
|
+
cs[:tengen] = [:bold, :green]
|
19
|
+
cs[:downloaded] = [:green]
|
20
|
+
cs[:p1] = [:bold, :red]
|
21
|
+
cs[:p2] = [:red]
|
22
|
+
cs[:p3] = [:cyan]
|
23
|
+
cs[:p4] = [:green]
|
24
|
+
cs[:p4] = [:green]
|
25
|
+
end
|
26
|
+
HighLine.color_scheme = tengen
|
27
|
+
|
28
|
+
program :version, '0.0.0'
|
29
|
+
program :description, 'Set of JIRA command line tools'
|
30
|
+
program(:help, 'Common Errors',<<END)
|
31
|
+
error: SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed.
|
32
|
+
Try :
|
33
|
+
|
34
|
+
rvm osx-ssl-certs update all
|
35
|
+
END
|
36
|
+
|
37
|
+
program(:help, 'Reporting Errors',<<END)
|
38
|
+
add --trace to the end of the command , re-run and email me the log.
|
39
|
+
|
40
|
+
END
|
41
|
+
|
42
|
+
program(:help, 'Supported Versions',<<END)
|
43
|
+
I've tested the gem with the following ruby versions:
|
44
|
+
|
45
|
+
ruby-1.9.2
|
46
|
+
ruby-1.9.3
|
47
|
+
ruby-2.0.0
|
48
|
+
|
49
|
+
It does not work on 1.8.7 :
|
50
|
+
|
51
|
+
activesupport requires Ruby version >= 1.9.3.
|
52
|
+
|
53
|
+
END
|
54
|
+
|
55
|
+
global_option('-c', '--creds FILE', 'Load config data for your commands to use') { |file| $config = file }
|
56
|
+
global_option('-V', 'increment verbosity level, i.e. -VV for higher debug level') { $level += 1}
|
57
|
+
|
58
|
+
default_command :projects
|
59
|
+
|
60
|
+
command :init do |c|
|
61
|
+
c.syntax = 'jira init [options]'
|
62
|
+
c.summary = 'Run this command to initialize jira mongo gem'
|
63
|
+
c.description = 'This command will walk you through the account details that are needed.'
|
64
|
+
c.example 'description', 'jira init'
|
65
|
+
c.action do
|
66
|
+
if Mongo::Jira::Config::check($config)
|
67
|
+
exit 1 unless agree("#{$config} exists, <%= color('Overwrite?', RED) %> ")
|
68
|
+
end
|
69
|
+
|
70
|
+
conf = {}
|
71
|
+
conf[:username] = prompt('username', 'jim.oleary@10gen.com')
|
72
|
+
conf[:password] = ask("password (<%= color('hit ENTER for none', :password) %>) ? ") { |q| q.echo = '*' }
|
73
|
+
conf[:site] = prompt('site', 'https://jira.mongodb.org')
|
74
|
+
conf[:auth_type] = prompt('auth_type', 'basic')
|
75
|
+
conf.delete(:password) if conf[:password].blank?
|
76
|
+
|
77
|
+
Mongo::Jira::Config::save(conf, $config)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
command :download do |c|
|
82
|
+
c.syntax = 'jira download <ticket>* [options]'
|
83
|
+
c.summary = 'download files attached to this ticket'
|
84
|
+
c.description=<<END
|
85
|
+
Download all the files attached attached to a ticket.
|
86
|
+
|
87
|
+
If no parameters are supplied then all new attachments will be downloaded. By default the file
|
88
|
+
structure is flattened and the files are downloaded to the 'attachment' directory.
|
89
|
+
|
90
|
+
If the '--force' flag is used then all or files matching a glob are downloaded (regardless of whether they
|
91
|
+
are currently downloaded). By default the force pattern is a glob and '*' are prepended and appended to the glob.
|
92
|
+
So the following 2 commands are equivalent :
|
93
|
+
|
94
|
+
$> jira download pr-1111
|
95
|
+
$> jira download pr-1111 pr-2222
|
96
|
+
$> jira download pr-1111 --force filename
|
97
|
+
$> jira download pr-1111 --force '*filename*'
|
98
|
+
$> jira download pr-1111 --force '*filename*' --to attachment
|
99
|
+
|
100
|
+
Multiple patterns can also be supplied:
|
101
|
+
|
102
|
+
$> jira download pr-1111 --force filename1,file2
|
103
|
+
END
|
104
|
+
c.example 'download all the new files from pr-1111', 'jira download pr-1111'
|
105
|
+
c.option '--dryrun', 'don\'t do the download just print what would happen '
|
106
|
+
c.option '-f','--[no-]flatten', 'flatten directory'
|
107
|
+
c.option '--silent', 'don\'t display progress'
|
108
|
+
c.option '--force [GLOBS]', String, 'force download of matching files'
|
109
|
+
c.option '--to LOCATION', String, 'download to LOCATION, defaults to ticket name'
|
110
|
+
c.action do |args,options|
|
111
|
+
options.default(:dryrun => false, :silent => false, :flatten=>true, :to=>nil)
|
112
|
+
if options.force.nil? || options.force.is_a?(TrueClass)
|
113
|
+
force = (options.force.nil? ? %w() : %w(*))
|
114
|
+
else
|
115
|
+
force = options.force.split(/[,\s]/).collect{|g| "*#{g.chomp}*"}
|
116
|
+
end
|
117
|
+
|
118
|
+
tids = args|| %w(.*)
|
119
|
+
tids.each do |tid|
|
120
|
+
ticket = client.find(tid)
|
121
|
+
|
122
|
+
unless ticket
|
123
|
+
puts "no ticket for #{tid}"
|
124
|
+
next
|
125
|
+
end
|
126
|
+
trace JSON.pretty_generate(ticket.attrs) if ticket
|
127
|
+
|
128
|
+
#noinspection RubyResolve
|
129
|
+
ticket.attachments.each do |attachment|
|
130
|
+
trace JSON.pretty_generate(attachment.attrs)
|
131
|
+
u = URI.parse(attachment.content)
|
132
|
+
parts = u.path.split('/')#[2..-1].join('/')
|
133
|
+
to = options.to.nil? ? tid : parts[2]
|
134
|
+
trace "to -> #{to}"
|
135
|
+
if options.flatten
|
136
|
+
target = [to, parts.last]
|
137
|
+
else
|
138
|
+
target = [to, parts[3..-1]]
|
139
|
+
end
|
140
|
+
target = File.join(target.flatten)
|
141
|
+
|
142
|
+
trace target
|
143
|
+
size = attachment.attrs['size']
|
144
|
+
debug "checking #{target} => #{File.exists?(target)}"
|
145
|
+
if !force.any?{|g|File.fnmatch(g, target)} && File.exists?(target) && File.size(target) == size
|
146
|
+
say("<%= color('skipping', :downloaded) %> already downloaded '#{target}'")
|
147
|
+
next
|
148
|
+
end
|
149
|
+
|
150
|
+
name = target.split(%r{/}).last
|
151
|
+
title = name[0..14].ljust(15)
|
152
|
+
format = '%T %a |%b>%i|'
|
153
|
+
length= 80
|
154
|
+
|
155
|
+
pb = ProgressBar.create(:format => format,
|
156
|
+
:title => title,
|
157
|
+
:total => size,
|
158
|
+
:throttle_rate => 0.1,
|
159
|
+
:length => length)
|
160
|
+
pb = DummyProgressBar.new(size) if options.silent
|
161
|
+
|
162
|
+
progress=0
|
163
|
+
if options.dryrun
|
164
|
+
pb.format('%T |%b>%i|')
|
165
|
+
pb.title = name[0..29].ljust(30)
|
166
|
+
pb.progress=size
|
167
|
+
else
|
168
|
+
client.get(u.path) do |response|
|
169
|
+
FileUtils.mkdir_p(File::dirname(target))
|
170
|
+
debug u, ' => ', target
|
171
|
+
open target, 'w' do |io|
|
172
|
+
response.read_body do |chunk|
|
173
|
+
progress+=chunk.length
|
174
|
+
if progress == size
|
175
|
+
pb.format('%T |%b>%i|')
|
176
|
+
pb.title = name[0..29].ljust(30)
|
177
|
+
end
|
178
|
+
pb.progress=progress
|
179
|
+
io.write chunk
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
command :projects do |c|
|
191
|
+
c.syntax = 'jira projects <glob> [options]'
|
192
|
+
c.summary = 'list all the projects'
|
193
|
+
c.description = ''
|
194
|
+
c.example 'description', 'command example'
|
195
|
+
c.action do |args|
|
196
|
+
glob = args.first || '.*'
|
197
|
+
client.projects.each do |project|
|
198
|
+
say "#{project.key} - #{project.name}" if project.key =~ %r{#{glob}}
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
alias_command :test, :projects
|
204
|
+
|
205
|
+
command :show do |c|
|
206
|
+
c.syntax = 'jira ticket <id>* [options]'
|
207
|
+
c.summary = 'view a ticket or list of tickets'
|
208
|
+
c.description= <<END
|
209
|
+
|
210
|
+
$> jira show pr-1111
|
211
|
+
$> jira ticket pr-1111
|
212
|
+
$> jira show pr-1111 pr-2222
|
213
|
+
$> jira show pr-1111 --reverse | less -R
|
214
|
+
END
|
215
|
+
c.option '--reverse', 'print the comments in reverse order'
|
216
|
+
c.action do |args, options|
|
217
|
+
(args || %w(.*)).each do |tid|
|
218
|
+
ticket = client.find(tid)
|
219
|
+
next unless ticket
|
220
|
+
trace JSON.pretty_generate(ticket.attrs)
|
221
|
+
desc = Proc.new do
|
222
|
+
say <<END
|
223
|
+
#{header(ticket).join(' - ')}
|
224
|
+
|
225
|
+
#{('-' * 40)}
|
226
|
+
|
227
|
+
#{ticket.description}
|
228
|
+
END
|
229
|
+
end
|
230
|
+
|
231
|
+
desc.call() unless options.reverse
|
232
|
+
|
233
|
+
comments = ticket.comment['comments']
|
234
|
+
comments.reverse! if options.reverse
|
235
|
+
comments.each do |cmnt|
|
236
|
+
say <<END
|
237
|
+
|
238
|
+
#{'=' * 40}
|
239
|
+
|
240
|
+
#{comment(cmnt).join(' - ')}
|
241
|
+
|
242
|
+
#{cmnt['body']}
|
243
|
+
END
|
244
|
+
end
|
245
|
+
desc.call() if options.reverse
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end
|
249
|
+
alias_command :ticket, :show
|
250
|
+
|
251
|
+
command :open do |c|
|
252
|
+
c.syntax = 'jira open <ids>* [options]'
|
253
|
+
c.summary = 'open a ticket'
|
254
|
+
c.description = 'open a ticket in the browser'
|
255
|
+
c.example 'description', 'jira open pr-1111'
|
256
|
+
c.option '--some-switch', 'Some switch that does something'
|
257
|
+
c.action do |args|
|
258
|
+
(args || %w(.*)).each do |tid|
|
259
|
+
ticket = client.find(tid)
|
260
|
+
if ticket
|
261
|
+
trace JSON.pretty_generate(ticket.attrs)
|
262
|
+
%x{open 'https://jira.mongodb.org/browse/#{tid}'}
|
263
|
+
end
|
264
|
+
end
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
command :query do |c|
|
269
|
+
c.syntax = 'jira query <jql> [options]'
|
270
|
+
c.summary = 'run a jql query '
|
271
|
+
c.description =<<END
|
272
|
+
Use JQL syntax to find tickets.
|
273
|
+
|
274
|
+
Sample queries :
|
275
|
+
$> jira query 'project = CS AND labels = fs AND (Assignee is NULL) AND status = Open ORDER BY priority DESC' -> commercial support, no owner
|
276
|
+
$> jira query 'project = CS AND (Assignee is NULL) AND status = Open ORDER BY priority DESC' -> commercial support, no owner
|
277
|
+
$> jira query 'project in (CS, MMSSUPPORT) AND (Assignee is NULL) AND status = Open ORDER BY priority DESC' -> commercial support, no owner
|
278
|
+
$> jira query 'label = "fs"' -> find issues resolved by ME
|
279
|
+
$> jira query 'status WAS "Resolved" BY currentUser()' -> find issues resolved by ME
|
280
|
+
$> jira query 'assignee = currentUser() OR owner = currentUser() ' -> find issues resolved by ME
|
281
|
+
$> jira query 'owner = currentUser() AND status in (open , "waiting for customer") '
|
282
|
+
$> jira query 'assignee is EMPTY AND status in ("waiting for customer") ORDER BY updated DESC '
|
283
|
+
END
|
284
|
+
c.example 'description', 'command example'
|
285
|
+
c.action do |args|
|
286
|
+
q = args.join(' ')
|
287
|
+
debug ":find '#{q}'"
|
288
|
+
client.jql(q).each do |ticket|
|
289
|
+
trace JSON.pretty_generate(ticket.attrs)
|
290
|
+
say header(ticket).join(' - ')
|
291
|
+
end
|
292
|
+
end
|
293
|
+
end
|
294
|
+
|
295
|
+
command :find do |c|
|
296
|
+
c.syntax = 'jira find <key words>'
|
297
|
+
c.summary = 'find ticket with keywords matching the following fields "summary description comment"'
|
298
|
+
c.description =<<END
|
299
|
+
Find tickets by keywords
|
300
|
+
|
301
|
+
Sample find:
|
302
|
+
$> jira find Test aggregation framework # match any of the words
|
303
|
+
$> jira find 'Test aggregation framework' # match any of the words
|
304
|
+
$> jira find '"Test aggregation framework"' # match exact phrase
|
305
|
+
END
|
306
|
+
c.action do |args|
|
307
|
+
pattern = args.join(' ')
|
308
|
+
q = %w{ summary description comment}.collect { |field| "#{field} ~ '#{pattern}'" }.join(' OR ')
|
309
|
+
debug ":find '#{q}'"
|
310
|
+
client.jql(q).each do |ticket|
|
311
|
+
trace JSON.pretty_generate(ticket.attrs)
|
312
|
+
say header(ticket).join(' - ')
|
313
|
+
end
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
def debug(*args)
|
318
|
+
puts args.join if $level > 0
|
319
|
+
end
|
320
|
+
|
321
|
+
def trace(*args)
|
322
|
+
puts args.join if $level > 1
|
323
|
+
end
|
324
|
+
|
325
|
+
def client(config=$config)
|
326
|
+
$jira ||= begin
|
327
|
+
jira = Mongo::Jira::Main.new(config)
|
328
|
+
jira.password = ask('Password: ') { |q| q.echo = '*' } unless jira.password?
|
329
|
+
jira
|
330
|
+
rescue Mongo::Jira::ConfigException
|
331
|
+
say("\n <%= color('UNEXPECTED ERROR', :error) %>\n\n conf file not found :: <%= color(\"#{config}\", RED) %>\n")
|
332
|
+
command(:help).run('init')
|
333
|
+
abort ''
|
334
|
+
end
|
335
|
+
end
|
336
|
+
|
337
|
+
# @param [Object] default
|
338
|
+
def prompt(name, default=nil)
|
339
|
+
ask("#{name} (<%= color(\"#{default}\", RED) %>) ? ", lambda { |v| v.blank? ? default : v })
|
340
|
+
end
|
341
|
+
|
342
|
+
def header(ticket)
|
343
|
+
[ticket.key.ljust(15) ,ticket.summary , fix_versions(ticket), priority(ticket)].compact
|
344
|
+
end
|
345
|
+
|
346
|
+
def comment(comment)
|
347
|
+
hdr = "#{comment['author']['displayName']} (#{comment['author']['name']})"
|
348
|
+
hdr = "<%= color(\"#{hdr}\", :tengen) %>" if comment['author']['emailAddress'] =~ /@10gen.com$/
|
349
|
+
|
350
|
+
trace JSON.pretty_generate(comment)
|
351
|
+
dev_only = case (comment['visibility']||{})['value']
|
352
|
+
when /developer/i
|
353
|
+
"<%= color('Dev Only', :dev_only) %>"
|
354
|
+
when /customer/i
|
355
|
+
"<%= color('Customer Only', :dev_only) %>"
|
356
|
+
else
|
357
|
+
nil
|
358
|
+
end
|
359
|
+
|
360
|
+
[hdr , DateTime.parse(comment['updated']).strftime('%D %T'), dev_only].compact
|
361
|
+
end
|
362
|
+
|
363
|
+
def fix_versions(ticket)
|
364
|
+
if ticket.try(:fixVersions)
|
365
|
+
trace "fixVersions #{JSON.pretty_generate(ticket.fixVersions)}"
|
366
|
+
unless ticket.fixVersions.compact.empty?
|
367
|
+
labels = ticket.fixVersions.collect do |v|
|
368
|
+
c = case v['name']
|
369
|
+
when /^\d+\.(0|2|4|6|8)/
|
370
|
+
':released'
|
371
|
+
when /^\d+\.(1|3|5|7|9)/
|
372
|
+
':rc'
|
373
|
+
else
|
374
|
+
':error'
|
375
|
+
end
|
376
|
+
"<%= color(\"#{v['name']}\", #{c}) %>"
|
377
|
+
end
|
378
|
+
labels.join(',')
|
379
|
+
end
|
380
|
+
else
|
381
|
+
nil
|
382
|
+
end
|
383
|
+
end
|
384
|
+
|
385
|
+
def priority(ticket)
|
386
|
+
if ticket.respond_to?(:priority)
|
387
|
+
trace "priority #{JSON.pretty_generate(ticket.priority.attrs)}"
|
388
|
+
c = case ticket.priority.attrs['name']
|
389
|
+
when /p1$/i ; ':p1'
|
390
|
+
when /p2$/i ; ':p2'
|
391
|
+
when /p3$/i ; ':p3'
|
392
|
+
when /p4$/i ; ':p4'
|
393
|
+
when /p5$/i ; ':p5'
|
394
|
+
else
|
395
|
+
':error'
|
396
|
+
end
|
397
|
+
"<%= color(\"#{ticket.priority.attrs['name']}\", #{c}) %>"
|
398
|
+
end
|
399
|
+
end
|
400
|
+
|
401
|
+
class DummyProgressBar
|
402
|
+
def initialize(s)
|
403
|
+
@size = s
|
404
|
+
end
|
405
|
+
def method_missing(meth, *args)
|
406
|
+
print '.' if meth.to_s == 'progress=' && args[0] == @size
|
407
|
+
end
|
408
|
+
end
|
data/lib/mongo/jira.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
require "mongo/jira/version"
|
2
|
+
|
3
|
+
require 'mongo/jira/config'
|
4
|
+
require 'mongo/jira/patch'
|
5
|
+
module Mongo
|
6
|
+
|
7
|
+
#noinspection ALL
|
8
|
+
module Jira
|
9
|
+
class Main
|
10
|
+
|
11
|
+
attr_accessor :filename, :jira, :config
|
12
|
+
|
13
|
+
def initialize(file)
|
14
|
+
@filename= file
|
15
|
+
end
|
16
|
+
|
17
|
+
def find(tid)
|
18
|
+
jira.Issue.find(tid)
|
19
|
+
rescue JIRA::HTTPError => e
|
20
|
+
raise e if e.code == '401' || e.code == '403'
|
21
|
+
nil
|
22
|
+
end
|
23
|
+
|
24
|
+
def jql(qry)
|
25
|
+
JIRA::Resource::Issue.jql(jira,qry)
|
26
|
+
end
|
27
|
+
|
28
|
+
def projects
|
29
|
+
jira.Project.all
|
30
|
+
end
|
31
|
+
|
32
|
+
def jira
|
33
|
+
@jira ||= JIRA::Client.new(config.config)
|
34
|
+
end
|
35
|
+
|
36
|
+
def password?
|
37
|
+
config.password?
|
38
|
+
end
|
39
|
+
def password=(pw)
|
40
|
+
config.password=pw
|
41
|
+
end
|
42
|
+
|
43
|
+
def config
|
44
|
+
@config ||= Mongo::Jira::Config.new(filename)
|
45
|
+
end
|
46
|
+
|
47
|
+
def method_missing(m, *args, &block)
|
48
|
+
jira.send(m, *args, &block)
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'openssl'
|
2
|
+
begin
|
3
|
+
require 'Base64s'
|
4
|
+
rescue LoadError
|
5
|
+
module Base64
|
6
|
+
def decode64(str)
|
7
|
+
str.unpack('m0').first
|
8
|
+
end
|
9
|
+
def encode64(bin)
|
10
|
+
[bin].pack('m0')
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
require 'digest'
|
15
|
+
require 'mongo/jira/config_exception'
|
16
|
+
|
17
|
+
module Mongo
|
18
|
+
module Jira
|
19
|
+
class Config
|
20
|
+
|
21
|
+
CFG_FILE="#{ENV['HOME']}/.mongo_jira.json"
|
22
|
+
|
23
|
+
# check the config file
|
24
|
+
#
|
25
|
+
# @example Save to default location and specific location.
|
26
|
+
# Mongo::Jira::Config::check()
|
27
|
+
# Mongo::Jira::Config::check("/tmp/.jira.json")
|
28
|
+
#
|
29
|
+
# @param [ String ] filename The config file path. It defaults to "#{ENV['HOME']}/.mongo_jira.json"
|
30
|
+
#
|
31
|
+
# @return [ true, false ] If the config is ok.
|
32
|
+
#
|
33
|
+
# @since 0.0.1
|
34
|
+
def self.check(filename=CFG_FILE)
|
35
|
+
File::exists?(filename)
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.save(config, filename)
|
39
|
+
cpy = config.clone
|
40
|
+
if config[:password]
|
41
|
+
cpy[:password] = Mongo::Jira::Config::encrypt('password',cpy[:password])
|
42
|
+
else
|
43
|
+
cpy.delete(:password)
|
44
|
+
end
|
45
|
+
cpy[:context_path] ||= ''
|
46
|
+
|
47
|
+
File.open(filename , 'w') {|f| f.write(JSON.pretty_generate(cpy)) }
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.load(filename=CFG_FILE)
|
51
|
+
Config.new(filename)
|
52
|
+
end
|
53
|
+
|
54
|
+
attr_accessor :filename , :config
|
55
|
+
def initialize(file)
|
56
|
+
raise ConfigException , "file not found #{file}" unless File::exists?(file)
|
57
|
+
@filename=file
|
58
|
+
@config = JSON.parse( IO.read(filename) )
|
59
|
+
config.symbolize_keys!()
|
60
|
+
config[:auth_type] = (config[:auth_type] || :basic).to_sym
|
61
|
+
config[:context_path] = ''
|
62
|
+
config[:password] = Mongo::Jira::Config::decrypt("password", config[:password]) if config[:password]
|
63
|
+
end
|
64
|
+
|
65
|
+
# save the config file
|
66
|
+
#
|
67
|
+
# @example write the config file
|
68
|
+
# Mongo::Jira::Config::check()
|
69
|
+
# Mongo::Jira::Config::check("/tmp/.jira.json")
|
70
|
+
#
|
71
|
+
# @param [ String ] filename The config file path. It defaults to "#{ENV['HOME']}/.mongo_jira.json"
|
72
|
+
#
|
73
|
+
# @return [ true, false ] If the config is ok.
|
74
|
+
#
|
75
|
+
# @since 0.0.1
|
76
|
+
def save
|
77
|
+
Mongo::Jira::Config::save(config,filename)
|
78
|
+
end
|
79
|
+
|
80
|
+
def password?
|
81
|
+
config[:password]
|
82
|
+
end
|
83
|
+
|
84
|
+
def password=(pw)
|
85
|
+
config[:password]=pw
|
86
|
+
end
|
87
|
+
|
88
|
+
def self.encrypt(key, value)
|
89
|
+
cipher = OpenSSL::Cipher::Cipher.new("des3")
|
90
|
+
cipher.encrypt # Call this before setting key or iv
|
91
|
+
cipher.key = key * 10
|
92
|
+
cipher.iv = '12345678'
|
93
|
+
text = cipher.update(value)
|
94
|
+
text << cipher.final
|
95
|
+
Base64.encode64(text).chomp
|
96
|
+
end
|
97
|
+
|
98
|
+
def self.decrypt(key, data)
|
99
|
+
cipher = OpenSSL::Cipher::Cipher.new("des3")
|
100
|
+
cipher.decrypt
|
101
|
+
cipher.key = key * 10
|
102
|
+
cipher.iv = '12345678'
|
103
|
+
plaintext = cipher.update(Base64.decode64(data))
|
104
|
+
plaintext << cipher.final
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'jira'
|
2
|
+
## monkey patch for progress bar
|
3
|
+
module JIRA
|
4
|
+
class RequestClient
|
5
|
+
|
6
|
+
# Returns the response if the request was successful (HTTP::2xx) and
|
7
|
+
# raises a JIRA::HTTPError if it was not successful, with the response
|
8
|
+
# attached.
|
9
|
+
|
10
|
+
def request(*args,&block)
|
11
|
+
response = make_request(*args,&block)
|
12
|
+
raise HTTPError.new(response) unless response.kind_of?(Net::HTTPSuccess)
|
13
|
+
response
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class HttpClient < RequestClient
|
18
|
+
|
19
|
+
def make_request(http_method, path, body='', headers={}, &block)
|
20
|
+
request = Net::HTTP.const_get(http_method.to_s.capitalize).new(path, headers)
|
21
|
+
request.body = body unless body.nil?
|
22
|
+
request.basic_auth(@options[:username], @options[:password])
|
23
|
+
basic_auth_http_conn.request(request, &block)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class Client
|
28
|
+
def get(path, headers = {}, &block)
|
29
|
+
request(:get, path, nil, merge_default_headers(headers), &block)
|
30
|
+
end
|
31
|
+
def request(http_method, path, body = '', headers={}, &block)
|
32
|
+
@request_client.request(http_method, path, body, headers, &block)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/mongo-jira.gemspec
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'mongo/jira/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = 'mongo-jira'
|
8
|
+
s.version = Mongo::Jira::VERSION #'0.0.0'
|
9
|
+
s.platform = Gem::Platform::RUBY
|
10
|
+
s.authors = ['Jim O\'Leary']
|
11
|
+
s.email = %q{jim.oleary@gmail.com}
|
12
|
+
s.homepage = %q{http://rubygems.org/gems/mongo_jira}
|
13
|
+
s.summary = %q{Simple Mongo Jira command line tools}
|
14
|
+
s.description = %q{Easy/Simple Jira command line tool}
|
15
|
+
s.rubyforge_project = 'mongo_jira'
|
16
|
+
s.signing_key = "#{ENV['HOME']}/.ssh/gem-private_key.pem"
|
17
|
+
s.cert_chain = ["#{ENV['HOME']}/.ssh/gem-public_cert.pem"]
|
18
|
+
|
19
|
+
|
20
|
+
s.files = `git ls-files`.split("\n")
|
21
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
22
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
23
|
+
s.require_paths = ["lib"]
|
24
|
+
|
25
|
+
|
26
|
+
s.add_dependency 'jira-ruby'#, ['>= 0.1.2']
|
27
|
+
s.add_dependency 'commander'#, ['>= 4.1.5']
|
28
|
+
s.add_dependency 'ruby-progressbar'#, ['>= 1.2.0']
|
29
|
+
end
|
metadata
ADDED
@@ -0,0 +1,129 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mongo-jira
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jim O'Leary
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain:
|
11
|
+
- !binary |-
|
12
|
+
LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURlRENDQW1DZ0F3SUJB
|
13
|
+
Z0lCQVRBTkJna3Foa2lHOXcwQkFRVUZBREJCTVJNd0VRWURWUVFEREFwcWFX
|
14
|
+
MHUKYjJ4bFlYSjVNUlV3RXdZS0NaSW1pWlB5TEdRQkdSWUZaMjFoYVd3eEV6
|
15
|
+
QVJCZ29Ka2lhSmsvSXNaQUVaRmdOagpiMjB3SGhjTk1UTXdPREl3TVRJMU5U
|
16
|
+
VXpXaGNOTVRRd09ESXdNVEkxTlRVeldqQkJNUk13RVFZRFZRUUREQXBxCmFX
|
17
|
+
MHViMnhsWVhKNU1SVXdFd1lLQ1pJbWlaUHlMR1FCR1JZRloyMWhhV3d4RXpB
|
18
|
+
UkJnb0praWFKay9Jc1pBRVoKRmdOamIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFF
|
19
|
+
QkFRVUFBNElCRHdBd2dnRUtBb0lCQVFDMHpZczdrOFcyQmx3bQo0aHVLeWJh
|
20
|
+
dk9qTzl0NVdDaDZEbkJ0WWh6OTJ4NUhSS1lGWXJTSlNzOFJiWjYvVFQ3SEUx
|
21
|
+
bm1pRmNwV3hUNEpCCnVneVMrMnplWVBJeVNMck1qT25XNFZEaXp2Z0tFM2li
|
22
|
+
V3UvZC9pa1NZRXZldTl4Zkx1RjlzekVrODl1RTdwYy8Kc0JxdXc5dXAwZ3Zw
|
23
|
+
aU9wZ0E3Q01VU3hmajRLU2ZQNmtoR1k4eUtHUUtoalYvNDBSdkxFKzB5Q1gx
|
24
|
+
REZRam8xNQpBQ1BqUVBCWjFoWHVZd0M4TkpKSzlKY0h0ZitpT0JWZng5Q1NP
|
25
|
+
S2ZpbGdsMzZiZWgwZ0hibFJmOWFFVWExR0ZTCm5YN0pWcDI1SUs1K3VxQll6
|
26
|
+
UFJtVWprNDBwZUFQWnNyWmVyd1B1NzZzUzR0N1d3N3FzVGlnbHdQeFZPS2Zw
|
27
|
+
TnQKS3JFck1hYWZBZ01CQUFHamV6QjVNQWtHQTFVZEV3UUNNQUF3Q3dZRFZS
|
28
|
+
MFBCQVFEQWdTd01CMEdBMVVkRGdRVwpCQlRnbUM0dFpEeGZOQzRldGhJMDkw
|
29
|
+
WGFUSmdoSkRBZkJnTlZIUkVFR0RBV2dSUnFhVzB1YjJ4bFlYSjVRR2R0CllX
|
30
|
+
bHNMbU52YlRBZkJnTlZIUklFR0RBV2dSUnFhVzB1YjJ4bFlYSjVRR2R0WVds
|
31
|
+
c0xtTnZiVEFOQmdrcWhraUcKOXcwQkFRVUZBQU9DQVFFQUVRdlJJRVVqOU5r
|
32
|
+
RUJtV09mdWYyMHhraHVLSkhIbCt2b3F3SXNtMEFITWpiMWIzSgpRYUhoOVdC
|
33
|
+
QTBJSzgySTk2dmlIOVBTZUlLOE5oM1hKOUxWQk80OXFtemovL3FkN0lTNVpk
|
34
|
+
TW1vcHZMWFIrVU93CnFtZi9yRlYwOWZaWnFHMmdUS3VhMDdMOC9LYXlpNHJZ
|
35
|
+
ZXZKUytJcGlJemZ0Si9mOEhSbHJGQ1NGaDdSK1gzZFMKc3drR05ORi9ZZGJl
|
36
|
+
MXdicFBBMWc2cS9OeVZVWlpYbzBjek5KR1hUZFZtWGJPY3pQY1dOTTV2S3Bq
|
37
|
+
bjhKN2pXbApUTHdTWGw3OHNxTjZPRktESjk2R1N4TXJuWTl0MGZRTzJrTXd5
|
38
|
+
QkRtZ0g0My9vVWFuSjhoMDZ6djFlckdwY3VjClJTR2VCbW9ycjBaWnBmQ1Bv
|
39
|
+
S0FMU3VXc2xBa1pXTy9XUnZQZENRPT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUt
|
40
|
+
LS0tLQo=
|
41
|
+
date: 2013-08-20 00:00:00.000000000 Z
|
42
|
+
dependencies:
|
43
|
+
- !ruby/object:Gem::Dependency
|
44
|
+
name: jira-ruby
|
45
|
+
requirement: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - ! '>='
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '0'
|
50
|
+
type: :runtime
|
51
|
+
prerelease: false
|
52
|
+
version_requirements: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - ! '>='
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: '0'
|
57
|
+
- !ruby/object:Gem::Dependency
|
58
|
+
name: commander
|
59
|
+
requirement: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ! '>='
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: '0'
|
64
|
+
type: :runtime
|
65
|
+
prerelease: false
|
66
|
+
version_requirements: !ruby/object:Gem::Requirement
|
67
|
+
requirements:
|
68
|
+
- - ! '>='
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: '0'
|
71
|
+
- !ruby/object:Gem::Dependency
|
72
|
+
name: ruby-progressbar
|
73
|
+
requirement: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
type: :runtime
|
79
|
+
prerelease: false
|
80
|
+
version_requirements: !ruby/object:Gem::Requirement
|
81
|
+
requirements:
|
82
|
+
- - ! '>='
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: '0'
|
85
|
+
description: Easy/Simple Jira command line tool
|
86
|
+
email: jim.oleary@gmail.com
|
87
|
+
executables:
|
88
|
+
- jira
|
89
|
+
extensions: []
|
90
|
+
extra_rdoc_files: []
|
91
|
+
files:
|
92
|
+
- .gitignore
|
93
|
+
- Gemfile
|
94
|
+
- LICENSE
|
95
|
+
- README.md
|
96
|
+
- Rakefile
|
97
|
+
- bin/jira
|
98
|
+
- lib/mongo/jira.rb
|
99
|
+
- lib/mongo/jira/config.rb
|
100
|
+
- lib/mongo/jira/config_exception.rb
|
101
|
+
- lib/mongo/jira/patch.rb
|
102
|
+
- lib/mongo/jira/version.rb
|
103
|
+
- mongo-jira.gemspec
|
104
|
+
- test/test_jira_mongo.rb
|
105
|
+
homepage: http://rubygems.org/gems/mongo_jira
|
106
|
+
licenses: []
|
107
|
+
metadata: {}
|
108
|
+
post_install_message:
|
109
|
+
rdoc_options: []
|
110
|
+
require_paths:
|
111
|
+
- lib
|
112
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
113
|
+
requirements:
|
114
|
+
- - ! '>='
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: '0'
|
117
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
118
|
+
requirements:
|
119
|
+
- - ! '>='
|
120
|
+
- !ruby/object:Gem::Version
|
121
|
+
version: '0'
|
122
|
+
requirements: []
|
123
|
+
rubyforge_project: mongo_jira
|
124
|
+
rubygems_version: 2.0.3
|
125
|
+
signing_key:
|
126
|
+
specification_version: 4
|
127
|
+
summary: Simple Mongo Jira command line tools
|
128
|
+
test_files:
|
129
|
+
- test/test_jira_mongo.rb
|
metadata.gz.sig
ADDED
Binary file
|