watson-ruby 1.0.3 → 1.0.4
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/.travis.yml +5 -0
- data/Gemfile.lock +1 -1
- data/README.md +9 -8
- data/Rakefile +2 -2
- data/lib/watson.rb +49 -49
- data/lib/watson/bitbucket.rb +370 -371
- data/lib/watson/command.rb +468 -468
- data/lib/watson/config.rb +490 -490
- data/lib/watson/fs.rb +59 -59
- data/lib/watson/github.rb +367 -367
- data/lib/watson/parser.rb +417 -418
- data/lib/watson/printer.rb +291 -291
- data/lib/watson/remote.rb +104 -104
- data/lib/watson/version.rb +1 -1
- data/spec/config_spec.rb +111 -111
- data/spec/fs_spec.rb +47 -47
- data/spec/parser_spec.rb +124 -124
- data/watson.gemspec +21 -21
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1e7a5e5e589587a830676cfecdbc585e2c3a3de3
|
4
|
+
data.tar.gz: 7fff249d9ac21e308bd4a512840fe9fdfffdec38
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d9dc3bc1f36631e44e52ac94c2901ff496eb78344a99e349bc6ba17dd379afb19e1f25c0f0eb684a0bab7666d45159eb9443ebd5647ba55661c7d9b1521d252d
|
7
|
+
data.tar.gz: 0f192b53b5b45421850a1601dd822f6a5e8c0d143869cbeb1c9e3b579df5b0122fe25545067c903778aa2e7f5a5119448c50a8d5022ee8d85ca3547296cbd7d5
|
data/.travis.yml
ADDED
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -19,9 +19,10 @@ gem install watson-ruby
|
|
19
19
|
|
20
20
|
Or you can clone this repo and install with Rake
|
21
21
|
```
|
22
|
-
clone https://github.com/nhmood/watson-ruby.git .
|
22
|
+
git clone https://github.com/nhmood/watson-ruby.git .
|
23
23
|
cd watson-ruby
|
24
|
-
|
24
|
+
bundle install
|
25
|
+
bundle exec rake
|
25
26
|
```
|
26
27
|
|
27
28
|
## Usage
|
@@ -34,7 +35,7 @@ Usage: watson [OPTION]...
|
|
34
35
|
Running watson with no arguments will parse with settings in RC file
|
35
36
|
If no RC file exists, default RC file will be created
|
36
37
|
|
37
|
-
-c, --context-lines
|
38
|
+
-c, --context-lines number of lines of context to provide with posted issue
|
38
39
|
-d, --dirs list of directories to search in
|
39
40
|
-f, --files list of files to search in
|
40
41
|
-h, --help print help
|
@@ -42,7 +43,7 @@ If no RC file exists, default RC file will be created
|
|
42
43
|
-p, --parse-depth depth to recursively parse directories
|
43
44
|
-r, --remote list / create tokens for Bitbucket/Github
|
44
45
|
-t, --tags list of tags to search for
|
45
|
-
-u, --update
|
46
|
+
-u, --update update remote repos with current issues
|
46
47
|
-v, --version print watson version and info
|
47
48
|
|
48
49
|
Any number of files, tags, dirs, and ignores can be listed after flag
|
@@ -139,9 +140,9 @@ Special thanks to [@crowell](http://github.com/crowell) for testing out watson-r
|
|
139
140
|
|
140
141
|
## FAQ
|
141
142
|
- **Why Ruby?**
|
142
|
-
|
143
|
+
I wanted to learn Ruby and this seemed like a pretty decent project.
|
143
144
|
|
144
145
|
- **Why is the Ruby version different from the Perl version?**
|
145
|
-
|
146
|
-
|
147
|
-
|
146
|
+
The Ruby version was developed after the Perl version was made. Because of this, it was a lot easier to add on features that were thought of while/after making the Perl version as the plumbing was still being setup.
|
147
|
+
With a combination of wanting to finish watson-ruby as well as laziness, some of the improvements that were added to watson-ruby *have yet* to be pulled back into watson-perl.
|
148
|
+
If you are interested in helping out or maintaining watson-perl let me know!
|
data/Rakefile
CHANGED
data/lib/watson.rb
CHANGED
@@ -8,62 +8,62 @@ require_relative 'watson/github'
|
|
8
8
|
require_relative 'watson/bitbucket'
|
9
9
|
|
10
10
|
module Watson
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
11
|
+
# [todo] - Replace all regex parentheses() with brackets[] if not matching
|
12
|
+
# Was using () to group things together for syntax instead of []
|
13
|
+
# Replace so we can get cleaner matches and don't need to keep track of matches
|
14
|
+
|
15
|
+
# [todo] - Change debug_print to provide its own \n
|
16
|
+
|
17
|
+
# [todo] - Add ability to pass "IDENTIFY" to debug_print to auto print method entry info
|
18
|
+
|
19
|
+
# [todo] - Make sure all methods have proper return at end
|
20
|
+
|
21
|
+
# [review] - Method input arg always renamed from arg to _arg inside method, change this?
|
22
|
+
# Not sure if I should just make input arg _arg or if explicit _ is useful
|
23
|
+
|
24
|
+
# [todo] - Add option to save output to specified file
|
25
|
+
# [todo] - Replace Identify line in each method with method_added call
|
26
|
+
# http://ruby-doc.org/core-2.0.0/Module.html#method-i-method_added
|
27
27
|
|
28
|
-
|
29
|
-
|
28
|
+
# Separate ON and OFF so we can force state and still let
|
29
|
+
# individual classes have some control over their prints
|
30
30
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
31
|
+
# Global flag to turn ON debugging across all files
|
32
|
+
GLOBAL_DEBUG_ON = false
|
33
|
+
# Gllobal flag to turn OFF debugging across all files
|
34
|
+
GLOBAL_DEBUG_OFF = false
|
35
35
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
36
|
+
# [review] - Not sure if module_function is proper way to scope
|
37
|
+
# I want to be able to call debug_print without having to use the scope
|
38
|
+
# operator (Watson::Printer.debug_print) so it is defined here as a
|
39
|
+
# module_function instead of having it in the Printer class
|
40
|
+
# Gets included into every class individually
|
41
|
+
module_function
|
42
|
+
|
43
|
+
###########################################################
|
44
|
+
# Global debug print that prints based on local file DEBUG flag as well as GLOBAL debug flag
|
45
|
+
def debug_print(msg)
|
46
|
+
# [todo] - If input msg is a Hash, use pp to dump it
|
47
47
|
|
48
|
-
|
49
|
-
|
50
|
-
|
48
|
+
# Print only if DEBUG flag of calling class is true OR
|
49
|
+
# GLOBAL_DEBUG_ON of Watson module (defined above) is true
|
50
|
+
# AND GLOBAL_DEBUG_OFF of Watson module (Defined above) is false
|
51
51
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
52
|
+
# Sometimes we call debug_print from a static method (class << self)
|
53
|
+
# and other times from a class method, and ::DEBUG is accessed differently
|
54
|
+
# from a class vs object, so lets take care of that
|
55
|
+
_DEBUG = (self.is_a? Class) ? self::DEBUG : self.class::DEBUG
|
56
56
|
|
57
|
-
|
58
|
-
|
57
|
+
print "=> #{msg}" if ( (_DEBUG == true || GLOBAL_DEBUG_ON == true) && (GLOBAL_DEBUG_OFF == false))
|
58
|
+
end
|
59
59
|
|
60
60
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
61
|
+
###########################################################
|
62
|
+
# Perform system check to see if we are able to use unix less for printing
|
63
|
+
def check_less
|
64
|
+
# Check if system has less (so we can print out to it to allow scrolling)
|
65
|
+
# [todo] - Implement this scrolling thing inside watson with ncurses
|
66
|
+
return system("which less > /dev/null 2>&1")
|
67
|
+
end
|
68
68
|
|
69
69
|
end
|
data/lib/watson/bitbucket.rb
CHANGED
@@ -1,373 +1,372 @@
|
|
1
1
|
module Watson
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
end
|
2
|
+
class Remote
|
3
|
+
# Bitbucket remote access class
|
4
|
+
# Contains all necessary methods to obtain access to, get issue list,
|
5
|
+
# and post issues to Bitbucket
|
6
|
+
class Bitbucket
|
7
|
+
|
8
|
+
# Debug printing for this class
|
9
|
+
DEBUG = false
|
10
|
+
|
11
|
+
class << self
|
12
|
+
|
13
|
+
# [todo] - Allow closing of issues from watson? Don't like that idea but maybe
|
14
|
+
# [todo] - Wrap Bitbucket password grabbing into separate method
|
15
|
+
|
16
|
+
# Include for debug_print
|
17
|
+
include Watson
|
18
|
+
|
19
|
+
#############################################################################
|
20
|
+
# Setup remote access to Bitbucket
|
21
|
+
# Get Username, Repo, and PW and perform necessary HTTP calls to check validity
|
22
|
+
def setup(config)
|
23
|
+
|
24
|
+
# Identify method entry
|
25
|
+
debug_print "#{ self.class } : #{ __method__ }\n"
|
26
|
+
|
27
|
+
Printer.print_status "+", GREEN
|
28
|
+
print BOLD + "Attempting to access Bitbucket...\n" + RESET
|
29
|
+
|
30
|
+
# Check config to make sure no previous repo info exists
|
31
|
+
unless config.bitbucket_api.empty? && config.bitbucket_repo.empty?
|
32
|
+
Printer.print_status "!", RED
|
33
|
+
print BOLD + "Previous Bitbucket API + Repo is in RC, are you sure you want to overwrite?\n" + RESET
|
34
|
+
print " (Y)es/(N)o: "
|
35
|
+
|
36
|
+
# Get user input
|
37
|
+
_overwrite = $stdin.gets.chomp
|
38
|
+
if ["no", "n"].include?(_overwrite.downcase)
|
39
|
+
print "\n"
|
40
|
+
Printer.print_status "x", RED
|
41
|
+
print BOLD + "Not overwriting current Bitbucket API + repo info\n" + RESET
|
42
|
+
return false
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
Printer.print_status "!", YELLOW
|
48
|
+
print BOLD + "Access to your Bitbucket account required to make/update issues\n" + RESET
|
49
|
+
print " See help or README for more details on GitHub/Bitbucket access\n\n"
|
50
|
+
|
51
|
+
|
52
|
+
# [todo] - Bitbucket OAuth not implemented yet so warn user about HTTP Auth
|
53
|
+
# Bitbucket doesn't have nonOAuth flow that GitHub does :(
|
54
|
+
# Even if I use OAuth lib, still need to validate from webview which is lame
|
55
|
+
Printer.print_status "!", RED
|
56
|
+
print BOLD + "Bitbucket OAuth not implemented yet.\n" + RESET;
|
57
|
+
print " Basic HTTP Auth in use, will request PW entry every time.\n\n"
|
58
|
+
|
59
|
+
|
60
|
+
# [todo] - Don't just check for blank password but invalid as well
|
61
|
+
# Poor mans username/password grabbing
|
62
|
+
print BOLD + "Username: " + RESET
|
63
|
+
_username = $stdin.gets.chomp
|
64
|
+
if _username.empty?
|
65
|
+
Printer.print_status "x", RED
|
66
|
+
print BOLD + "Input blank. Please enter your username!\n\n" + RESET
|
67
|
+
return false
|
68
|
+
end
|
69
|
+
|
70
|
+
print "\n"
|
71
|
+
|
72
|
+
# Get repo information, if blank give error
|
73
|
+
Printer.print_status "!", YELLOW
|
74
|
+
print BOLD + "Repo information required\n" + RESET
|
75
|
+
print " Please provide owner that repo is under followed by repo name\n"
|
76
|
+
print " e.g. owner: nhmood, repo: watson (case sensitive)\n"
|
77
|
+
print " See help or README for more details on GitHub access\n\n"
|
78
|
+
|
79
|
+
print BOLD + "Owner: " + RESET
|
80
|
+
_owner = $stdin.gets.chomp
|
81
|
+
if _owner.empty?
|
82
|
+
print "\n"
|
83
|
+
Printer.print_status "x", RED
|
84
|
+
print BOLD + "Input blank. Please enter the owner the repo is under!\n\n" + RESET
|
85
|
+
return false
|
86
|
+
end
|
87
|
+
|
88
|
+
print BOLD + "Repo: " + RESET
|
89
|
+
_repo = $stdin.gets.chomp
|
90
|
+
if _repo.empty?
|
91
|
+
print "\n"
|
92
|
+
Printer.print_status "x", RED
|
93
|
+
print BOLD + "Input blank. Please enter the repo name!\n\n" + RESET
|
94
|
+
return false
|
95
|
+
end
|
96
|
+
|
97
|
+
print "\n"
|
98
|
+
|
99
|
+
# [fix] - Crossplatform password block needed, not sure if current method is safe either
|
100
|
+
# Block output to tty to prevent PW showing, Linux/Unix only :(
|
101
|
+
print BOLD + "Password: " + RESET
|
102
|
+
system "stty -echo"
|
103
|
+
_password = $stdin.gets.chomp
|
104
|
+
system "stty echo"
|
105
|
+
print "\n"
|
106
|
+
if _password.empty?
|
107
|
+
Printer.print_status "x", RED
|
108
|
+
print BOLD + "Input is blank. Please enter your password!\n\n" + RESET
|
109
|
+
return false
|
110
|
+
end
|
111
|
+
|
112
|
+
# HTTP Request to check if Repo exists and user has access
|
113
|
+
# http://confluence.atlassian.com/display/BITBUCKET/Use+the+Bitbucket+REST+APIs
|
114
|
+
|
115
|
+
# Create options hash to pass to Remote::http_call
|
116
|
+
# Endpoint for accessing Repo as User with SSL
|
117
|
+
# Basic auth with user input
|
118
|
+
opts = {:url => "https://bitbucket.org/api/1.0/repositories/#{_owner}/#{_repo}",
|
119
|
+
:ssl => true,
|
120
|
+
:method => "GET",
|
121
|
+
:basic_auth => [_username, _password],
|
122
|
+
:verbose => false
|
123
|
+
}
|
124
|
+
|
125
|
+
_json, _resp = Watson::Remote.http_call(opts)
|
126
|
+
|
127
|
+
# Check response to validate authorization
|
128
|
+
if _resp.code == "200"
|
129
|
+
print "\n"
|
130
|
+
Printer.print_status "o", GREEN
|
131
|
+
print BOLD + "Successfully accessed remote repo with given credentials\n" + RESET
|
132
|
+
else
|
133
|
+
print "\n"
|
134
|
+
Printer.print_status "x", RED
|
135
|
+
print BOLD + "Unable to access /#{ _owner }/#{ _repo } with given credentials\n" + RESET
|
136
|
+
print " Check that credentials are correct and repository exists under user\n"
|
137
|
+
print " Status: #{ _resp.code } - #{ _resp.message }\n\n"
|
138
|
+
return false
|
139
|
+
end
|
140
|
+
|
141
|
+
|
142
|
+
# No OAuth for Bitbucket yet so just store username in api for config
|
143
|
+
# This will let us just prompt for PW
|
144
|
+
config.bitbucket_api = _username
|
145
|
+
config.bitbucket_pw = _password # Never gets written to file
|
146
|
+
config.bitbucket_repo = "#{ _owner }/#{ _repo }"
|
147
|
+
debug_print " \n"
|
148
|
+
|
149
|
+
# All setup has been completed, need to update RC
|
150
|
+
# Call config updater/writer from @config to write config
|
151
|
+
debug_print "Updating config with new Bitbucket info\n"
|
152
|
+
config.update_conf("bitbucket_api", "bitbucket_repo")
|
153
|
+
|
154
|
+
print "\n"
|
155
|
+
Printer.print_status "o", GREEN
|
156
|
+
print BOLD + "Bitbucket successfully setup\n" + RESET
|
157
|
+
print " Issues will now automatically be retrieved from Bitbucket by default\n"
|
158
|
+
print " Use -p, --push to post issues to GitHub\n"
|
159
|
+
print " See help or README for more details on GitHub/Bitbucket access\n\n"
|
160
|
+
|
161
|
+
return true
|
162
|
+
|
163
|
+
end
|
164
|
+
|
165
|
+
|
166
|
+
###########################################################
|
167
|
+
# Get all remote Bitbucket issues and store into Config container class
|
168
|
+
def get_issues(config)
|
169
|
+
|
170
|
+
# Identify method entry
|
171
|
+
debug_print "#{ self.class } : #{ __method__ }\n"
|
172
|
+
|
173
|
+
# Only attempt to get issues if API is specified
|
174
|
+
if config.bitbucket_api.empty?
|
175
|
+
debug_print "No API found, this shouldn't be called...\n"
|
176
|
+
return false
|
177
|
+
end
|
178
|
+
|
179
|
+
# If we haven't obtained the pw from user yet, do it
|
180
|
+
if config.bitbucket_pw.empty?
|
181
|
+
# No OAuth for Bitbucket yet, gotta get user password in order to make calls :(
|
182
|
+
Printer.print_status "!", YELLOW
|
183
|
+
print BOLD + "Bitbucket password required for remote checking/posting.\n" + RESET
|
184
|
+
print " Password: "
|
185
|
+
|
186
|
+
# Block output to tty to prevent PW showing, Linux/Unix only :(
|
187
|
+
system "stty -echo"
|
188
|
+
_password = $stdin.gets.chomp
|
189
|
+
system "stty echo"
|
190
|
+
if _password.empty?
|
191
|
+
print "Input is blank. Please enter your password!\n"
|
192
|
+
return false
|
193
|
+
else
|
194
|
+
print "\n"
|
195
|
+
end
|
196
|
+
|
197
|
+
config.bitbucket_pw = _password
|
198
|
+
end
|
199
|
+
|
200
|
+
|
201
|
+
# Get all open tickets (anything but resolved)
|
202
|
+
# Create options hash to pass to Remote::http_call
|
203
|
+
# Issues URL for Bitbucket + SSL
|
204
|
+
opts = {:url => "https://bitbucket.org/api/1.0/repositories/#{ config.bitbucket_repo }/issues?status=!resolved",
|
205
|
+
:ssl => true,
|
206
|
+
:method => "GET",
|
207
|
+
:basic_auth => [config.bitbucket_api, config.bitbucket_pw],
|
208
|
+
:verbose => false
|
209
|
+
}
|
210
|
+
|
211
|
+
_json, _resp = Watson::Remote.http_call(opts)
|
212
|
+
|
213
|
+
|
214
|
+
# Check response to validate repo access
|
215
|
+
if _resp.code != "200"
|
216
|
+
Printer.print_status "x", RED
|
217
|
+
print BOLD + "Unable to access remote #{ config.bitbucket_repo }, Bitbucket API may be invalid\n" + RESET
|
218
|
+
print " Make sure you have created an issue tracker for your repository on the Bitbucket website\n"
|
219
|
+
print " Consider running --remote (-r) option to regenerate/validate settings\n"
|
220
|
+
print " Status: #{ _resp.code } - #{ _resp.message }\n\n"
|
221
|
+
|
222
|
+
debug_print "Bitbucket invalid, setting config var\n"
|
223
|
+
config.bitbucket_valid = false
|
224
|
+
return false
|
225
|
+
end
|
226
|
+
|
227
|
+
|
228
|
+
|
229
|
+
config.bitbucket_issues[:open] = _json["issues"].empty? ? Hash.new : _json["issues"]
|
230
|
+
config.bitbucket_valid = true
|
231
|
+
|
232
|
+
# Get all closed tickets
|
233
|
+
# Create options hash to pass to Remote::http_call
|
234
|
+
# Issues URL for Bitbucket + SSL
|
235
|
+
opts = {:url => "https://bitbucket.org/api/1.0/repositories/#{ config.bitbucket_repo }/issues?status=resolved",
|
236
|
+
:ssl => true,
|
237
|
+
:method => "GET",
|
238
|
+
:basic_auth => [config.bitbucket_api, config.bitbucket_pw],
|
239
|
+
:verbose => false
|
240
|
+
}
|
241
|
+
|
242
|
+
_json, _resp = Watson::Remote.http_call(opts)
|
243
|
+
|
244
|
+
# Check response to validate repo access
|
245
|
+
# Shouldn't be necessary if we passed the last check but just to be safe
|
246
|
+
if _resp.code != "200"
|
247
|
+
Printer.print_status "x", RED
|
248
|
+
print BOLD + "Unable to get closed issues.\n" + RESET
|
249
|
+
print " Since the open issues were obtained, something is probably wrong and you should file a bug report or something...\n"
|
250
|
+
print " Status: #{ _resp.code } - #{ _resp.message }\n"
|
251
|
+
|
252
|
+
debug_print "Bitbucket invalid, setting config var\n"
|
253
|
+
config.bitbucket_valid = false
|
254
|
+
return false
|
255
|
+
end
|
256
|
+
|
257
|
+
config.bitbucket_issues[:closed] = _json["issues"].empty? ? Hash.new : _json["issues"]
|
258
|
+
config.bitbucket_valid = true
|
259
|
+
return true
|
260
|
+
end
|
261
|
+
|
262
|
+
|
263
|
+
###########################################################
|
264
|
+
# Post given issue to remote Bitbucket repo
|
265
|
+
def post_issue(issue, config)
|
266
|
+
# [todo] - Better way to identify/compare remote->local issues than md5
|
267
|
+
# Current md5 based on some things that easily can change, need better ident
|
268
|
+
|
269
|
+
# Identify method entry
|
270
|
+
debug_print "#{self.class} : #{__method__}\n"
|
271
|
+
|
272
|
+
|
273
|
+
# Only attempt to get issues if API is specified
|
274
|
+
if config.bitbucket_api.empty?
|
275
|
+
debug_print "No API found, this shouldn't be called...\n"
|
276
|
+
return false
|
277
|
+
end
|
278
|
+
|
279
|
+
# Check that issue hasn't been posted already by comparing md5s
|
280
|
+
# Go through all open issues, if there is a match in md5, return out of method
|
281
|
+
# [todo] - Play with idea of making body of GitHub issue hash format to be exec'd
|
282
|
+
# Store pieces in text as :md5 => "whatever" so when we get issues we can
|
283
|
+
# call exec and turn it into a real hash for parsing in watson
|
284
|
+
# Makes watson code cleaner but not as readable comment on GitHub...?
|
285
|
+
debug_print "Checking open issues to see if already posted\n"
|
286
|
+
config.bitbucket_issues[:open].each do | _open |
|
287
|
+
if _open["content"].include?(issue[:md5])
|
288
|
+
debug_print "Found in #{ _open["title"] }, not posting\n"
|
289
|
+
return false
|
290
|
+
end
|
291
|
+
debug_print "Did not find in #{_open["title"]}\n"
|
292
|
+
end
|
293
|
+
|
294
|
+
debug_print "Checking closed issues to see if already posted\n"
|
295
|
+
config.bitbucket_issues[:closed].each do | _closed |
|
296
|
+
if _closed["content"].include?(issue[:md5])
|
297
|
+
debug_print "Found in #{ _closed["title"] }, not posting\n"
|
298
|
+
return false
|
299
|
+
end
|
300
|
+
debug_print "Did not find in #{ _closed["title"] }\n"
|
301
|
+
end
|
302
|
+
|
303
|
+
|
304
|
+
# If we haven't obtained the pw from user yet, do it
|
305
|
+
if config.bitbucket_pw.empty?
|
306
|
+
# No OAuth for Bitbucket yet, gotta get user password in order to make calls :(
|
307
|
+
Printer.print_status "!", YELLOW
|
308
|
+
print BOLD + "Bitbucket password required for remote checking/posting.\n" + RESET
|
309
|
+
print " Password: "
|
310
|
+
|
311
|
+
# Block output to tty to prevent PW showing, Linux/Unix only :(
|
312
|
+
print "Password: "
|
313
|
+
system "stty -echo"
|
314
|
+
_password = $stdin.gets.chomp
|
315
|
+
system "stty echo"
|
316
|
+
if _password.empty?
|
317
|
+
print "Input is blank. Please enter your password!\n"
|
318
|
+
return false
|
319
|
+
else
|
320
|
+
print "\n"
|
321
|
+
end
|
322
|
+
|
323
|
+
config.bitbucket_pw = _password
|
324
|
+
end
|
325
|
+
|
326
|
+
|
327
|
+
|
328
|
+
|
329
|
+
# We didn't find the md5 for this issue in the open or closed issues, so safe to post
|
330
|
+
|
331
|
+
# Create the body text for the issue here, too long to fit nicely into opts hash
|
332
|
+
# [review] - Only give relative path for privacy when posted
|
333
|
+
_body = "__filename__ : #{ issue[:path] } \n" +
|
334
|
+
"__line #__ : #{ issue[:line_number] } \n" +
|
335
|
+
"__tag__ : #{ issue[:tag] } \n" +
|
336
|
+
"__md5__ : #{ issue[:md5] } \n\n" +
|
337
|
+
"#{ issue[:context].join }"
|
338
|
+
|
339
|
+
# Create option hash to pass to Remote::http_call
|
340
|
+
# Issues URL for GitHub + SSL
|
341
|
+
# No tag or label concept in Bitbucket unfortunately :(
|
342
|
+
opts = {:url => "https://bitbucket.org/api/1.0/repositories/#{ config.bitbucket_repo }/issues",
|
343
|
+
:ssl => true,
|
344
|
+
:method => "POST",
|
345
|
+
:basic_auth => [config.bitbucket_api, config.bitbucket_pw],
|
346
|
+
:data => [{"title" => issue[:title] + " [#{ issue[:path] }]",
|
347
|
+
"content" => _body }],
|
348
|
+
:verbose => false
|
349
|
+
}
|
350
|
+
|
351
|
+
_json, _resp = Watson::Remote.http_call(opts)
|
352
|
+
|
353
|
+
|
354
|
+
# Check response to validate repo access
|
355
|
+
# Shouldn't be necessary if we passed the last check but just to be safe
|
356
|
+
if _resp.code != "200"
|
357
|
+
Printer.print_status "x", RED
|
358
|
+
print BOLD + "Post unsuccessful. \n" + RESET
|
359
|
+
print " Since the open issues were obtained earlier, something is probably wrong and you should let someone know...\n"
|
360
|
+
print " Status: #{ _resp.code } - #{ _resp.message }\n"
|
361
|
+
return false
|
362
|
+
end
|
363
|
+
|
364
|
+
return true
|
365
|
+
end
|
366
|
+
|
367
|
+
end
|
368
|
+
|
369
|
+
|
370
|
+
end
|
371
|
+
end
|
373
372
|
end
|