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 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 Slow!
82
+ ### Help! It's slow!
83
83
 
84
- Is your prompt slow? It may be hub.
84
+ #### Is `hub` noticeably slower than plain git?
85
85
 
86
- 1. Check that it's **not** installed using RubyGems.
87
- 2. Check that RUBYOPT isn't loading anything shady:
86
+ That is inconvenient, especially if you want to alias hub as `git`. Few things
87
+ you can try:
88
88
 
89
- $ echo $RUBYOPT
89
+ * Find out which ruby is used for the hub executable:
90
90
 
91
- 3. Check that your system Ruby is speedy:
91
+ ``` sh
92
+ head -1 `which hub`
93
+ ```
92
94
 
93
- $ time /usr/bin/env ruby -e0
95
+ * That ruby should be speedy. Time it with:
94
96
 
95
- If #3 is slow, it may be your [GC settings][gc].
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
@@ -1,4 +1,4 @@
1
- require 'hub/version'
1
+ require 'hub/version' unless defined?(Hub::VERSION)
2
2
  require 'hub/args'
3
3
  require 'hub/ssh_config'
4
4
  require 'hub/github_api'
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 Hub class is initialized:
13
- # >> hub = Hub.new('clone', 'rtomayko/tilt')
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
- if api_client.repo_exists?(forked_project)
469
- abort "Error creating fork: %s already exists on %s" %
470
- [ forked_project.name_with_owner, forked_project.host ]
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
- api_client.create_repo(new_project, options) unless args.noop?
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.each { |url|
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 ||= local_repo.git_config("remote.#{name}.url", :all).to_s.split("\n").map { |uri|
344
- begin
345
- if uri =~ %r{^[\w-]+://} then uri_parse(uri)
346
- elsif uri =~ %r{^([^/]+?):} then uri_parse("ssh://#{$1}/#{$'}") # scp-like syntax
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
- }.compact
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? ? 'start' :
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
 
@@ -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 `proxy_uri(with_ssl)`
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'] = req.body ? req.body.length : 0
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
- res = http.start { http.request(req) }
166
- res.extend ResponseMethods
167
- res
168
- rescue SocketError => err
169
- raise Context::FatalError, "error with #{type.to_s.upcase} #{url} (#{err.message})"
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
- def generate_String(str) str.inspect end
115
- alias generate_Numeric generate_String
116
- alias generate_TrueClass generate_String
117
- alias generate_FalseClass generate_String
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
@@ -1,3 +1,3 @@
1
1
  module Hub
2
- Version = VERSION = '1.10.2'
2
+ Version = VERSION = '1.10.3'
3
3
  end
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" "May 2012" "DEFUNKT" "Git Manual"
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 &amp; 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'>May 2012</li>
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
- 'config --get-all remote.origin.url' => 'git://github.com/defunkt/hub.git',
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
- stub_config_value "remote.#{remote_name}.url", value, '--get-all'
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.2
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-07-24 00:00:00.000000000 Z
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.24
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