git-process 1.0.11 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +37 -9
- data/Gemfile +2 -2
- data/Gemfile.lock +17 -17
- data/README.md +14 -7
- data/bin/git-new-fb +10 -2
- data/bin/git-pull-request +30 -6
- data/bin/git-sync +5 -2
- data/bin/git-to-master +62 -11
- data/git-process.gemspec +15 -15
- data/lib/git-process/abstract_error_builder.rb +0 -3
- data/lib/git-process/changed_file_helper.rb +30 -24
- data/lib/git-process/git_abstract_merge_error_builder.rb +31 -11
- data/lib/git-process/git_branch.rb +5 -0
- data/lib/git-process/git_config.rb +153 -0
- data/lib/git-process/git_lib.rb +212 -164
- data/lib/git-process/git_logger.rb +84 -0
- data/lib/git-process/git_merge_error.rb +3 -14
- data/lib/git-process/git_process.rb +44 -73
- data/lib/git-process/git_process_options.rb +6 -6
- data/lib/git-process/git_rebase_error.rb +4 -13
- data/lib/git-process/git_remote.rb +254 -0
- data/lib/git-process/github_configuration.rb +298 -0
- data/lib/git-process/github_pull_request.rb +65 -27
- data/lib/git-process/new_fb.rb +14 -4
- data/lib/git-process/parked_changes_error.rb +1 -1
- data/lib/git-process/pull_request.rb +100 -13
- data/lib/git-process/pull_request_error.rb +25 -0
- data/lib/git-process/rebase_to_master.rb +47 -27
- data/lib/git-process/sync.rb +48 -33
- data/lib/git-process/uncommitted_changes_error.rb +1 -1
- data/lib/git-process/version.rb +2 -2
- data/spec/GitRepoHelper.rb +48 -25
- data/spec/changed_file_helper_spec.rb +39 -58
- data/spec/git_abstract_merge_error_builder_spec.rb +42 -33
- data/spec/git_branch_spec.rb +30 -30
- data/spec/git_config_spec.rb +45 -0
- data/spec/git_lib_spec.rb +103 -122
- data/spec/git_logger_spec.rb +66 -0
- data/spec/git_process_spec.rb +81 -81
- data/spec/git_remote_spec.rb +188 -0
- data/spec/git_status_spec.rb +36 -36
- data/spec/github_configuration_spec.rb +152 -0
- data/spec/github_pull_request_spec.rb +39 -35
- data/spec/github_test_helper.rb +49 -0
- data/spec/new_fb_spec.rb +65 -24
- data/spec/pull_request_helper.rb +94 -0
- data/spec/pull_request_spec.rb +128 -0
- data/spec/rebase_to_master_spec.rb +241 -145
- data/spec/spec_helper.rb +20 -0
- data/spec/sync_spec.rb +115 -109
- metadata +34 -20
- data/lib/git-process/github_client.rb +0 -83
- data/lib/git-process/github_service.rb +0 -174
- data/spec/github_service_spec.rb +0 -211
@@ -0,0 +1,188 @@
|
|
1
|
+
require 'git-process/git_remote'
|
2
|
+
require 'GitRepoHelper'
|
3
|
+
include GitProc
|
4
|
+
|
5
|
+
describe GitRemote do
|
6
|
+
|
7
|
+
def log_level
|
8
|
+
Logger::ERROR
|
9
|
+
end
|
10
|
+
|
11
|
+
|
12
|
+
describe '#name' do
|
13
|
+
include GitRepoHelper
|
14
|
+
|
15
|
+
it 'should work with origin' do
|
16
|
+
change_file_and_commit('a', '')
|
17
|
+
|
18
|
+
clone_repo('master', 'origin') do |gl|
|
19
|
+
gl.remote.name.should == 'origin'
|
20
|
+
gl.branches.include?('origin/master').should be_true
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
it 'should work with a different remote name' do
|
26
|
+
change_file_and_commit('a', '')
|
27
|
+
|
28
|
+
clone_repo('master', 'a_remote') do |gl|
|
29
|
+
gl.remote.name.should == 'a_remote'
|
30
|
+
gl.branches.include?('a_remote/master').should be_true
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
it 'should work with an overridden remote name' do
|
36
|
+
change_file_and_commit('a', '')
|
37
|
+
|
38
|
+
clone_repo('master', 'a_remote') do |gl|
|
39
|
+
gl.config['gitProcess.remoteName'] = 'something_else'
|
40
|
+
|
41
|
+
gl.remote.name.should == 'something_else'
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
describe "#expanded_url" do
|
49
|
+
include GitRepoHelper
|
50
|
+
|
51
|
+
it "should work for an ssh address" do
|
52
|
+
remote.add('torigin', 'tuser@github.myco.com:jdigger/git-process.git')
|
53
|
+
|
54
|
+
remote.expanded_url('torigin').should == 'ssh://tuser@github.myco.com/jdigger/git-process.git'
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
it 'should work for an http address' do
|
59
|
+
remote.add('torigin', 'http://github.myco.com:8080/jdigger/git-process.git')
|
60
|
+
|
61
|
+
remote.expanded_url('torigin').should == 'http://github.myco.com:8080/jdigger/git-process.git'
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
it "should work for an https address" do
|
66
|
+
remote.add('torigin', 'https://github.myco.com/jdigger/git-process.git')
|
67
|
+
|
68
|
+
remote.expanded_url('torigin').should == 'https://github.myco.com/jdigger/git-process.git'
|
69
|
+
end
|
70
|
+
|
71
|
+
|
72
|
+
it "should work for an ssh-configured url address" do
|
73
|
+
remote.add('origin', 'mygithub:jdigger/git-process.git')
|
74
|
+
|
75
|
+
content = "\nHost mygithub\n"+
|
76
|
+
" User tuser\n"+
|
77
|
+
" HostName github.myco.com\n"
|
78
|
+
|
79
|
+
in_tempfile('ssh_config', content) do |file|
|
80
|
+
remote.expanded_url('origin', nil, :ssh_config_file => file.path).should == 'ssh://tuser@github.myco.com/jdigger/git-process.git'
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
|
86
|
+
|
87
|
+
describe "#hostname_and_user_from_ssh_config" do
|
88
|
+
include GitRepoHelper
|
89
|
+
|
90
|
+
it "should find in a single entry" do
|
91
|
+
content = "\nHost mygithub\n"+
|
92
|
+
" User git\n"+
|
93
|
+
" HostName github.myco.com\n"
|
94
|
+
|
95
|
+
in_tempfile('ssh_config', content) do |file|
|
96
|
+
GitRemote.hostname_and_user_from_ssh_config('mygithub', file.path).should == %w(github.myco.com git)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
|
101
|
+
it "should find in multiple entries" do
|
102
|
+
content = "\nHost mygithub1\n"+
|
103
|
+
" User gittyw\n"+
|
104
|
+
" HostName github.mycoy.com\n"+
|
105
|
+
"Host mygithub2\n"+
|
106
|
+
" User gitty\n"+
|
107
|
+
" HostName github.myco.com\n"+
|
108
|
+
"Host mygithub3\n"+
|
109
|
+
" User gittyz\n"+
|
110
|
+
" HostName github.mycoz.com\n"
|
111
|
+
|
112
|
+
in_tempfile('ssh_config', content) do |file|
|
113
|
+
GitRemote.hostname_and_user_from_ssh_config('mygithub2', file.path).should == %w(github.myco.com gitty)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
|
118
|
+
it "should return nil when no file" do
|
119
|
+
GitRemote.hostname_and_user_from_ssh_config('mygithub', '/bogus_file').should == nil
|
120
|
+
end
|
121
|
+
|
122
|
+
|
123
|
+
it "should return nil when given an unknown host" do
|
124
|
+
content = "\nHost mygithub1\n"+
|
125
|
+
" User gittyw\n"+
|
126
|
+
" HostName github.mycoy.com\n"+
|
127
|
+
"Host mygithub2\n"+
|
128
|
+
" User gitty\n"+
|
129
|
+
" HostName github.myco.com\n"+
|
130
|
+
"Host mygithub3\n"+
|
131
|
+
" User gittyz\n"+
|
132
|
+
" HostName github.mycoz.com\n"
|
133
|
+
|
134
|
+
in_tempfile('ssh_config', content) do |file|
|
135
|
+
GitRemote.hostname_and_user_from_ssh_config('UNKNOWNZ', file.path).should == nil
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
|
140
|
+
it "should return nil when no hostname for an existing host" do
|
141
|
+
content = "\nHost mygithub1\n"+
|
142
|
+
" User gittyw\n"+
|
143
|
+
" HostName github.mycoy.com\n"+
|
144
|
+
"Host mygithub2\n"+
|
145
|
+
" User gitty\n"+
|
146
|
+
"Host mygithub3\n"+
|
147
|
+
" User gittyz\n"+
|
148
|
+
" HostName github.mycoz.com\n"
|
149
|
+
|
150
|
+
in_tempfile('ssh_config', content) do |file|
|
151
|
+
GitRemote.hostname_and_user_from_ssh_config('mygithub2', file.path).should == nil
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
|
156
|
+
it "should return hostname but no username when no user for an existing host" do
|
157
|
+
content = "\nHost mygithub1\n"+
|
158
|
+
" User gittyw\n"+
|
159
|
+
" HostName github.mycoy.com\n"+
|
160
|
+
"Host mygithub2\n"+
|
161
|
+
" HostName github.myco.com\n"+
|
162
|
+
"Host mygithub3\n"+
|
163
|
+
" User gittyz\n"+
|
164
|
+
" HostName github.mycoz.com\n"
|
165
|
+
|
166
|
+
in_tempfile('ssh_config', content) do |file|
|
167
|
+
GitRemote.hostname_and_user_from_ssh_config('mygithub2', file.path).should == ['github.myco.com', nil]
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
end
|
172
|
+
|
173
|
+
end
|
174
|
+
|
175
|
+
|
176
|
+
def in_tempfile(filename, content, &block)
|
177
|
+
file = Tempfile.new(filename)
|
178
|
+
file.puts content
|
179
|
+
file.flush
|
180
|
+
|
181
|
+
begin
|
182
|
+
block.call(file)
|
183
|
+
ensure
|
184
|
+
file.close
|
185
|
+
file.unlink
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
data/spec/git_status_spec.rb
CHANGED
@@ -13,49 +13,49 @@ describe GitProc::GitStatus do
|
|
13
13
|
|
14
14
|
before(:each) do
|
15
15
|
create_files(%w(.gitignore))
|
16
|
-
|
16
|
+
gitlib.commit('initial')
|
17
17
|
end
|
18
18
|
|
19
19
|
|
20
20
|
after(:each) do
|
21
|
-
rm_rf(
|
21
|
+
rm_rf(gitlib.workdir)
|
22
22
|
end
|
23
23
|
|
24
24
|
|
25
|
-
it
|
25
|
+
it 'should handle added files' do
|
26
26
|
create_files(['a', 'b file.txt', 'c'])
|
27
27
|
|
28
|
-
|
28
|
+
gitlib.status.added.should == ['a', 'b file.txt', 'c']
|
29
29
|
end
|
30
30
|
|
31
31
|
|
32
|
-
it
|
32
|
+
it 'should handle a modification on both sides' do
|
33
33
|
change_file_and_commit('a', '')
|
34
34
|
|
35
|
-
|
35
|
+
gitlib.checkout('fb', :new_branch => 'master')
|
36
36
|
change_file_and_commit('a', 'hello')
|
37
37
|
|
38
|
-
|
38
|
+
gitlib.checkout('master')
|
39
39
|
change_file_and_commit('a', 'goodbye')
|
40
40
|
|
41
|
-
|
41
|
+
gitlib.merge('fb') rescue ''
|
42
42
|
|
43
|
-
status =
|
43
|
+
status = gitlib.status
|
44
44
|
status.unmerged.should == %w(a)
|
45
45
|
status.modified.should == %w(a)
|
46
46
|
end
|
47
47
|
|
48
48
|
|
49
49
|
it "should handle an addition on both sides" do
|
50
|
-
|
50
|
+
gitlib.checkout('fb', :new_branch => 'master')
|
51
51
|
change_file_and_commit('a', 'hello')
|
52
52
|
|
53
|
-
|
53
|
+
gitlib.checkout('master')
|
54
54
|
change_file_and_commit('a', 'goodbye')
|
55
55
|
|
56
|
-
|
56
|
+
gitlib.merge('fb') rescue ''
|
57
57
|
|
58
|
-
status =
|
58
|
+
status = gitlib.status
|
59
59
|
status.unmerged.should == %w(a)
|
60
60
|
status.added.should == %w(a)
|
61
61
|
end
|
@@ -64,16 +64,16 @@ describe GitProc::GitStatus do
|
|
64
64
|
it "should handle a merge deletion on fb" do
|
65
65
|
change_file_and_commit('a', '')
|
66
66
|
|
67
|
-
|
68
|
-
|
69
|
-
|
67
|
+
gitlib.checkout('fb', :new_branch => 'master')
|
68
|
+
gitlib.remove('a', :force => true)
|
69
|
+
gitlib.commit('removed a')
|
70
70
|
|
71
|
-
|
71
|
+
gitlib.checkout('master')
|
72
72
|
change_file_and_commit('a', 'goodbye')
|
73
73
|
|
74
|
-
|
74
|
+
gitlib.merge('fb') rescue ''
|
75
75
|
|
76
|
-
status =
|
76
|
+
status = gitlib.status
|
77
77
|
status.unmerged.should == %w(a)
|
78
78
|
status.deleted.should == %w(a)
|
79
79
|
end
|
@@ -82,41 +82,41 @@ describe GitProc::GitStatus do
|
|
82
82
|
it "should handle a merge deletion on master" do
|
83
83
|
change_file_and_commit('a', '')
|
84
84
|
|
85
|
-
|
85
|
+
gitlib.checkout('fb', :new_branch => 'master')
|
86
86
|
change_file_and_commit('a', 'hello')
|
87
87
|
|
88
|
-
|
89
|
-
|
90
|
-
|
88
|
+
gitlib.checkout('master')
|
89
|
+
gitlib.remove('a', :force => true)
|
90
|
+
gitlib.commit('removed a')
|
91
91
|
|
92
|
-
|
92
|
+
gitlib.merge('fb') rescue ''
|
93
93
|
|
94
|
-
status =
|
94
|
+
status = gitlib.status
|
95
95
|
status.unmerged.should == %w(a)
|
96
96
|
status.deleted.should == %w(a)
|
97
97
|
end
|
98
98
|
|
99
99
|
|
100
100
|
it "should handle a move/rename" do
|
101
|
-
FileUtils.cp __FILE__, File.join(
|
102
|
-
|
103
|
-
|
101
|
+
FileUtils.cp __FILE__, File.join(gitlib.workdir, 'a file.txt')
|
102
|
+
gitlib.add('a file.txt')
|
103
|
+
gitlib.commit('a with content')
|
104
104
|
|
105
|
-
FileUtils.cp __FILE__, File.join(
|
106
|
-
|
107
|
-
|
105
|
+
FileUtils.cp __FILE__, File.join(gitlib.workdir, 'b file.txt')
|
106
|
+
gitlib.remove 'a file.txt'
|
107
|
+
gitlib.add 'b file.txt'
|
108
108
|
|
109
|
-
status =
|
109
|
+
status = gitlib.status
|
110
110
|
status.deleted.should == ['a file.txt']
|
111
111
|
status.added.should == ['b file.txt']
|
112
112
|
end
|
113
113
|
|
114
114
|
|
115
115
|
it "should return an empty result" do
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
116
|
+
gitlib.status.added.should == []
|
117
|
+
gitlib.status.deleted.should == []
|
118
|
+
gitlib.status.modified.should == []
|
119
|
+
gitlib.status.unmerged.should == []
|
120
120
|
end
|
121
121
|
|
122
122
|
end
|
@@ -0,0 +1,152 @@
|
|
1
|
+
require 'git-process/github_configuration'
|
2
|
+
require 'json'
|
3
|
+
require 'github_test_helper'
|
4
|
+
|
5
|
+
|
6
|
+
describe GitHubService::Configuration, :git_repo_helper do
|
7
|
+
include GitHubTestHelper
|
8
|
+
|
9
|
+
|
10
|
+
def test_token
|
11
|
+
'hfgkdjfgksjhdfkls'
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
def ghc
|
16
|
+
@ghc ||= GitHubService::Configuration.new(gitlib.config, :user => 'tu', :password => 'dfsdf')
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
describe 'create_authorization' do
|
21
|
+
|
22
|
+
it "should return an auth_token for a good request" do
|
23
|
+
gitlib.remote.add('origin', 'git@github.com:jdigger/git-process.git')
|
24
|
+
stub_post('https://tu:dfsdf@api.github.com/authorizations', :send => auth_json,
|
25
|
+
:body => {:token => test_token})
|
26
|
+
|
27
|
+
ghc.create_authorization().should == test_token
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
it 'should 401 for bad password' do
|
32
|
+
gitlib.remote.add('origin', 'git@github.com:jdigger/git-process.git')
|
33
|
+
stub_post('https://tu:dfsdf@api.github.com/authorizations', :send => auth_json,
|
34
|
+
:status => 401)
|
35
|
+
|
36
|
+
expect { ghc.create_authorization() }.to raise_error Octokit::Unauthorized
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
describe "auth_token no username or password" do
|
43
|
+
|
44
|
+
it "should get the token from config if it exists" do
|
45
|
+
gitlib.config['github.user'] = 'test_user'
|
46
|
+
gitlib.config['gitProcess.github.authToken'] = test_token
|
47
|
+
|
48
|
+
ghc.auth_token.should == test_token
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
|
54
|
+
describe 'auth_token with password but no username' do
|
55
|
+
|
56
|
+
def ghc
|
57
|
+
@ghc ||= GitHubService::Configuration.new(gitlib.config, :user => nil, :password => 'dfsdf')
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
it 'should get the token from the server if it does not exist in config' do
|
62
|
+
gitlib.remote.add('origin', 'git@github.com:jdigger/git-process.git')
|
63
|
+
gitlib.config['github.user'] = 'test_user'
|
64
|
+
gitlib.config['gitProcess.github.authToken'] = ''
|
65
|
+
|
66
|
+
stub_post('https://test_user:dfsdf@api.github.com/authorizations', :send => auth_json,
|
67
|
+
:body => {:token => test_token})
|
68
|
+
|
69
|
+
ghc.auth_token.should == test_token
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
describe "user" do
|
76
|
+
|
77
|
+
def ghc
|
78
|
+
@ghc ||= GitHubService::Configuration.new(gitlib.config, :user => nil, :password => 'dfsdf')
|
79
|
+
end
|
80
|
+
|
81
|
+
|
82
|
+
it "should get the value from config" do
|
83
|
+
gitlib.config['github.user'] = 'test_user'
|
84
|
+
|
85
|
+
ghc.user.should == 'test_user'
|
86
|
+
end
|
87
|
+
|
88
|
+
|
89
|
+
it "should prompt the user and store it in the config" do
|
90
|
+
gitlib.config['github.user'] = ''
|
91
|
+
|
92
|
+
GitHubService::Configuration.stub(:ask_for_user).and_return('test_user')
|
93
|
+
ghc.user.should == 'test_user'
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
|
98
|
+
|
99
|
+
describe "using GHE instead of GitHub.com" do
|
100
|
+
|
101
|
+
it "should use the correct server and path for a non-GitHub.com site" do
|
102
|
+
gitlib.remote.add('origin', 'git@myco.com:jdigger/git-process.git')
|
103
|
+
|
104
|
+
stub_post('https://tu:dfsdf@myco.com/api/v3/authorizations',
|
105
|
+
:send => auth_json,
|
106
|
+
:body => {:token => test_token})
|
107
|
+
|
108
|
+
ghc.create_authorization().should == test_token
|
109
|
+
end
|
110
|
+
|
111
|
+
|
112
|
+
it "site should raise an error if remote.origin.url not set" do
|
113
|
+
gitlib.config['remote.origin.url'] = ''
|
114
|
+
|
115
|
+
expect { ghc.base_github_api_url_for_remote }.to raise_error GitHubService::NoRemoteRepository
|
116
|
+
end
|
117
|
+
|
118
|
+
|
119
|
+
it "site should not work for a garbage url address" do
|
120
|
+
gitlib.remote.add('origin', 'garbage')
|
121
|
+
|
122
|
+
expect { ghc.base_github_api_url_for_remote }.to raise_error URI::InvalidURIError
|
123
|
+
end
|
124
|
+
|
125
|
+
|
126
|
+
it "site should work for an ssh-configured url address" do
|
127
|
+
gitlib.remote.add('origin', 'git@github.myco.com:fooble')
|
128
|
+
|
129
|
+
ghc.base_github_api_url_for_remote.should == 'https://github.myco.com'
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
133
|
+
|
134
|
+
|
135
|
+
it "#url_to_base_github_api_url" do
|
136
|
+
c = GitHubService::Configuration
|
137
|
+
|
138
|
+
c.url_to_base_github_api_url('ssh://git@github.myco.com/fooble').should == 'https://github.myco.com'
|
139
|
+
c.url_to_base_github_api_url('git://myco.com/jdigger/git-process.git').should == 'https://myco.com'
|
140
|
+
c.url_to_base_github_api_url('http://github.myco.com/fooble').should == 'http://github.myco.com'
|
141
|
+
c.url_to_base_github_api_url('http://tu@github.myco.com/fooble').should == 'http://github.myco.com'
|
142
|
+
c.url_to_base_github_api_url('https://github.myco.com/fooble').should == 'https://github.myco.com'
|
143
|
+
c.url_to_base_github_api_url('https://github.com/fooble').should == 'https://api.github.com'
|
144
|
+
end
|
145
|
+
|
146
|
+
|
147
|
+
def auth_json
|
148
|
+
JSON({:note_url => 'http://jdigger.github.com/git-process',
|
149
|
+
:scopes => %w(repo user gist), :note => "Git-Process"})
|
150
|
+
end
|
151
|
+
|
152
|
+
end
|