hub 1.6.1 → 1.7.0
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.
Potentially problematic release.
This version of hub might be problematic. Click here for more details.
- data/README.md +94 -60
- data/Rakefile +74 -38
- data/lib/hub/args.rb +16 -3
- data/lib/hub/commands.rb +340 -101
- data/lib/hub/context.rb +270 -112
- data/lib/hub/runner.rb +4 -2
- data/lib/hub/standalone.rb +13 -7
- data/lib/hub/version.rb +1 -1
- data/man/hub.1 +162 -80
- data/man/hub.1.html +163 -96
- data/man/hub.1.ronn +84 -167
- data/test/alias_test.rb +0 -1
- data/test/helper.rb +8 -8
- data/test/hub_test.rb +395 -71
- data/test/standalone_test.rb +0 -1
- metadata +8 -6
data/test/alias_test.rb
CHANGED
data/test/helper.rb
CHANGED
@@ -1,15 +1,8 @@
|
|
1
1
|
require 'test/unit'
|
2
|
-
|
3
|
-
begin
|
4
|
-
require 'redgreen'
|
5
|
-
rescue LoadError
|
6
|
-
end
|
7
|
-
|
8
|
-
$LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
|
9
2
|
require 'hub'
|
10
3
|
require 'hub/standalone'
|
11
4
|
|
12
|
-
# We're
|
5
|
+
# We're checking for `open` in our tests
|
13
6
|
ENV['BROWSER'] = 'open'
|
14
7
|
|
15
8
|
# Setup path with fake executables in case a test hits them
|
@@ -108,4 +101,11 @@ class Test::Unit::TestCase
|
|
108
101
|
assert !haystack.include?(needle),
|
109
102
|
"didn't expect #{needle.inspect} in #{haystack.inspect}"
|
110
103
|
end
|
104
|
+
|
105
|
+
# Version of assert_equal tailored for big output
|
106
|
+
def assert_output(expected, command)
|
107
|
+
output = hub(command) { ENV['GIT'] = 'echo' }
|
108
|
+
assert expected == output,
|
109
|
+
"expected:\n#{expected}\ngot:\n#{output}"
|
110
|
+
end
|
111
111
|
end
|
data/test/hub_test.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
|
-
$LOAD_PATH.unshift File.dirname(__FILE__)
|
2
1
|
require 'helper'
|
3
2
|
require 'webmock/test_unit'
|
4
3
|
require 'rbconfig'
|
4
|
+
require 'yaml'
|
5
|
+
require 'forwardable'
|
6
|
+
require 'json'
|
5
7
|
|
6
8
|
WebMock::BodyPattern.class_eval do
|
7
9
|
undef normalize_hash
|
@@ -10,6 +12,8 @@ WebMock::BodyPattern.class_eval do
|
|
10
12
|
end
|
11
13
|
|
12
14
|
class HubTest < Test::Unit::TestCase
|
15
|
+
extend Forwardable
|
16
|
+
|
13
17
|
if defined? WebMock::API
|
14
18
|
include WebMock::API
|
15
19
|
else
|
@@ -25,30 +29,35 @@ class HubTest < Test::Unit::TestCase
|
|
25
29
|
end
|
26
30
|
end
|
27
31
|
|
32
|
+
attr_reader :git_reader
|
33
|
+
include Hub::Context::GitReaderMethods
|
34
|
+
def_delegators :git_reader, :stub_config_value, :stub_command_output
|
35
|
+
|
28
36
|
def setup
|
37
|
+
super
|
29
38
|
COMMANDS.replace %w[open groff]
|
30
|
-
Hub::Context::
|
31
|
-
Hub::Context::REMOTES.clear
|
39
|
+
Hub::Context::PWD.replace '/path/to/hub'
|
32
40
|
|
33
|
-
Hub::Context::
|
34
|
-
|
35
|
-
|
36
|
-
unless k.index('config alias.') == 0
|
37
|
-
raise ArgumentError, "`git #{k}` not stubbed"
|
41
|
+
@git_reader = Hub::Context::GitReader.new 'git' do |cache, cmd|
|
42
|
+
unless cmd.index('config --get alias.') == 0
|
43
|
+
raise ArgumentError, "`git #{cmd}` not stubbed"
|
38
44
|
end
|
39
|
-
|
45
|
+
end
|
46
|
+
|
47
|
+
Hub::Commands.instance_variable_set :@git_reader, @git_reader
|
48
|
+
Hub::Commands.instance_variable_set :@local_repo, nil
|
49
|
+
|
50
|
+
@git_reader.stub! \
|
40
51
|
'remote' => "mislav\norigin",
|
41
52
|
'symbolic-ref -q HEAD' => 'refs/heads/master',
|
42
|
-
'config github.user' => 'tpw',
|
43
|
-
'config github.token' => 'abc123',
|
53
|
+
'config --get github.user' => 'tpw',
|
54
|
+
'config --get github.token' => 'abc123',
|
44
55
|
'config --get-all remote.origin.url' => 'git://github.com/defunkt/hub.git',
|
45
56
|
'config --get-all remote.mislav.url' => 'git://github.com/mislav/hub.git',
|
46
|
-
'
|
47
|
-
'config
|
48
|
-
'config --
|
49
|
-
'
|
50
|
-
)
|
51
|
-
super
|
57
|
+
'rev-parse --symbolic-full-name master@{upstream}' => 'refs/remotes/origin/master',
|
58
|
+
'config --get --bool hub.http-clone' => 'false',
|
59
|
+
'config --get hub.protocol' => nil,
|
60
|
+
'rev-parse -q --git-dir' => '.git'
|
52
61
|
end
|
53
62
|
|
54
63
|
def test_private_clone
|
@@ -57,6 +66,19 @@ class HubTest < Test::Unit::TestCase
|
|
57
66
|
assert_command input, command
|
58
67
|
end
|
59
68
|
|
69
|
+
def test_private_clone_noop
|
70
|
+
input = "--noop clone -p rtomayko/ronn"
|
71
|
+
command = "git clone git@github.com:rtomayko/ronn.git\n"
|
72
|
+
assert_output command, hub(input)
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_https_clone
|
76
|
+
stub_https_is_preferred
|
77
|
+
input = "clone rtomayko/ronn"
|
78
|
+
command = "git clone https://github.com/rtomayko/ronn.git"
|
79
|
+
assert_command input, command
|
80
|
+
end
|
81
|
+
|
60
82
|
def test_public_clone
|
61
83
|
input = "clone rtomayko/ronn"
|
62
84
|
command = "git clone git://github.com/rtomayko/ronn.git"
|
@@ -69,15 +91,15 @@ class HubTest < Test::Unit::TestCase
|
|
69
91
|
assert_command input, command
|
70
92
|
end
|
71
93
|
|
72
|
-
def
|
94
|
+
def test_your_clone_is_always_private
|
73
95
|
input = "clone resque"
|
74
|
-
command = "git clone git
|
96
|
+
command = "git clone git@github.com:tpw/resque.git"
|
75
97
|
assert_command input, command
|
76
98
|
end
|
77
99
|
|
78
100
|
def test_clone_with_arguments
|
79
101
|
input = "clone --bare -o master resque"
|
80
|
-
command = "git clone --bare -o master git
|
102
|
+
command = "git clone --bare -o master git@github.com:tpw/resque.git"
|
81
103
|
assert_command input, command
|
82
104
|
end
|
83
105
|
|
@@ -90,7 +112,7 @@ class HubTest < Test::Unit::TestCase
|
|
90
112
|
stub_github_user(nil)
|
91
113
|
end
|
92
114
|
|
93
|
-
assert_equal "** No GitHub user set. See http://help.github.com/
|
115
|
+
assert_equal "** No GitHub user set. See http://help.github.com/set-your-user-name-email-and-github-token/\n", out
|
94
116
|
end
|
95
117
|
|
96
118
|
def test_your_public_clone_fails_without_config
|
@@ -98,7 +120,7 @@ class HubTest < Test::Unit::TestCase
|
|
98
120
|
stub_github_user(nil)
|
99
121
|
end
|
100
122
|
|
101
|
-
assert_equal "** No GitHub user set. See http://help.github.com/
|
123
|
+
assert_equal "** No GitHub user set. See http://help.github.com/set-your-user-name-email-and-github-token/\n", out
|
102
124
|
end
|
103
125
|
|
104
126
|
def test_private_clone_left_alone
|
@@ -117,6 +139,10 @@ class HubTest < Test::Unit::TestCase
|
|
117
139
|
assert_forwarded "clone ./test"
|
118
140
|
end
|
119
141
|
|
142
|
+
def test_clone_with_host_alias
|
143
|
+
assert_forwarded "clone server:git/repo.git"
|
144
|
+
end
|
145
|
+
|
120
146
|
def test_alias_expand
|
121
147
|
stub_alias 'c', 'clone --bare'
|
122
148
|
input = "c rtomayko/ronn"
|
@@ -162,6 +188,10 @@ class HubTest < Test::Unit::TestCase
|
|
162
188
|
assert_forwarded "remote add origin /path"
|
163
189
|
end
|
164
190
|
|
191
|
+
def test_remote_with_host_alias
|
192
|
+
assert_forwarded "remote add origin server:/git/repo.git"
|
193
|
+
end
|
194
|
+
|
165
195
|
def test_private_remote_origin_as_normal
|
166
196
|
assert_forwarded "remote add origin git@github.com:defunkt/resque.git"
|
167
197
|
end
|
@@ -196,6 +226,13 @@ class HubTest < Test::Unit::TestCase
|
|
196
226
|
assert_command input, command
|
197
227
|
end
|
198
228
|
|
229
|
+
def test_https_protocol_remote
|
230
|
+
stub_https_is_preferred
|
231
|
+
input = "remote add rtomayko"
|
232
|
+
command = "git remote add rtomayko https://github.com/rtomayko/hub.git"
|
233
|
+
assert_command input, command
|
234
|
+
end
|
235
|
+
|
199
236
|
def test_public_remote
|
200
237
|
input = "remote add rtomayko"
|
201
238
|
command = "git remote add rtomayko git://github.com/rtomayko/hub.git"
|
@@ -334,7 +371,7 @@ class HubTest < Test::Unit::TestCase
|
|
334
371
|
end
|
335
372
|
|
336
373
|
def test_cherry_pick_github_user_notation
|
337
|
-
assert_commands "git fetch mislav", "git cherry-pick
|
374
|
+
assert_commands "git fetch mislav", "git cherry-pick 368af20", "cherry-pick mislav@368af20"
|
338
375
|
end
|
339
376
|
|
340
377
|
def test_cherry_pick_github_user_repo_notation
|
@@ -387,6 +424,41 @@ class HubTest < Test::Unit::TestCase
|
|
387
424
|
end
|
388
425
|
end
|
389
426
|
|
427
|
+
def test_apply_untouched
|
428
|
+
assert_forwarded "apply some.patch"
|
429
|
+
end
|
430
|
+
|
431
|
+
def test_apply_pull_request
|
432
|
+
with_tmpdir('/tmp/') do
|
433
|
+
assert_commands "curl -#LA 'hub #{Hub::Version}' https://github.com/defunkt/hub/pull/55.patch -o /tmp/55.patch",
|
434
|
+
"git apply /tmp/55.patch -p2",
|
435
|
+
"apply https://github.com/defunkt/hub/pull/55 -p2"
|
436
|
+
|
437
|
+
cmd = Hub("apply https://github.com/defunkt/hub/pull/55/files").command
|
438
|
+
assert_includes '/pull/55.patch', cmd
|
439
|
+
end
|
440
|
+
end
|
441
|
+
|
442
|
+
def test_apply_commit_url
|
443
|
+
with_tmpdir('/tmp/') do
|
444
|
+
url = 'https://github.com/davidbalbert/hub/commit/fdb9921'
|
445
|
+
|
446
|
+
assert_commands "curl -#LA 'hub #{Hub::Version}' #{url}.patch -o /tmp/fdb9921.patch",
|
447
|
+
"git apply /tmp/fdb9921.patch -p2",
|
448
|
+
"apply #{url} -p2"
|
449
|
+
end
|
450
|
+
end
|
451
|
+
|
452
|
+
def test_apply_gist
|
453
|
+
with_tmpdir('/tmp/') do
|
454
|
+
url = 'https://gist.github.com/8da7fb575debd88c54cf'
|
455
|
+
|
456
|
+
assert_commands "curl -#LA 'hub #{Hub::Version}' #{url}.txt -o /tmp/gist-8da7fb575debd88c54cf.txt",
|
457
|
+
"git apply /tmp/gist-8da7fb575debd88c54cf.txt -p2",
|
458
|
+
"apply #{url} -p2"
|
459
|
+
end
|
460
|
+
end
|
461
|
+
|
390
462
|
def test_init
|
391
463
|
assert_commands "git init", "git remote add origin git@github.com:tpw/hub.git", "init -g"
|
392
464
|
end
|
@@ -396,7 +468,7 @@ class HubTest < Test::Unit::TestCase
|
|
396
468
|
stub_github_user(nil)
|
397
469
|
end
|
398
470
|
|
399
|
-
assert_equal "** No GitHub user set. See http://help.github.com/
|
471
|
+
assert_equal "** No GitHub user set. See http://help.github.com/set-your-user-name-email-and-github-token/\n", out
|
400
472
|
end
|
401
473
|
|
402
474
|
def test_push_untouched
|
@@ -424,21 +496,60 @@ class HubTest < Test::Unit::TestCase
|
|
424
496
|
def test_create
|
425
497
|
stub_no_remotes
|
426
498
|
stub_nonexisting_fork('tpw')
|
427
|
-
stub_request(:post, "github.com/api/v2/yaml/repos/create").
|
428
|
-
with(:body => { '
|
499
|
+
stub_request(:post, "https://#{auth}github.com/api/v2/yaml/repos/create").
|
500
|
+
with(:body => { 'name' => 'hub' })
|
429
501
|
|
430
502
|
expected = "remote add -f origin git@github.com:tpw/hub.git\n"
|
431
503
|
expected << "created repository: tpw/hub\n"
|
432
504
|
assert_equal expected, hub("create") { ENV['GIT'] = 'echo' }
|
433
505
|
end
|
434
506
|
|
507
|
+
def test_create_custom_name
|
508
|
+
stub_no_remotes
|
509
|
+
stub_nonexisting_fork('tpw', 'hubbub')
|
510
|
+
stub_request(:post, "https://#{auth}github.com/api/v2/yaml/repos/create").
|
511
|
+
with(:body => { 'name' => 'hubbub' })
|
512
|
+
|
513
|
+
expected = "remote add -f origin git@github.com:tpw/hubbub.git\n"
|
514
|
+
expected << "created repository: tpw/hubbub\n"
|
515
|
+
assert_equal expected, hub("create hubbub") { ENV['GIT'] = 'echo' }
|
516
|
+
end
|
517
|
+
|
518
|
+
def test_create_in_organization
|
519
|
+
stub_no_remotes
|
520
|
+
stub_nonexisting_fork('acme', 'hubbub')
|
521
|
+
stub_request(:post, "https://#{auth}github.com/api/v2/yaml/repos/create").
|
522
|
+
with(:body => { 'name' => 'acme/hubbub' })
|
523
|
+
|
524
|
+
expected = "remote add -f origin git@github.com:acme/hubbub.git\n"
|
525
|
+
expected << "created repository: acme/hubbub\n"
|
526
|
+
assert_equal expected, hub("create acme/hubbub") { ENV['GIT'] = 'echo' }
|
527
|
+
end
|
528
|
+
|
529
|
+
def test_create_no_openssl
|
530
|
+
stub_no_remotes
|
531
|
+
stub_nonexisting_fork('tpw')
|
532
|
+
stub_request(:post, "http://#{auth}github.com/api/v2/yaml/repos/create").
|
533
|
+
with(:body => { 'name' => 'hub' })
|
534
|
+
|
535
|
+
expected = "remote add -f origin git@github.com:tpw/hub.git\n"
|
536
|
+
expected << "created repository: tpw/hub\n"
|
537
|
+
|
538
|
+
assert_equal expected, hub("create") {
|
539
|
+
ENV['GIT'] = 'echo'
|
540
|
+
require 'net/https'
|
541
|
+
Object.send :remove_const, :OpenSSL
|
542
|
+
}
|
543
|
+
end
|
544
|
+
|
435
545
|
def test_create_failed
|
436
546
|
stub_no_remotes
|
437
547
|
stub_nonexisting_fork('tpw')
|
438
|
-
stub_request(:post, "github.com/api/v2/yaml/repos/create").
|
548
|
+
stub_request(:post, "https://#{auth}github.com/api/v2/yaml/repos/create").
|
439
549
|
to_return(:status => [401, "Your token is fail"])
|
440
550
|
|
441
|
-
expected = "
|
551
|
+
expected = "Error creating repository: Your token is fail (HTTP 401)\n"
|
552
|
+
expected << "Check your token configuration (`git config github.token`)\n"
|
442
553
|
assert_equal expected, hub("create") { ENV['GIT'] = 'echo' }
|
443
554
|
end
|
444
555
|
|
@@ -451,8 +562,8 @@ class HubTest < Test::Unit::TestCase
|
|
451
562
|
ENV['GITHUB_USER'] = 'mojombo'
|
452
563
|
ENV['GITHUB_TOKEN'] = '123abc'
|
453
564
|
|
454
|
-
stub_request(:post, "github.com/api/v2/yaml/repos/create").
|
455
|
-
with(:body => { '
|
565
|
+
stub_request(:post, "https://#{auth('mojombo', '123abc')}github.com/api/v2/yaml/repos/create").
|
566
|
+
with(:body => { 'name' => 'hub' })
|
456
567
|
|
457
568
|
expected = "remote add -f origin git@github.com:mojombo/hub.git\n"
|
458
569
|
expected << "created repository: mojombo/hub\n"
|
@@ -466,8 +577,8 @@ class HubTest < Test::Unit::TestCase
|
|
466
577
|
def test_create_private_repository
|
467
578
|
stub_no_remotes
|
468
579
|
stub_nonexisting_fork('tpw')
|
469
|
-
stub_request(:post, "github.com/api/v2/yaml/repos/create").
|
470
|
-
with(:body => { '
|
580
|
+
stub_request(:post, "https://#{auth}github.com/api/v2/yaml/repos/create").
|
581
|
+
with(:body => { 'name' => 'hub', 'public' => '0' })
|
471
582
|
|
472
583
|
expected = "remote add -f origin git@github.com:tpw/hub.git\n"
|
473
584
|
expected << "created repository: tpw/hub\n"
|
@@ -477,9 +588,8 @@ class HubTest < Test::Unit::TestCase
|
|
477
588
|
def test_create_with_description_and_homepage
|
478
589
|
stub_no_remotes
|
479
590
|
stub_nonexisting_fork('tpw')
|
480
|
-
stub_request(:post, "github.com/api/v2/yaml/repos/create").with(:body => {
|
481
|
-
'
|
482
|
-
'description' => 'toyproject', 'homepage' => 'http://example.com'
|
591
|
+
stub_request(:post, "https://#{auth}github.com/api/v2/yaml/repos/create").with(:body => {
|
592
|
+
'name' => 'hub', 'description' => 'toyproject', 'homepage' => 'http://example.com'
|
483
593
|
})
|
484
594
|
|
485
595
|
expected = "remote add -f origin git@github.com:tpw/hub.git\n"
|
@@ -487,6 +597,11 @@ class HubTest < Test::Unit::TestCase
|
|
487
597
|
assert_equal expected, hub("create -d toyproject -h http://example.com") { ENV['GIT'] = 'echo' }
|
488
598
|
end
|
489
599
|
|
600
|
+
def test_create_with_invalid_arguments
|
601
|
+
assert_equal "invalid argument: -a\n", hub("create -a blah") { ENV['GIT'] = 'echo' }
|
602
|
+
assert_equal "invalid argument: bleh\n", hub("create blah bleh") { ENV['GIT'] = 'echo' }
|
603
|
+
end
|
604
|
+
|
490
605
|
def test_create_with_existing_repository
|
491
606
|
stub_no_remotes
|
492
607
|
stub_existing_fork('tpw')
|
@@ -497,12 +612,23 @@ class HubTest < Test::Unit::TestCase
|
|
497
612
|
assert_equal expected, hub("create") { ENV['GIT'] = 'echo' }
|
498
613
|
end
|
499
614
|
|
615
|
+
def test_create_https_protocol
|
616
|
+
stub_no_remotes
|
617
|
+
stub_existing_fork('tpw')
|
618
|
+
stub_https_is_preferred
|
619
|
+
|
620
|
+
expected = "tpw/hub already exists on GitHub\n"
|
621
|
+
expected << "remote add -f origin https://github.com/tpw/hub.git\n"
|
622
|
+
expected << "set remote origin: tpw/hub\n"
|
623
|
+
assert_equal expected, hub("create") { ENV['GIT'] = 'echo' }
|
624
|
+
end
|
625
|
+
|
500
626
|
def test_create_no_user
|
501
627
|
stub_no_remotes
|
502
628
|
out = hub("create") do
|
503
629
|
stub_github_token(nil)
|
504
630
|
end
|
505
|
-
assert_equal "** No GitHub token set. See http://help.github.com/
|
631
|
+
assert_equal "** No GitHub token set. See http://help.github.com/set-your-user-name-email-and-github-token/\n", out
|
506
632
|
end
|
507
633
|
|
508
634
|
def test_create_outside_git_repo
|
@@ -512,8 +638,8 @@ class HubTest < Test::Unit::TestCase
|
|
512
638
|
|
513
639
|
def test_create_origin_already_exists
|
514
640
|
stub_nonexisting_fork('tpw')
|
515
|
-
stub_request(:post, "github.com/api/v2/yaml/repos/create").
|
516
|
-
with(:body => { '
|
641
|
+
stub_request(:post, "https://#{auth}github.com/api/v2/yaml/repos/create").
|
642
|
+
with(:body => { 'name' => 'hub' })
|
517
643
|
|
518
644
|
expected = "remote -v\ncreated repository: tpw/hub\n"
|
519
645
|
assert_equal expected, hub("create") { ENV['GIT'] = 'echo' }
|
@@ -521,8 +647,7 @@ class HubTest < Test::Unit::TestCase
|
|
521
647
|
|
522
648
|
def test_fork
|
523
649
|
stub_nonexisting_fork('tpw')
|
524
|
-
stub_request(:post, "github.com/api/v2/yaml/repos/fork/defunkt/hub")
|
525
|
-
with(:body => { 'login'=>'tpw', 'token'=>'abc123' })
|
650
|
+
stub_request(:post, "https://#{auth}github.com/api/v2/yaml/repos/fork/defunkt/hub")
|
526
651
|
|
527
652
|
expected = "remote add -f tpw git@github.com:tpw/hub.git\n"
|
528
653
|
expected << "new remote: tpw\n"
|
@@ -531,16 +656,16 @@ class HubTest < Test::Unit::TestCase
|
|
531
656
|
|
532
657
|
def test_fork_failed
|
533
658
|
stub_nonexisting_fork('tpw')
|
534
|
-
stub_request(:post, "github.com/api/v2/yaml/repos/fork/defunkt/hub").
|
659
|
+
stub_request(:post, "https://#{auth}github.com/api/v2/yaml/repos/fork/defunkt/hub").
|
535
660
|
to_return(:status => [500, "Your fork is fail"])
|
536
661
|
|
537
|
-
expected = "
|
662
|
+
expected = "Error creating fork: Your fork is fail (HTTP 500)\n"
|
538
663
|
assert_equal expected, hub("fork") { ENV['GIT'] = 'echo' }
|
539
664
|
end
|
540
665
|
|
541
666
|
def test_fork_no_remote
|
542
667
|
stub_nonexisting_fork('tpw')
|
543
|
-
stub_request(:post, "github.com/api/v2/yaml/repos/fork/defunkt/hub")
|
668
|
+
stub_request(:post, "https://#{auth}github.com/api/v2/yaml/repos/fork/defunkt/hub")
|
544
669
|
|
545
670
|
assert_equal "", hub("fork --no-remote") { ENV['GIT'] = 'echo' }
|
546
671
|
end
|
@@ -554,6 +679,161 @@ class HubTest < Test::Unit::TestCase
|
|
554
679
|
assert_equal expected, hub("fork") { ENV['GIT'] = 'echo' }
|
555
680
|
end
|
556
681
|
|
682
|
+
def test_fork_https_protocol
|
683
|
+
stub_existing_fork('tpw')
|
684
|
+
stub_https_is_preferred
|
685
|
+
|
686
|
+
expected = "tpw/hub already exists on GitHub\n"
|
687
|
+
expected << "remote add -f tpw https://github.com/tpw/hub.git\n"
|
688
|
+
expected << "new remote: tpw\n"
|
689
|
+
assert_equal expected, hub("fork") { ENV['GIT'] = 'echo' }
|
690
|
+
end
|
691
|
+
|
692
|
+
def test_pullrequest
|
693
|
+
expected = "Aborted: head branch is the same as base (\"master\")\n" <<
|
694
|
+
"(use `-h <branch>` to specify an explicit pull request head)\n"
|
695
|
+
assert_output expected, "pull-request hereyougo"
|
696
|
+
end
|
697
|
+
|
698
|
+
def test_pullrequest_with_unpushed_commits
|
699
|
+
stub_tracking('master', 'mislav', 'master')
|
700
|
+
stub_command_output "rev-list --cherry mislav/master...", "+abcd1234\n+bcde2345"
|
701
|
+
|
702
|
+
expected = "Aborted: 2 commits are not yet pushed to mislav/master\n" <<
|
703
|
+
"(use `-f` to force submit a pull request anyway)\n"
|
704
|
+
assert_output expected, "pull-request hereyougo"
|
705
|
+
end
|
706
|
+
|
707
|
+
def test_pullrequest_from_branch
|
708
|
+
stub_branch('refs/heads/feature')
|
709
|
+
stub_tracking_nothing('feature')
|
710
|
+
|
711
|
+
stub_request(:post, "https://#{auth}github.com/api/v2/yaml/pulls/defunkt/hub").
|
712
|
+
with(:body => { 'pull' => {'base' => "master", 'head' => "tpw:feature", 'title' => "hereyougo"} }).
|
713
|
+
to_return(:body => mock_pullreq_response(1))
|
714
|
+
|
715
|
+
expected = "https://github.com/defunkt/hub/pull/1\n"
|
716
|
+
assert_output expected, "pull-request hereyougo -f"
|
717
|
+
end
|
718
|
+
|
719
|
+
def test_pullrequest_from_tracking_branch
|
720
|
+
stub_branch('refs/heads/feature')
|
721
|
+
stub_tracking('feature', 'mislav', 'yay-feature')
|
722
|
+
stub_command_output "rev-list --cherry mislav/master...", nil
|
723
|
+
|
724
|
+
stub_request(:post, "https://#{auth}github.com/api/v2/yaml/pulls/defunkt/hub").
|
725
|
+
with(:body => { 'pull' => {'base' => "master", 'head' => "mislav:yay-feature", 'title' => "hereyougo"} }).
|
726
|
+
to_return(:body => mock_pullreq_response(1))
|
727
|
+
|
728
|
+
expected = "https://github.com/defunkt/hub/pull/1\n"
|
729
|
+
assert_output expected, "pull-request hereyougo -f"
|
730
|
+
end
|
731
|
+
|
732
|
+
def test_pullrequest_explicit_head
|
733
|
+
stub_request(:post, "https://#{auth}github.com/api/v2/yaml/pulls/defunkt/hub").
|
734
|
+
with(:body => { 'pull' => {'base' => "master", 'head' => "tpw:yay-feature", 'title' => "hereyougo"} }).
|
735
|
+
to_return(:body => mock_pullreq_response(1))
|
736
|
+
|
737
|
+
expected = "https://github.com/defunkt/hub/pull/1\n"
|
738
|
+
assert_output expected, "pull-request hereyougo -h yay-feature -f"
|
739
|
+
end
|
740
|
+
|
741
|
+
def test_pullrequest_explicit_head_with_owner
|
742
|
+
stub_request(:post, "https://#{auth}github.com/api/v2/yaml/pulls/defunkt/hub").
|
743
|
+
with(:body => { 'pull' => {'base' => "master", 'head' => "mojombo:feature", 'title' => "hereyougo"} }).
|
744
|
+
to_return(:body => mock_pullreq_response(1))
|
745
|
+
|
746
|
+
expected = "https://github.com/defunkt/hub/pull/1\n"
|
747
|
+
assert_output expected, "pull-request hereyougo -h mojombo:feature -f"
|
748
|
+
end
|
749
|
+
|
750
|
+
def test_pullrequest_explicit_base
|
751
|
+
stub_request(:post, "https://#{auth}github.com/api/v2/yaml/pulls/defunkt/hub").
|
752
|
+
with(:body => { 'pull' => {'base' => "feature", 'head' => "defunkt:master", 'title' => "hereyougo"} }).
|
753
|
+
to_return(:body => mock_pullreq_response(1))
|
754
|
+
|
755
|
+
expected = "https://github.com/defunkt/hub/pull/1\n"
|
756
|
+
assert_output expected, "pull-request hereyougo -b feature -f"
|
757
|
+
end
|
758
|
+
|
759
|
+
def test_pullrequest_explicit_base_with_owner
|
760
|
+
stub_request(:post, "https://#{auth}github.com/api/v2/yaml/pulls/mojombo/hub").
|
761
|
+
with(:body => { 'pull' => {'base' => "feature", 'head' => "defunkt:master", 'title' => "hereyougo"} }).
|
762
|
+
to_return(:body => mock_pullreq_response(1))
|
763
|
+
|
764
|
+
expected = "https://github.com/defunkt/hub/pull/1\n"
|
765
|
+
assert_output expected, "pull-request hereyougo -b mojombo:feature -f"
|
766
|
+
end
|
767
|
+
|
768
|
+
def test_pullrequest_explicit_base_with_repo
|
769
|
+
stub_request(:post, "https://#{auth}github.com/api/v2/yaml/pulls/mojombo/hubbub").
|
770
|
+
with(:body => { 'pull' => {'base' => "feature", 'head' => "defunkt:master", 'title' => "hereyougo"} }).
|
771
|
+
to_return(:body => mock_pullreq_response(1))
|
772
|
+
|
773
|
+
expected = "https://github.com/defunkt/hub/pull/1\n"
|
774
|
+
assert_output expected, "pull-request hereyougo -b mojombo/hubbub:feature -f"
|
775
|
+
end
|
776
|
+
|
777
|
+
def test_pullrequest_existing_issue
|
778
|
+
stub_branch('refs/heads/myfix')
|
779
|
+
stub_tracking('myfix', 'mislav', 'awesomefix')
|
780
|
+
stub_command_output "rev-list --cherry mislav/awesomefix...", nil
|
781
|
+
|
782
|
+
stub_request(:post, "https://#{auth}github.com/api/v2/yaml/pulls/defunkt/hub").
|
783
|
+
with(:body => { 'pull' => {'base' => "master", 'head' => "mislav:awesomefix", 'issue' => '92'} }).
|
784
|
+
to_return(:body => mock_pullreq_response(92))
|
785
|
+
|
786
|
+
expected = "https://github.com/defunkt/hub/pull/92\n"
|
787
|
+
assert_output expected, "pull-request -i 92"
|
788
|
+
end
|
789
|
+
|
790
|
+
def test_pullrequest_existing_issue_url
|
791
|
+
stub_branch('refs/heads/myfix')
|
792
|
+
stub_tracking('myfix', 'mislav', 'awesomefix')
|
793
|
+
stub_command_output "rev-list --cherry mislav/awesomefix...", nil
|
794
|
+
|
795
|
+
stub_request(:post, "https://#{auth}github.com/api/v2/yaml/pulls/mojombo/hub").
|
796
|
+
with(:body => { 'pull' => {'base' => "master", 'head' => "mislav:awesomefix", 'issue' => '92'} }).
|
797
|
+
to_return(:body => mock_pullreq_response(92, 'mojombo/hub'))
|
798
|
+
|
799
|
+
expected = "https://github.com/mojombo/hub/pull/92\n"
|
800
|
+
assert_output expected, "pull-request https://github.com/mojombo/hub/issues/92#comment_4"
|
801
|
+
end
|
802
|
+
|
803
|
+
def test_checkout_no_changes
|
804
|
+
assert_forwarded "checkout master"
|
805
|
+
end
|
806
|
+
|
807
|
+
def test_checkout_pullrequest
|
808
|
+
stub_request(:get, "http://github.com/api/v2/json/pulls/defunkt/hub/73").
|
809
|
+
to_return(:body => mock_pull_response('blueyed:feature'))
|
810
|
+
|
811
|
+
assert_commands 'git remote add -f -t feature blueyed git://github.com/blueyed/hub.git',
|
812
|
+
'git checkout -b blueyed-feature blueyed/feature',
|
813
|
+
"checkout https://github.com/defunkt/hub/pull/73/files"
|
814
|
+
end
|
815
|
+
|
816
|
+
def test_checkout_pullrequest_custom_branch
|
817
|
+
stub_request(:get, "http://github.com/api/v2/json/pulls/defunkt/hub/73").
|
818
|
+
to_return(:body => mock_pull_response('blueyed:feature'))
|
819
|
+
|
820
|
+
assert_commands 'git remote add -f -t feature blueyed git://github.com/blueyed/hub.git',
|
821
|
+
'git checkout -b review blueyed/feature',
|
822
|
+
"checkout https://github.com/defunkt/hub/pull/73/files review"
|
823
|
+
end
|
824
|
+
|
825
|
+
def test_checkout_pullrequest_existing_remote
|
826
|
+
stub_command_output 'remote', "origin\nblueyed"
|
827
|
+
|
828
|
+
stub_request(:get, "http://github.com/api/v2/json/pulls/defunkt/hub/73").
|
829
|
+
to_return(:body => mock_pull_response('blueyed:feature'))
|
830
|
+
|
831
|
+
assert_commands 'git remote set-branches --add blueyed feature',
|
832
|
+
'git fetch blueyed +refs/heads/feature:refs/remotes/blueyed/feature',
|
833
|
+
'git checkout -b blueyed-feature blueyed/feature',
|
834
|
+
"checkout https://github.com/defunkt/hub/pull/73/files"
|
835
|
+
end
|
836
|
+
|
557
837
|
def test_version
|
558
838
|
out = hub('--version')
|
559
839
|
assert_includes "git version 1.7.0.4", out
|
@@ -567,7 +847,7 @@ class HubTest < Test::Unit::TestCase
|
|
567
847
|
|
568
848
|
def test_exec_path_arg
|
569
849
|
out = hub('--exec-path=/home/wombat/share/my-l33t-git-core')
|
570
|
-
assert_equal
|
850
|
+
assert_equal improved_help_text, out
|
571
851
|
end
|
572
852
|
|
573
853
|
def test_html_path
|
@@ -576,15 +856,15 @@ class HubTest < Test::Unit::TestCase
|
|
576
856
|
end
|
577
857
|
|
578
858
|
def test_help
|
579
|
-
assert_equal
|
859
|
+
assert_equal improved_help_text, hub("help")
|
580
860
|
end
|
581
861
|
|
582
862
|
def test_help_by_default
|
583
|
-
assert_equal
|
863
|
+
assert_equal improved_help_text, hub("")
|
584
864
|
end
|
585
865
|
|
586
866
|
def test_help_with_pager
|
587
|
-
assert_equal
|
867
|
+
assert_equal improved_help_text, hub("-p")
|
588
868
|
end
|
589
869
|
|
590
870
|
def test_help_hub
|
@@ -623,7 +903,7 @@ config
|
|
623
903
|
|
624
904
|
def test_hub_compare_tracking_branch
|
625
905
|
stub_branch('refs/heads/feature')
|
626
|
-
stub_tracking('feature', 'mislav', '
|
906
|
+
stub_tracking('feature', 'mislav', 'experimental')
|
627
907
|
|
628
908
|
assert_command "compare",
|
629
909
|
"open https://github.com/mislav/hub/compare/experimental"
|
@@ -634,6 +914,21 @@ config
|
|
634
914
|
"open https://github.com/defunkt/hub/compare/1.0...fix"
|
635
915
|
end
|
636
916
|
|
917
|
+
def test_hub_compare_range_fixes_two_dots_for_tags
|
918
|
+
assert_command "compare 1.0..fix",
|
919
|
+
"open https://github.com/defunkt/hub/compare/1.0...fix"
|
920
|
+
end
|
921
|
+
|
922
|
+
def test_hub_compare_range_fixes_two_dots_for_shas
|
923
|
+
assert_command "compare 1234abc..3456cde",
|
924
|
+
"open https://github.com/defunkt/hub/compare/1234abc...3456cde"
|
925
|
+
end
|
926
|
+
|
927
|
+
def test_hub_compare_range_ignores_two_dots_for_complex_ranges
|
928
|
+
assert_command "compare @{a..b}..@{c..d}",
|
929
|
+
"open https://github.com/defunkt/hub/compare/@{a..b}..@{c..d}"
|
930
|
+
end
|
931
|
+
|
637
932
|
def test_hub_compare_on_wiki
|
638
933
|
stub_repo_url 'git://github.com/defunkt/hub.wiki.git'
|
639
934
|
assert_command "compare 1.0...fix",
|
@@ -654,6 +949,10 @@ config
|
|
654
949
|
assert_command "browse mojombo/bert", "open https://github.com/mojombo/bert"
|
655
950
|
end
|
656
951
|
|
952
|
+
def test_hub_browse_commit
|
953
|
+
assert_command "browse mojombo/bert commit/5d5582", "open https://github.com/mojombo/bert/commit/5d5582"
|
954
|
+
end
|
955
|
+
|
657
956
|
def test_hub_browse_tracking_nothing
|
658
957
|
stub_tracking_nothing
|
659
958
|
assert_command "browse mojombo/bert", "open https://github.com/mojombo/bert"
|
@@ -678,7 +977,7 @@ config
|
|
678
977
|
|
679
978
|
def test_hub_browse_on_branch
|
680
979
|
stub_branch('refs/heads/feature')
|
681
|
-
stub_tracking('feature', 'mislav', '
|
980
|
+
stub_tracking('feature', 'mislav', 'experimental')
|
682
981
|
|
683
982
|
assert_command "browse resque", "open https://github.com/tpw/resque"
|
684
983
|
assert_command "browse resque commits",
|
@@ -697,6 +996,10 @@ config
|
|
697
996
|
assert_command "browse --", "open https://github.com/defunkt/hub"
|
698
997
|
end
|
699
998
|
|
999
|
+
def test_hub_browse_commit_from_current
|
1000
|
+
assert_command "browse -- commit/6616e4", "open https://github.com/defunkt/hub/commit/6616e4"
|
1001
|
+
end
|
1002
|
+
|
700
1003
|
def test_hub_browse_no_tracking
|
701
1004
|
stub_tracking_nothing
|
702
1005
|
assert_command "browse", "open https://github.com/defunkt/hub"
|
@@ -704,7 +1007,7 @@ config
|
|
704
1007
|
|
705
1008
|
def test_hub_browse_no_tracking_on_branch
|
706
1009
|
stub_branch('refs/heads/feature')
|
707
|
-
|
1010
|
+
stub_tracking_nothing('feature')
|
708
1011
|
assert_command "browse", "open https://github.com/defunkt/hub"
|
709
1012
|
end
|
710
1013
|
|
@@ -786,63 +1089,62 @@ config
|
|
786
1089
|
def test_global_flags_preserved
|
787
1090
|
cmd = '--no-pager --bare -c core.awesome=true -c name=value --git-dir=/srv/www perform'
|
788
1091
|
assert_command cmd, 'git --bare -c core.awesome=true -c name=value --git-dir=/srv/www --no-pager perform'
|
789
|
-
assert_equal %w[git --bare -c core.awesome=true -c name=value --git-dir=/srv/www],
|
1092
|
+
assert_equal %w[git --bare -c core.awesome=true -c name=value --git-dir=/srv/www], git_reader.executable
|
790
1093
|
end
|
791
1094
|
|
792
1095
|
protected
|
793
1096
|
|
794
1097
|
def stub_github_user(name)
|
795
|
-
|
1098
|
+
stub_config_value 'github.user', name
|
796
1099
|
end
|
797
1100
|
|
798
1101
|
def stub_github_token(token)
|
799
|
-
|
1102
|
+
stub_config_value 'github.token', token
|
800
1103
|
end
|
801
1104
|
|
802
|
-
def stub_repo_url(value)
|
803
|
-
|
804
|
-
Hub::Context::REMOTES.clear
|
1105
|
+
def stub_repo_url(value, remote_name = 'origin')
|
1106
|
+
stub_config_value "remote.#{remote_name}.url", value, '--get-all'
|
805
1107
|
end
|
806
1108
|
|
807
1109
|
def stub_branch(value)
|
808
|
-
|
1110
|
+
stub_command_output 'symbolic-ref -q HEAD', value
|
809
1111
|
end
|
810
1112
|
|
811
1113
|
def stub_tracking(from, remote_name, remote_branch)
|
812
|
-
|
813
|
-
|
1114
|
+
stub_command_output "rev-parse --symbolic-full-name #{from}@{upstream}",
|
1115
|
+
remote_branch ? "refs/remotes/#{remote_name}/#{remote_branch}" : nil
|
814
1116
|
end
|
815
1117
|
|
816
|
-
def stub_tracking_nothing
|
817
|
-
stub_tracking(
|
1118
|
+
def stub_tracking_nothing(from = 'master')
|
1119
|
+
stub_tracking(from, nil, nil)
|
818
1120
|
end
|
819
1121
|
|
820
1122
|
def stub_remotes_group(name, value)
|
821
|
-
|
1123
|
+
stub_config_value "remotes.#{name}", value
|
822
1124
|
end
|
823
1125
|
|
824
1126
|
def stub_no_remotes
|
825
|
-
|
1127
|
+
stub_command_output 'remote', nil
|
826
1128
|
end
|
827
1129
|
|
828
1130
|
def stub_no_git_repo
|
829
|
-
|
1131
|
+
stub_command_output 'rev-parse -q --git-dir', nil
|
830
1132
|
end
|
831
1133
|
|
832
1134
|
def stub_alias(name, value)
|
833
|
-
|
1135
|
+
stub_config_value "alias.#{name}", value
|
834
1136
|
end
|
835
1137
|
|
836
|
-
def stub_existing_fork(user)
|
837
|
-
stub_fork(user, 200)
|
1138
|
+
def stub_existing_fork(user, repo = 'hub')
|
1139
|
+
stub_fork(user, repo, 200)
|
838
1140
|
end
|
839
1141
|
|
840
|
-
def stub_nonexisting_fork(user)
|
841
|
-
stub_fork(user, 404)
|
1142
|
+
def stub_nonexisting_fork(user, repo = 'hub')
|
1143
|
+
stub_fork(user, repo, 404)
|
842
1144
|
end
|
843
1145
|
|
844
|
-
def stub_fork(user, status)
|
845
|
-
stub_request(:get, "github.com/api/v2/yaml/repos/show/#{user}
|
1146
|
+
def stub_fork(user, repo, status)
|
1147
|
+
stub_request(:get, "github.com/api/v2/yaml/repos/show/#{user}/#{repo}").
|
846
1148
|
to_return(:status => status)
|
847
1149
|
end
|
848
1150
|
|
@@ -850,6 +1152,10 @@ config
|
|
850
1152
|
COMMANDS.replace names
|
851
1153
|
end
|
852
1154
|
|
1155
|
+
def stub_https_is_preferred
|
1156
|
+
stub_config_value 'hub.protocol', 'https'
|
1157
|
+
end
|
1158
|
+
|
853
1159
|
def with_browser_env(value)
|
854
1160
|
browser, ENV['BROWSER'] = ENV['BROWSER'], value
|
855
1161
|
yield
|
@@ -878,4 +1184,22 @@ config
|
|
878
1184
|
end
|
879
1185
|
end
|
880
1186
|
|
1187
|
+
def auth(user = git_config('github.user'), password = git_config('github.token'))
|
1188
|
+
"#{user}%2Ftoken:#{password}@"
|
1189
|
+
end
|
1190
|
+
|
1191
|
+
def mock_pullreq_response(id, name_with_owner = 'defunkt/hub')
|
1192
|
+
YAML.dump('pull' => {
|
1193
|
+
'html_url' => "https://github.com/#{name_with_owner}/pull/#{id}"
|
1194
|
+
})
|
1195
|
+
end
|
1196
|
+
|
1197
|
+
def mock_pull_response(label)
|
1198
|
+
JSON.generate('pull' => { 'head' => {'label' => label} })
|
1199
|
+
end
|
1200
|
+
|
1201
|
+
def improved_help_text
|
1202
|
+
Hub::Commands.send :improved_help_text
|
1203
|
+
end
|
1204
|
+
|
881
1205
|
end
|