hub 1.11.0 → 1.11.1

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/Rakefile CHANGED
@@ -173,7 +173,7 @@ task :homebrew do
173
173
  sh "git checkout -q -B #{branch}"
174
174
  sh "git commit -m 'hub v#{Hub::VERSION}' -- #{formula_file}"
175
175
  sh "git push -u mislav #{branch}"
176
- sh "hub pull-request 'upgrade hub to v#{Hub::VERSION}'"
176
+ sh "hub pull-request -m 'upgrade hub to v#{Hub::VERSION}'"
177
177
 
178
178
  sh "git checkout -q master"
179
179
  end
data/lib/hub/context.rb CHANGED
@@ -18,7 +18,8 @@ module Hub
18
18
  @executable = executable || 'git'
19
19
  # caches output when shelling out to git
20
20
  read_proc ||= lambda { |cache, cmd|
21
- result = %x{#{command_to_string(cmd)} 2>#{NULL}}.chomp
21
+ str = command_to_string(cmd)
22
+ result = silence_stderr { %x{#{str}}.chomp }
22
23
  cache[cmd] = $?.success? && !result.empty? ? result : nil
23
24
  }
24
25
  @cache = Hash.new(&read_proc)
@@ -61,6 +62,14 @@ module Hub
61
62
  full_cmd = to_exec(cmd)
62
63
  full_cmd.respond_to?(:shelljoin) ? full_cmd.shelljoin : full_cmd.join(' ')
63
64
  end
65
+
66
+ def silence_stderr
67
+ oldio = STDERR.dup
68
+ STDERR.reopen(NULL)
69
+ yield
70
+ ensure
71
+ STDERR.reopen(oldio)
72
+ end
64
73
  end
65
74
 
66
75
  module GitReaderMethods
@@ -88,17 +97,19 @@ module Hub
88
97
  private :git_config, :git_command
89
98
 
90
99
  def local_repo(fatal = true)
91
- @local_repo ||= begin
92
- if is_repo?
93
- LocalRepo.new git_reader, current_dir
100
+ return nil if defined?(@local_repo) && @local_repo == false
101
+ @local_repo =
102
+ if git_dir = git_command('rev-parse -q --git-dir')
103
+ LocalRepo.new(git_reader, current_dir, git_dir)
94
104
  elsif fatal
95
105
  raise FatalError, "Not a git repository"
106
+ else
107
+ false
96
108
  end
97
- end
98
109
  end
99
110
 
100
111
  repo_methods = [
101
- :current_branch,
112
+ :current_branch, :git_dir,
102
113
  :remote_branch_and_project,
103
114
  :repo_owner, :repo_host,
104
115
  :remotes, :remotes_group, :origin_remote
@@ -116,7 +127,7 @@ module Hub
116
127
  end
117
128
  end
118
129
 
119
- class LocalRepo < Struct.new(:git_reader, :dir)
130
+ class LocalRepo < Struct.new(:git_reader, :dir, :git_dir)
120
131
  include GitReaderMethods
121
132
 
122
133
  def name
@@ -151,28 +162,49 @@ module Hub
151
162
  end
152
163
 
153
164
  def current_branch
154
- if branch = git_command('symbolic-ref -q HEAD')
155
- Branch.new self, branch
165
+ @current_branch ||= branch_at_ref('HEAD')
166
+ end
167
+
168
+ def branch_at_ref(*parts)
169
+ begin
170
+ head = file_read(*parts)
171
+ rescue Errno::ENOENT
172
+ return nil
173
+ else
174
+ Branch.new(self, head.rstrip) if head.sub!('ref: ', '')
156
175
  end
157
176
  end
158
177
 
178
+ def file_read(*parts)
179
+ File.read(File.join(git_dir, *parts))
180
+ end
181
+
182
+ def file_exist?(*parts)
183
+ File.exist?(File.join(git_dir, *parts))
184
+ end
185
+
159
186
  def master_branch
160
187
  if remote = origin_remote
161
- default_branch = git_command("rev-parse --symbolic-full-name #{remote}")
188
+ default_branch = branch_at_ref("refs/remotes/#{remote}/HEAD")
162
189
  end
163
- Branch.new(self, default_branch || 'refs/heads/master')
190
+ default_branch || Branch.new(self, 'refs/heads/master')
164
191
  end
165
192
 
166
193
  ORIGIN_NAMES = %w[ upstream github origin ]
167
194
 
168
195
  def remotes
169
196
  @remotes ||= begin
170
- # TODO: is there a plumbing command to get a list of remotes?
171
- list = git_command('remote').to_s.split("\n")
172
- list = ORIGIN_NAMES.inject([]) { |sorted, name|
173
- sorted << list.delete(name)
174
- }.compact.concat(list)
175
- list.map { |name| Remote.new self, name }
197
+ names = []
198
+ url_memo = Hash.new {|h,k| names << k; h[k]=[] }
199
+ git_command('remote -v').to_s.split("\n").map do |line|
200
+ next if line !~ /^(.+?)\t(.+) \(/
201
+ name, url = $1, $2
202
+ url_memo[name] << url
203
+ end
204
+ ((ORIGIN_NAMES + names) & names).map do |name|
205
+ urls = url_memo[name].uniq
206
+ Remote.new(self, name, urls)
207
+ end
176
208
  end
177
209
  end
178
210
 
@@ -194,12 +226,10 @@ module Hub
194
226
  remotes.find {|r| r.name == remote_name }
195
227
  end
196
228
 
197
- def known_hosts
198
- hosts = git_config('hub.host', :all).to_s.split("\n")
199
- hosts << default_host
200
- # support ssh.github.com
201
- # https://help.github.com/articles/using-ssh-over-the-https-port
202
- hosts << "ssh.#{default_host}"
229
+ def known_host?(host)
230
+ default = default_host
231
+ default == host || "ssh.#{default}" == host ||
232
+ git_config('hub.host', :all).to_s.split("\n").include?(host)
203
233
  end
204
234
 
205
235
  def self.default_host
@@ -220,7 +250,7 @@ module Hub
220
250
 
221
251
  class GithubProject < Struct.new(:local_repo, :owner, :name, :host)
222
252
  def self.from_url(url, local_repo)
223
- if local_repo.known_hosts.include? url.host
253
+ if local_repo.known_host?(url.host)
224
254
  _, owner, name = url.path.split('/', 4)
225
255
  GithubProject.new(local_repo, owner, name.sub(/\.git$/, ''), url.host)
226
256
  end
@@ -335,7 +365,7 @@ module Hub
335
365
  refs = local_repo.remotes_for_publish(owner_name).map { |remote|
336
366
  "refs/remotes/#{remote}/#{short}"
337
367
  }
338
- if branch = refs.detect {|ref| local_repo.git_command("rev-parse -q --verify #{ref}") }
368
+ if branch = refs.detect {|ref| local_repo.file_exist?(ref) }
339
369
  Branch.new(local_repo, branch)
340
370
  end
341
371
  end
@@ -351,7 +381,7 @@ module Hub
351
381
  end
352
382
  end
353
383
 
354
- class Remote < Struct.new(:local_repo, :name)
384
+ class Remote < Struct.new(:local_repo, :name, :raw_urls)
355
385
  alias to_s name
356
386
 
357
387
  def ==(other)
@@ -359,7 +389,7 @@ module Hub
359
389
  end
360
390
 
361
391
  def project
362
- urls.each_value { |url|
392
+ urls.each { |url|
363
393
  if valid = GithubProject.from_url(url, local_repo)
364
394
  return valid
365
395
  end
@@ -368,27 +398,29 @@ module Hub
368
398
  end
369
399
 
370
400
  def urls
371
- return @urls if defined? @urls
372
- @urls = {}
373
- local_repo.git_command('remote -v').to_s.split("\n").map do |line|
374
- next if line !~ /^(.+?)\t(.+) \((.+)\)$/
375
- remote, uri, type = $1, $2, $3
376
- next if remote != self.name
377
- if uri =~ %r{^[\w-]+://} or uri =~ %r{^([^/]+?):}
378
- uri = "ssh://#{$1}/#{$'}" if $1
401
+ @urls ||= raw_urls.map do |url|
402
+ with_normalized_url(url) do |normalized|
379
403
  begin
380
- @urls[type] = uri_parse(uri)
404
+ uri_parse(normalized)
381
405
  rescue URI::InvalidURIError
382
406
  end
383
407
  end
384
408
  end
385
- @urls
409
+ end
410
+
411
+ def with_normalized_url(url)
412
+ if url =~ %r{^[\w-]+://} || url =~ %r{^([^/]+?):}
413
+ url = "ssh://#{$1}/#{$'}" if $1
414
+ yield url
415
+ end
386
416
  end
387
417
 
388
418
  def uri_parse uri
389
419
  uri = URI.parse uri
390
- uri.host = local_repo.ssh_config.get_value(uri.host, 'hostname') { uri.host }
391
- uri.user = local_repo.ssh_config.get_value(uri.host, 'user') { uri.user }
420
+ if uri.host != local_repo.default_host
421
+ ssh = local_repo.ssh_config
422
+ uri.host = ssh.get_value(uri.host, :HostName) { uri.host }
423
+ end
392
424
  uri
393
425
  end
394
426
  end
@@ -447,12 +479,8 @@ module Hub
447
479
  PWD
448
480
  end
449
481
 
450
- def git_dir
451
- git_command 'rev-parse -q --git-dir'
452
- end
453
-
454
482
  def is_repo?
455
- !!git_dir
483
+ !!local_repo(false)
456
484
  end
457
485
 
458
486
  def git_editor
data/lib/hub/runner.rb CHANGED
@@ -58,6 +58,7 @@ module Hub
58
58
  if cmd.respond_to?(:call) then cmd.call
59
59
  elsif i == commands.length - 1
60
60
  # last command in chain
61
+ STDOUT.flush; STDERR.flush
61
62
  exec(*cmd)
62
63
  else
63
64
  exit($?.exitstatus) unless system(*cmd)
@@ -1,8 +1,9 @@
1
1
  module Hub
2
- # Reads ssh configuration files and records each setting under its host
3
- # pattern so it can be looked up by hostname.
2
+ # Reads ssh_config(5) files and records "Host" to "HostName" mappings to
3
+ # provide resolving of ssh aliases.
4
4
  class SshConfig
5
5
  CONFIG_FILES = %w(~/.ssh/config /etc/ssh_config /etc/ssh/ssh_config)
6
+ CONFIG_RE = /^\s*(Host|HostName)\s+/
6
7
 
7
8
  def initialize files = nil
8
9
  @settings = Hash.new {|h,k| h[k] = {} }
@@ -15,67 +16,21 @@ module Hub
15
16
  # Public: Get a setting as it would apply to a specific hostname.
16
17
  #
17
18
  # Yields if not found.
18
- def get_value hostname, key
19
- key = key.to_s.downcase
20
- @settings.each do |pattern, settings|
21
- if pattern.match? hostname and found = settings[key]
22
- return found
23
- end
24
- end
25
- yield
26
- end
27
-
28
- class HostPattern
29
- def initialize pattern
30
- @pattern = pattern.to_s.downcase
31
- end
32
-
33
- def to_s() @pattern end
34
- def ==(other) other.to_s == self.to_s end
35
-
36
- def matcher
37
- @matcher ||=
38
- if '*' == @pattern
39
- Proc.new { true }
40
- elsif @pattern !~ /[?*]/
41
- lambda { |hostname| hostname.to_s.downcase == @pattern }
42
- else
43
- re = self.class.pattern_to_regexp @pattern
44
- lambda { |hostname| re =~ hostname }
45
- end
46
- end
47
-
48
- def match? hostname
49
- matcher.call hostname
50
- end
51
-
52
- def self.pattern_to_regexp pattern
53
- escaped = Regexp.escape(pattern)
54
- escaped.gsub!('\*', '.*')
55
- escaped.gsub!('\?', '.')
56
- /^#{escaped}$/i
57
- end
19
+ def get_value(host, key, &fallback)
20
+ host = host.to_s.downcase
21
+ @settings[host].fetch(key.to_sym, &fallback)
58
22
  end
59
23
 
60
24
  def parse_file file
61
- host_patterns = [HostPattern.new('*')]
25
+ host_patterns = %w[*]
62
26
 
63
27
  IO.foreach(file) do |line|
64
- case line
65
- when /^\s*(#|$)/ then next
66
- when /^\s*(\S+)\s*=/
67
- key, value = $1, $'
68
- else
69
- key, value = line.strip.split(/\s+/, 2)
70
- end
71
-
72
- next if value.nil?
73
- key.downcase!
74
- value = $1 if value =~ /^"(.*)"$/
75
- value.chomp!
28
+ next unless line =~ CONFIG_RE
29
+ key, value = $1.to_sym, $'.chomp
30
+ value.gsub!(/^"|"$/, '')
76
31
 
77
- if 'host' == key
78
- host_patterns = value.split(/\s+/).map {|p| HostPattern.new p }
32
+ if :Host == key
33
+ host_patterns = value.downcase.split(/\s+/)
79
34
  else
80
35
  record_setting key, value, host_patterns
81
36
  end
data/lib/hub/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Hub
2
- Version = VERSION = '1.11.0'
2
+ Version = VERSION = '1.11.1'
3
3
  end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: hub
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 1.11.0
5
+ version: 1.11.1
6
6
  platform: ruby
7
7
  authors:
8
8
  - Chris Wanstrath
@@ -10,40 +10,8 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2013-12-22 00:00:00.000000000 Z
14
- dependencies:
15
- - !ruby/object:Gem::Dependency
16
- version_requirements: !ruby/object:Gem::Requirement
17
- requirements:
18
- - - ! '>='
19
- - !ruby/object:Gem::Version
20
- version: '0'
21
- none: false
22
- name: rake
23
- type: :development
24
- prerelease: false
25
- requirement: !ruby/object:Gem::Requirement
26
- requirements:
27
- - - ! '>='
28
- - !ruby/object:Gem::Version
29
- version: '0'
30
- none: false
31
- - !ruby/object:Gem::Dependency
32
- version_requirements: !ruby/object:Gem::Requirement
33
- requirements:
34
- - - ! '>='
35
- - !ruby/object:Gem::Version
36
- version: '0'
37
- none: false
38
- name: webmock
39
- type: :development
40
- prerelease: false
41
- requirement: !ruby/object:Gem::Requirement
42
- requirements:
43
- - - ! '>='
44
- - !ruby/object:Gem::Version
45
- version: '0'
46
- none: false
13
+ date: 2013-12-26 00:00:00.000000000 Z
14
+ dependencies: []
47
15
  description: ! " `hub` is a command line utility which adds GitHub knowledge to `git`.\n\n
48
16
  \ It can used on its own or as a `git` wrapper.\n\n Normal:\n\n $ hub clone
49
17
  rtomayko/tilt\n\n Expands to:\n $ git clone git://github.com/rtomayko/tilt.git\n\n
@@ -69,23 +37,10 @@ files:
69
37
  - lib/hub/standalone.rb
70
38
  - lib/hub/version.rb
71
39
  - lib/hub.rb
72
- - bin/bench
73
40
  - bin/hub
74
41
  - man/hub.1
75
42
  - man/hub.1.html
76
43
  - man/hub.1.ronn
77
- - script/cached-bundle
78
- - script/s3-put
79
- - script/test
80
- - script/test_each
81
- - test/context_test.rb
82
- - test/deps.rip
83
- - test/fakebin/git
84
- - test/fakebin/open
85
- - test/github_api_test.rb
86
- - test/helper.rb
87
- - test/hub_test.rb
88
- - test/standalone_test.rb
89
44
  homepage: http://hub.github.com/
90
45
  licenses:
91
46
  - MIT
@@ -99,17 +54,17 @@ rdoc_options: []
99
54
  require_paths:
100
55
  - lib
101
56
  required_ruby_version: !ruby/object:Gem::Requirement
57
+ none: false
102
58
  requirements:
103
59
  - - ! '>='
104
60
  - !ruby/object:Gem::Version
105
61
  version: '0'
106
- none: false
107
62
  required_rubygems_version: !ruby/object:Gem::Requirement
63
+ none: false
108
64
  requirements:
109
65
  - - ! '>='
110
66
  - !ruby/object:Gem::Version
111
67
  version: '0'
112
- none: false
113
68
  requirements: []
114
69
  rubyforge_project:
115
70
  rubygems_version: 1.8.23
data/bin/bench DELETED
@@ -1,37 +0,0 @@
1
- #!/bin/bash
2
- set -e
3
-
4
- iterations=20
5
-
6
- ruby="$(rbenv which ruby)"
7
- ruby_args="--disable-gems"
8
-
9
- unset RUBYLIB
10
- unset RUBYOPT
11
-
12
- export TIMEFORMAT='%3R'
13
-
14
- time_ruby() {
15
- (time "$ruby" $ruby_args "$@" >/dev/null) 2>&1
16
- }
17
-
18
- time_plain() {
19
- (time "$@" >/dev/null) 2>&1
20
- }
21
-
22
- measure() {
23
- local count="$iterations"
24
- echo "$@"
25
- { while [ "$count" -gt 0 ]; do
26
- # time_ruby "$@"
27
- time_plain "$@"
28
- count=$((count - 1))
29
- done
30
- } | stdev
31
- }
32
-
33
- /usr/bin/ruby -v
34
- measure tmp/hub-slow version
35
- measure tmp/hub-slow browse -u
36
- measure tmp/hub-fast version
37
- measure tmp/hub-fast browse -u