hub 1.10.2 → 1.10.3
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of hub might be problematic. Click here for more details.
- data/HISTORY.md +11 -0
- data/README.md +37 -8
- data/lib/hub.rb +1 -1
- data/lib/hub/commands.rb +18 -8
- data/lib/hub/context.rb +16 -9
- data/lib/hub/github_api.rb +24 -8
- data/lib/hub/json.rb +16 -4
- data/lib/hub/version.rb +1 -1
- data/man/hub.1 +4 -1
- data/man/hub.1.html +4 -1
- data/man/hub.1.ronn +3 -0
- data/test/helper.rb +16 -0
- data/test/hub_test.rb +9 -8
- metadata +3 -3
data/HISTORY.md
CHANGED
@@ -1,3 +1,14 @@
|
|
1
|
+
## 1.10.3 (2012-11-22)
|
2
|
+
|
3
|
+
* fix `browse` on Windows
|
4
|
+
* fix hub on JRuby
|
5
|
+
* try fixing Ruby 1.8.7 error with API requests
|
6
|
+
* fix various edge cases around `create` command
|
7
|
+
* have `fork` set up a remote even if own fork already exists
|
8
|
+
* fix `pull-request` with Unicode chars on Ruby 1.8
|
9
|
+
* respect $GITHUB_USER & $GITHUB_PASSWORD
|
10
|
+
* improve reading git remotes configuration
|
11
|
+
|
1
12
|
## 1.10.2 (2012-07-24)
|
2
13
|
|
3
14
|
* fix pushing multiple refs to multiple remotes
|
data/README.md
CHANGED
@@ -79,20 +79,49 @@ $ cd hub
|
|
79
79
|
$ rake install prefix=/usr/local
|
80
80
|
~~~
|
81
81
|
|
82
|
-
### Help! It's
|
82
|
+
### Help! It's slow!
|
83
83
|
|
84
|
-
Is
|
84
|
+
#### Is `hub` noticeably slower than plain git?
|
85
85
|
|
86
|
-
|
87
|
-
|
86
|
+
That is inconvenient, especially if you want to alias hub as `git`. Few things
|
87
|
+
you can try:
|
88
88
|
|
89
|
-
|
89
|
+
* Find out which ruby is used for the hub executable:
|
90
90
|
|
91
|
-
|
91
|
+
``` sh
|
92
|
+
head -1 `which hub`
|
93
|
+
```
|
92
94
|
|
93
|
-
|
95
|
+
* That ruby should be speedy. Time it with:
|
94
96
|
|
95
|
-
|
97
|
+
``` sh
|
98
|
+
time /usr/bin/ruby -e0
|
99
|
+
#=> it should be below 0.01 s total
|
100
|
+
```
|
101
|
+
|
102
|
+
* Check that Ruby isn't loading something shady:
|
103
|
+
|
104
|
+
``` sh
|
105
|
+
echo $RUBYOPT
|
106
|
+
```
|
107
|
+
|
108
|
+
* Check your [GC settings][gc]
|
109
|
+
|
110
|
+
General recommendation: you should change hub's shebang line to run with system
|
111
|
+
ruby (usually `/usr/bin/ruby`) instead of currently active ruby (`/usr/bin/env
|
112
|
+
ruby`). Also, Ruby 1.8 is speedier than 1.9.
|
113
|
+
|
114
|
+
#### Is your shell prompt slow?
|
115
|
+
|
116
|
+
Does your prompt show git information? Hub may be slowing down your prompt.
|
117
|
+
|
118
|
+
This can happen if you've aliased hub as `git`. This is fine when you use `git`
|
119
|
+
manually, but may be unacceptable for your prompt, which doesn't need hub
|
120
|
+
features anyway!
|
121
|
+
|
122
|
+
The solution is to identify which shell functions are calling `git`, and replace
|
123
|
+
each occurrence of that with `command git`. This is a shell feature that enables
|
124
|
+
you to call a command directly and skip aliases and functions wrapping it.
|
96
125
|
|
97
126
|
|
98
127
|
Aliasing
|
data/lib/hub.rb
CHANGED
data/lib/hub/commands.rb
CHANGED
@@ -9,12 +9,12 @@ module Hub
|
|
9
9
|
# 1. hub is invoked from the command line:
|
10
10
|
# $ hub clone rtomayko/tilt
|
11
11
|
#
|
12
|
-
# 2. The
|
13
|
-
# >>
|
12
|
+
# 2. The Runner class is initialized:
|
13
|
+
# >> Hub::Runner.new('clone', 'rtomayko/tilt')
|
14
14
|
#
|
15
15
|
# 3. The method representing the git subcommand is executed with the
|
16
16
|
# full args:
|
17
|
-
# >> Commands.clone('clone', 'rtomayko/tilt')
|
17
|
+
# >> Hub::Commands.clone(['clone', 'rtomayko/tilt'])
|
18
18
|
#
|
19
19
|
# 4. That method rewrites the args as it sees fit:
|
20
20
|
# >> args[1] = "git://github.com/" + args[1] + ".git"
|
@@ -465,9 +465,14 @@ module Hub
|
|
465
465
|
end
|
466
466
|
forked_project = project.owned_by(github_user(project.host))
|
467
467
|
|
468
|
-
|
469
|
-
|
470
|
-
|
468
|
+
existing_repo = api_client.repo_info(forked_project)
|
469
|
+
if existing_repo.success?
|
470
|
+
parent_data = existing_repo.data['parent']
|
471
|
+
parent_url = parent_data && resolve_github_url(parent_data['html_url'])
|
472
|
+
if !parent_url or parent_url.project != project
|
473
|
+
abort "Error creating fork: %s already exists on %s" %
|
474
|
+
[ forked_project.name_with_owner, forked_project.host ]
|
475
|
+
end
|
471
476
|
else
|
472
477
|
api_client.fork_repo(project) unless args.noop?
|
473
478
|
end
|
@@ -520,7 +525,10 @@ module Hub
|
|
520
525
|
action = "set remote origin"
|
521
526
|
else
|
522
527
|
action = "created repository"
|
523
|
-
|
528
|
+
unless args.noop?
|
529
|
+
repo_data = api_client.create_repo(new_project, options)
|
530
|
+
new_project = github_project(repo_data['full_name'])
|
531
|
+
end
|
524
532
|
end
|
525
533
|
|
526
534
|
url = new_project.git_url(:private => true, :https => https_protocol?)
|
@@ -949,6 +957,8 @@ help
|
|
949
957
|
read.close
|
950
958
|
write.close
|
951
959
|
end
|
960
|
+
rescue NotImplementedError
|
961
|
+
# fork might not available, such as in JRuby
|
952
962
|
end
|
953
963
|
|
954
964
|
def pullrequest_editmsg(changes)
|
@@ -993,7 +1003,7 @@ help
|
|
993
1003
|
end
|
994
1004
|
end
|
995
1005
|
end
|
996
|
-
|
1006
|
+
|
997
1007
|
def display_api_exception(action, response)
|
998
1008
|
$stderr.puts "Error #{action}: #{response.message.strip} (HTTP #{response.status})"
|
999
1009
|
if 422 == response.status and response.error_message?
|
data/lib/hub/context.rb
CHANGED
@@ -220,6 +220,7 @@ module Hub
|
|
220
220
|
|
221
221
|
def initialize(*args)
|
222
222
|
super
|
223
|
+
self.name = self.name.tr(' ', '-')
|
223
224
|
self.host ||= (local_repo || LocalRepo).default_host
|
224
225
|
self.host = host.sub(/^ssh\./i, '') if 'ssh.github.com' == host.downcase
|
225
226
|
end
|
@@ -331,7 +332,7 @@ module Hub
|
|
331
332
|
end
|
332
333
|
|
333
334
|
def project
|
334
|
-
urls.
|
335
|
+
urls.each_value { |url|
|
335
336
|
if valid = GithubProject.from_url(url, local_repo)
|
336
337
|
return valid
|
337
338
|
end
|
@@ -340,15 +341,21 @@ module Hub
|
|
340
341
|
end
|
341
342
|
|
342
343
|
def urls
|
343
|
-
@urls
|
344
|
-
|
345
|
-
|
346
|
-
|
344
|
+
return @urls if defined? @urls
|
345
|
+
@urls = {}
|
346
|
+
local_repo.git_command('remote -v').to_s.split("\n").map do |line|
|
347
|
+
next if line !~ /^(.+?)\t(.+) \((.+)\)$/
|
348
|
+
remote, uri, type = $1, $2, $3
|
349
|
+
next if remote != self.name
|
350
|
+
if uri =~ %r{^[\w-]+://} or uri =~ %r{^([^/]+?):}
|
351
|
+
uri = "ssh://#{$1}/#{$'}" if $1
|
352
|
+
begin
|
353
|
+
@urls[type] = uri_parse(uri)
|
354
|
+
rescue URI::InvalidURIError
|
347
355
|
end
|
348
|
-
rescue URI::InvalidURIError
|
349
|
-
nil
|
350
356
|
end
|
351
|
-
|
357
|
+
end
|
358
|
+
@urls
|
352
359
|
end
|
353
360
|
|
354
361
|
def uri_parse uri
|
@@ -435,7 +442,7 @@ module Hub
|
|
435
442
|
# Returns an array, e.g.: ['open']
|
436
443
|
def browser_launcher
|
437
444
|
browser = ENV['BROWSER'] || (
|
438
|
-
osx? ? 'open' : windows? ?
|
445
|
+
osx? ? 'open' : windows? ? %w[cmd /c start] :
|
439
446
|
%w[xdg-open cygstart x-www-browser firefox opera mozilla netscape].find { |comm| which comm }
|
440
447
|
)
|
441
448
|
|
data/lib/hub/github_api.rb
CHANGED
@@ -77,6 +77,7 @@ module Hub
|
|
77
77
|
res = post "https://%s/user/repos" % api_host(project.host), params
|
78
78
|
end
|
79
79
|
res.error! unless res.success?
|
80
|
+
res.data
|
80
81
|
end
|
81
82
|
|
82
83
|
# Public: Fetch info about a pull request.
|
@@ -111,7 +112,10 @@ module Hub
|
|
111
112
|
|
112
113
|
# Methods for performing HTTP requests
|
113
114
|
#
|
114
|
-
# Requires access to a `config` object that implements
|
115
|
+
# Requires access to a `config` object that implements:
|
116
|
+
# - proxy_uri(with_ssl)
|
117
|
+
# - username(host)
|
118
|
+
# - password(host, user)
|
115
119
|
module HttpMethods
|
116
120
|
# Decorator for Net::HTTPResponse
|
117
121
|
module ResponseMethods
|
@@ -139,10 +143,17 @@ module Hub
|
|
139
143
|
perform_request url, :Post do |req|
|
140
144
|
if params
|
141
145
|
req.body = JSON.dump params
|
142
|
-
req['Content-Type'] = 'application/json'
|
146
|
+
req['Content-Type'] = 'application/json;charset=utf-8'
|
143
147
|
end
|
144
148
|
yield req if block_given?
|
145
|
-
req['Content-Length'] =
|
149
|
+
req['Content-Length'] = byte_size req.body
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def byte_size str
|
154
|
+
if str.respond_to? :bytesize then str.bytesize
|
155
|
+
elsif str.respond_to? :length then str.length
|
156
|
+
else 0
|
146
157
|
end
|
147
158
|
end
|
148
159
|
|
@@ -162,11 +173,14 @@ module Hub
|
|
162
173
|
|
163
174
|
apply_authentication(req, url)
|
164
175
|
yield req if block_given?
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
176
|
+
|
177
|
+
begin
|
178
|
+
res = http.start { http.request(req) }
|
179
|
+
res.extend ResponseMethods
|
180
|
+
return res
|
181
|
+
rescue SocketError => err
|
182
|
+
raise Context::FatalError, "error with #{type.to_s.upcase} #{url} (#{err.message})"
|
183
|
+
end
|
170
184
|
end
|
171
185
|
|
172
186
|
def request_uri url
|
@@ -316,6 +330,7 @@ module Hub
|
|
316
330
|
end
|
317
331
|
|
318
332
|
def username host
|
333
|
+
return ENV['GITHUB_USER'] unless ENV['GITHUB_USER'].to_s.empty?
|
319
334
|
host = normalize_host host
|
320
335
|
@data.fetch_user host do
|
321
336
|
if block_given? then yield
|
@@ -334,6 +349,7 @@ module Hub
|
|
334
349
|
end
|
335
350
|
|
336
351
|
def password host, user
|
352
|
+
return ENV['GITHUB_PASSWORD'] unless ENV['GITHUB_PASSWORD'].to_s.empty?
|
337
353
|
host = normalize_host host
|
338
354
|
@password_cache["#{user}@#{host}"] ||= prompt_password host, user
|
339
355
|
end
|
data/lib/hub/json.rb
CHANGED
@@ -111,10 +111,22 @@ class Hub::JSON
|
|
111
111
|
end
|
112
112
|
end
|
113
113
|
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
114
|
+
ESC_MAP = Hash.new {|h,k| k }.update \
|
115
|
+
"\r" => 'r',
|
116
|
+
"\n" => 'n',
|
117
|
+
"\f" => 'f',
|
118
|
+
"\t" => 't',
|
119
|
+
"\b" => 'b'
|
120
|
+
|
121
|
+
def generate_String(str)
|
122
|
+
escaped = str.gsub(/[\r\n\f\t\b"\\]/) { "\\#{ESC_MAP[$&]}"}
|
123
|
+
%("#{escaped}")
|
124
|
+
end
|
125
|
+
|
126
|
+
def generate_simple(obj) obj.inspect end
|
127
|
+
alias generate_Numeric generate_simple
|
128
|
+
alias generate_TrueClass generate_simple
|
129
|
+
alias generate_FalseClass generate_simple
|
118
130
|
|
119
131
|
def generate_Symbol(sym) generate_String(sym.to_s) end
|
120
132
|
|
data/lib/hub/version.rb
CHANGED
data/man/hub.1
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
.\" generated with Ronn/v0.7.3
|
2
2
|
.\" http://github.com/rtomayko/ronn/tree/0.7.3
|
3
3
|
.
|
4
|
-
.TH "HUB" "1" "
|
4
|
+
.TH "HUB" "1" "November 2012" "DEFUNKT" "Git Manual"
|
5
5
|
.
|
6
6
|
.SH "NAME"
|
7
7
|
\fBhub\fR \- git + hub = github
|
@@ -155,6 +155,9 @@ If instead of normal \fITITLE\fR an issue number is given with \fB\-i\fR, the pu
|
|
155
155
|
Hub will prompt for GitHub username & password the first time it needs to access the API and exchange it for an OAuth token, which it saves in "~/\.config/hub"\.
|
156
156
|
.
|
157
157
|
.P
|
158
|
+
To avoid being prompted, use \fIGITHUB_USER\fR and \fIGITHUB_PASSWORD\fR environment variables\.
|
159
|
+
.
|
160
|
+
.P
|
158
161
|
If you prefer the HTTPS protocol for GitHub repositories, you can set "hub\.protocol" to "https"\. This will affect \fBclone\fR, \fBfork\fR, \fBremote add\fR and other operations that expand references to GitHub repositories as full URLs that otherwise use git and ssh protocols\.
|
159
162
|
.
|
160
163
|
.IP "" 4
|
data/man/hub.1.html
CHANGED
@@ -199,6 +199,9 @@ of title you can paste a full URL to an issue on GitHub.</p></dd>
|
|
199
199
|
<p>Hub will prompt for GitHub username & password the first time it needs to access
|
200
200
|
the API and exchange it for an OAuth token, which it saves in "~/.config/hub".</p>
|
201
201
|
|
202
|
+
<p>To avoid being prompted, use <var>GITHUB_USER</var> and <var>GITHUB_PASSWORD</var> environment
|
203
|
+
variables.</p>
|
204
|
+
|
202
205
|
<p>If you prefer the HTTPS protocol for GitHub repositories, you can set
|
203
206
|
"hub.protocol" to "https". This will affect <code>clone</code>, <code>fork</code>, <code>remote add</code>
|
204
207
|
and other operations that expand references to GitHub repositories as full
|
@@ -437,7 +440,7 @@ $ git help hub
|
|
437
440
|
|
438
441
|
<ol class='man-decor man-foot man foot'>
|
439
442
|
<li class='tl'>DEFUNKT</li>
|
440
|
-
<li class='tc'>
|
443
|
+
<li class='tc'>November 2012</li>
|
441
444
|
<li class='tr'>hub(1)</li>
|
442
445
|
</ol>
|
443
446
|
|
data/man/hub.1.ronn
CHANGED
@@ -156,6 +156,9 @@ hub also adds some custom commands that are otherwise not present in git:
|
|
156
156
|
Hub will prompt for GitHub username & password the first time it needs to access
|
157
157
|
the API and exchange it for an OAuth token, which it saves in "~/.config/hub".
|
158
158
|
|
159
|
+
To avoid being prompted, use <GITHUB_USER> and <GITHUB_PASSWORD> environment
|
160
|
+
variables.
|
161
|
+
|
159
162
|
If you prefer the HTTPS protocol for GitHub repositories, you can set
|
160
163
|
"hub.protocol" to "https". This will affect `clone`, `fork`, `remote add`
|
161
164
|
and other operations that expand references to GitHub repositories as full
|
data/test/helper.rb
CHANGED
@@ -11,6 +11,22 @@ ENV['PATH'] = "#{fakebin_dir}:#{ENV['PATH']}"
|
|
11
11
|
# Use an isolated config file in testing
|
12
12
|
ENV['HUB_CONFIG'] = File.join(ENV['TMPDIR'] || '/tmp', 'hub-test-config')
|
13
13
|
|
14
|
+
# Disable `abort` and `exit` in the main test process, but allow it in
|
15
|
+
# subprocesses where we need to test does a command properly bail out.
|
16
|
+
Hub::Commands.extend Module.new {
|
17
|
+
main_pid = Process.pid
|
18
|
+
|
19
|
+
[:abort, :exit].each do |method|
|
20
|
+
define_method method do |*args|
|
21
|
+
if Process.pid == main_pid
|
22
|
+
raise "#{method} is disabled"
|
23
|
+
else
|
24
|
+
super(*args)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
}
|
29
|
+
|
14
30
|
class Test::Unit::TestCase
|
15
31
|
# Shortcut for creating a `Hub` instance. Pass it what you would
|
16
32
|
# normally pass `hub` on the command line, e.g.
|
data/test/hub_test.rb
CHANGED
@@ -10,6 +10,13 @@ WebMock::BodyPattern.class_eval do
|
|
10
10
|
undef normalize_hash
|
11
11
|
# override normalizing hash since it otherwise requires JSON
|
12
12
|
def normalize_hash(hash) hash end
|
13
|
+
|
14
|
+
# strip out the "charset" directive from Content-type value
|
15
|
+
alias matches_with_dumb_content_type matches?
|
16
|
+
def matches?(body, content_type = "")
|
17
|
+
content_type = content_type.split(';').first if content_type.respond_to? :split
|
18
|
+
matches_with_dumb_content_type(body, content_type)
|
19
|
+
end
|
13
20
|
end
|
14
21
|
|
15
22
|
class HubTest < Test::Unit::TestCase
|
@@ -74,8 +81,7 @@ class HubTest < Test::Unit::TestCase
|
|
74
81
|
@git_reader.stub! \
|
75
82
|
'remote' => "mislav\norigin",
|
76
83
|
'symbolic-ref -q HEAD' => 'refs/heads/master',
|
77
|
-
'
|
78
|
-
'config --get-all remote.mislav.url' => 'git://github.com/mislav/hub.git',
|
84
|
+
'remote -v' => "origin\tgit://github.com/defunkt/hub.git (fetch)\nmislav\tgit://github.com/mislav/hub.git (fetch)",
|
79
85
|
'rev-parse --symbolic-full-name master@{upstream}' => 'refs/remotes/origin/master',
|
80
86
|
'config --get --bool hub.http-clone' => 'false',
|
81
87
|
'config --get hub.protocol' => nil,
|
@@ -641,11 +647,6 @@ class HubTest < Test::Unit::TestCase
|
|
641
647
|
assert_forwarded 'name'
|
642
648
|
end
|
643
649
|
|
644
|
-
def test_multiple_remote_urls
|
645
|
-
stub_repo_url("git://example.com/other.git\ngit://github.com/my/repo.git")
|
646
|
-
assert_command "browse", "open https://github.com/my/repo"
|
647
|
-
end
|
648
|
-
|
649
650
|
def test_global_flags_preserved
|
650
651
|
cmd = '--no-pager --bare -c core.awesome=true -c name=value --git-dir=/srv/www perform'
|
651
652
|
assert_command cmd, 'git --bare -c core.awesome=true -c name=value --git-dir=/srv/www --no-pager perform'
|
@@ -655,7 +656,7 @@ class HubTest < Test::Unit::TestCase
|
|
655
656
|
private
|
656
657
|
|
657
658
|
def stub_repo_url(value, remote_name = 'origin')
|
658
|
-
|
659
|
+
stub_command_output 'remote -v', "#{remote_name}\t#{value} (fetch)"
|
659
660
|
end
|
660
661
|
|
661
662
|
def stub_branch(value)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hub
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.10.
|
4
|
+
version: 1.10.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2012-
|
13
|
+
date: 2012-11-22 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rake
|
@@ -104,7 +104,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
104
104
|
version: '0'
|
105
105
|
requirements: []
|
106
106
|
rubyforge_project:
|
107
|
-
rubygems_version: 1.8.
|
107
|
+
rubygems_version: 1.8.23
|
108
108
|
signing_key:
|
109
109
|
specification_version: 3
|
110
110
|
summary: Command-line wrapper for git and GitHub
|