gb 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,260 @@
1
+ require 'sub_command'
2
+ require 'ext/gitlab_ext'
3
+
4
+ module Gb
5
+ class Review < SubCommand
6
+
7
+ self.summary = 'push工作分支到远程服务器,并创建merge request.'
8
+
9
+ self.description = <<-DESC
10
+ push工作分支到远程服务器,并创建merge request.
11
+ DESC
12
+
13
+ # self.arguments = [
14
+ # CLAide::Argument.new('working_branch', false, false),
15
+ # CLAide::Argument.new('remote_branch', false, false),
16
+ # ]
17
+
18
+ def self.options
19
+ [
20
+ ["--assignee=[user name]", "指定review用户名称"],
21
+ ["--title", "merge request标题"],
22
+ ["--show-diff", "review前是否显示变更"],
23
+ ].concat(super)
24
+ end
25
+
26
+ def initialize(argv)
27
+ # @working_branch = argv.shift_argument
28
+ # @remote_branch = argv.shift_argument
29
+ @assignee = argv.option('assignee')
30
+ @title = argv.option('title')
31
+ @show_diff = argv.flag?('show-diff')
32
+ super
33
+ end
34
+
35
+ def validate!
36
+ super
37
+ # if @working_branch.nil?
38
+ # help! 'working_branch is required.'
39
+ # end
40
+ # if @remote_branch.nil?
41
+ # help! 'remote_branch is required.'
42
+ # end
43
+ # if @assignee.nil?
44
+ # help! 'assignee is required.'
45
+ # end
46
+ end
47
+
48
+ def run_in_workspace
49
+
50
+ @working_branch = self.workspace_config.workspace_branch
51
+ @remote_branch = self.workspace_config.remote_branch
52
+
53
+ # api: https://www.rubydoc.info/gems/gitlab/toplevel
54
+ # document: https://narkoz.github.io/gitlab/cli
55
+
56
+ Gitlab.configure do |config|
57
+ # set an API endpoint
58
+ # API endpoint URL, default: ENV['GITLAB_API_ENDPOINT']
59
+ config.endpoint = self.gb_config.gitlab.endpoint
60
+
61
+ # set a user private token
62
+ # user's private token or OAuth2 access token, default: ENV['GITLAB_API_PRIVATE_TOKEN']
63
+ config.private_token = self.gb_config.gitlab.private_token
64
+
65
+ # user agent
66
+ config.user_agent = "gb ruby gem[#{VERSION}"
67
+ end
68
+
69
+ user = nil
70
+ if !@assignee.nil?
71
+ user = gitlab_search_user(@assignee)
72
+ end
73
+
74
+ self.gb_config.projects.each_with_index do |project, index|
75
+ project_path = File.expand_path(project.name, './')
76
+ if File.exist?(project_path)
77
+ remote = 'origin'
78
+ info "Create branch '#{@working_branch}' for project '#{project.name}'"
79
+ g = Git.open(project_path)
80
+ else
81
+ g = Git.clone(project.git, project.name, :path => './')
82
+ end
83
+
84
+ gitlab_project = gitlab_search_project(project.name)
85
+ info "Find project #{gitlab_project.name} on #{gitlab_project.web_url}."
86
+
87
+ unless g.is_remote_branch?(@working_branch)
88
+ raise Error.new("Branch '#{@working_branch}' not exist in remote '#{remote}'.")
89
+ end
90
+
91
+ unless g.is_remote_branch?(@remote_branch)
92
+ raise Error.new("Branch '#{@remote_branch}' not exist in remote '#{remote}'.")
93
+ end
94
+
95
+ g.checkout(@working_branch)
96
+ # 更新本地代码
97
+ g.fetch(remote, :p => true, :t => true)
98
+ g.pull("origin", @working_branch)
99
+ g.pull("origin", @remote_branch)
100
+ # push到origin
101
+ g.push(remote, @working_branch)
102
+
103
+ compare_response = Gitlab.compare(gitlab_project.id, @remote_branch, @working_branch);
104
+ if compare_response.commits.size >= 1
105
+ if @show_diff
106
+ puts "\ncommits"
107
+ compare_response.commits.each_with_index do |commit, index|
108
+ unless index == 0
109
+ puts ""
110
+ end
111
+ puts " #{index} id:" + commit["id"]
112
+ puts " author:" + commit["author_name"]
113
+ puts " create at: " + commit["created_at"]
114
+ puts " title: " + commit["title"]
115
+ end
116
+ puts ""
117
+ end
118
+ else
119
+ info "Can't find new commit on #{@working_branch} to #{@remote_branch} in project #{project.name}."
120
+ puts
121
+ next
122
+ end
123
+
124
+ if compare_response.diffs.size >= 1
125
+ if @show_diff
126
+ puts "Diffs"
127
+ compare_response.diffs.each do |diff|
128
+ if diff["new_file"]
129
+ puts " created " + diff["new_path"]
130
+ elsif diff["renamed_file"]
131
+ puts " renamed " + diff["old_path"] + "=>" + diff["new_path"]
132
+ elsif diff["deleted_file"]
133
+ puts " deleted" + diff["old_path"]
134
+ else
135
+ puts " edited " + diff["new_path"]
136
+ end
137
+
138
+ diff = diff["diff"];
139
+ lines = diff.split("\n")
140
+ lines.each do |line|
141
+ puts " " + line
142
+ end
143
+
144
+ end
145
+ end
146
+ else
147
+ info "Can't find diff between #{@working_branch} and #{@remote_branch} in project #{project.name}."
148
+ puts
149
+ next
150
+ end
151
+
152
+ if user.nil?
153
+ users = gitlab_get_team_members(gitlab_project.id)
154
+ begin
155
+ info "\nSelect user name or index for review."
156
+ input_user = STDIN.gets.chomp
157
+ if input_user =~ /[[:digit:]]/
158
+ user = users[input_user.to_i - 1]
159
+ else
160
+ user = gitlab_search_user(input_user)
161
+ end
162
+ if user.nil?
163
+ error "Can not found user '#{input_user}'."
164
+ else
165
+ info "Assign to #{user.username}(#{user.name})"
166
+ end
167
+ end until !user.nil?
168
+ end
169
+
170
+ if @title.nil? || @title.empty?
171
+ begin
172
+ info "\nInput merge request title for project '#{project.name}'"
173
+ @title = STDIN.gets.chomp
174
+ end until @title.length > 0
175
+ end
176
+
177
+ # 总共 0 (差异 0),复用 0 (差异 0)
178
+ # remote:
179
+ # remote: To create a merge request for dev-v3.9.0-luobin, visit:
180
+ # remote: http://git.tianxiao100.com/tianxiao-ios/tianxiao/tianxiao-base-iphone-sdk/merge_requests/new?merge_request%5Bsource_branch%5D=dev-v3.9.0-luobin
181
+ # remote:
182
+ # To http://git.tianxiao100.com/tianxiao-ios/tianxiao/tianxiao-base-iphone-sdk.git
183
+ # * [new branch] dev-v3.9.0-luobin -> dev-v3.9.0-luobin
184
+
185
+ begin
186
+ merge_request = Gitlab.create_merge_request(gitlab_project.id, @title,
187
+ { source_branch: @working_branch, target_branch: @remote_branch, assignee_id:user ? user.id : "" })
188
+ info "Create merge request for #{project.name} success. see detail url:#{merge_request.web_url}"
189
+ if !Gem.win_platform?
190
+ `open -a "/Applications/Google Chrome.app" '#{merge_request.web_url}/diffs'`
191
+ exitstatus = $?.exitstatus
192
+ if exitstatus != 0
193
+ raise Error.new("open chrome failed.")
194
+ else
195
+ # info "Please review diff, then input any to continue."
196
+ # STDIN.gets.chomp
197
+ end
198
+ end
199
+ rescue Gitlab::Error::Conflict => error
200
+ # merge exists
201
+ info "Merge request from '#{@working_branch}' to '#{@remote_branch}' exist."
202
+ rescue Gitlab::Error::Error => error
203
+ raise(error)
204
+ end
205
+ puts
206
+
207
+ end
208
+ end
209
+
210
+ def gitlab_search_user(assignee)
211
+ users = Gitlab.user_search(assignee)
212
+ if users.size > 1
213
+ info "Find more than one user. you means which one?"
214
+ users.each do |user|
215
+ print user.name + ' '
216
+ end
217
+ info ""
218
+ raise Error.new("Find #{users.size} user named #{project.name}")
219
+ elsif users.size == 1
220
+ user = users[0]
221
+ else
222
+ raise Error.new("Can't find user #{assignee}.")
223
+ end
224
+ user
225
+ end
226
+
227
+ def gitlab_search_project(project_name)
228
+ projects = Gitlab.project_search(project_name)
229
+ if projects.size > 1
230
+ info "Find #{projects.size} project named #{project_name}. you means which one?"
231
+ projects.each do |project|
232
+ print project.name + ' '
233
+ end
234
+ print "\n"
235
+ raise Error.new("Find #{projects.size} project named #{project_name}")
236
+
237
+ elsif projects.size == 1
238
+ project = projects[0];
239
+ else
240
+ raise Error.new("Can't find project named '#{project_name}'.")
241
+ end
242
+ project
243
+ end
244
+
245
+ def gitlab_get_team_members(project_id)
246
+ users = Gitlab.project_usesrs(project_id).delete_if { |user|
247
+ user.username == 'root'
248
+ }
249
+ if users.size > 0
250
+ info "Find user to assign."
251
+ users.each_with_index do |user, index|
252
+ puts "#{index + 1}、#{user.username}(#{user.name})".green
253
+ end
254
+ else
255
+ raise Error.new("Can't find members in project '#{project_id}''.")
256
+ end
257
+ users
258
+ end
259
+ end
260
+ end
@@ -0,0 +1,116 @@
1
+ require 'sub_command'
2
+
3
+ module Gb
4
+ class Start < SubCommand
5
+
6
+ self.summary = '创建对应工作分支,并同步到gitlab.'
7
+
8
+ self.description = <<-DESC
9
+ 创建对应工作分支,并同步到gitlab.
10
+ DESC
11
+
12
+ self.arguments = [
13
+ CLAide::Argument.new('working_branch', true, false),
14
+ CLAide::Argument.new('remote_branch', true, false),
15
+ ]
16
+
17
+ def self.options
18
+ [
19
+ ["--force", "忽略工作分支是否存在,强制执行"],
20
+ ].concat(super)
21
+ end
22
+
23
+ def initialize(argv)
24
+ @working_branch = argv.shift_argument
25
+ @remote_branch = argv.shift_argument
26
+ @force = argv.flag?('force')
27
+ super
28
+ end
29
+
30
+ def validate!
31
+ super
32
+ if @working_branch.nil?
33
+ help! 'working_branch is required.'
34
+ end
35
+ if @remote_branch.nil?
36
+ help! 'remote_branch is required.'
37
+ end
38
+ end
39
+
40
+ def run
41
+ remote = 'origin'
42
+ workspace_config = WorkSpaceConfig.new(@remote_branch, @working_branch)
43
+
44
+ self.gb_config.projects.each do |project|
45
+ project_path = File.expand_path(project.name, './')
46
+ if File.exist?(project_path)
47
+ g = Git.open(project_path)
48
+ else
49
+ g = Git.clone(project.git, project.name, :path => './')
50
+ end
51
+
52
+ if self.verbose?
53
+ # g.setLogger(Logger.new(STDOUT))
54
+ end
55
+
56
+ check_uncommit(g, project.name)
57
+
58
+ # 更新本地代码
59
+ g.fetch(remote, :p => true, :t => true)
60
+ # g.pull_opts(remote, g.current_branch, :p => true)
61
+
62
+ if !g.is_remote_branch?(@remote_branch)
63
+ raise Error.new("remote branch '#{@remote_branch}' does not exist for project '#{project.name}'.")
64
+ end
65
+
66
+ if g.is_remote_branch?(@working_branch) && !@force
67
+ raise Error.new("branch '#{@working_branch}' exist in remote '#{remote}' for project '#{project.name}'.")
68
+ end
69
+
70
+ if g.is_local_branch?(@working_branch) && !@force
71
+ raise Error.new("branch '#{@working_branch}' exist in local for project '#{project.name}'.")
72
+ end
73
+
74
+ # g.remote(remote).branch(@remote_branch).checkout()
75
+ # g.branch(@remote_branch).checkout
76
+
77
+ # git_cmd = "git remote set-branches #{remote} '#{@remote_branch}'"
78
+ # puts `#{git_cmd}`.chomp
79
+ #
80
+ # git_cmd = "git fetch --depth 1 #{remote} '#{@remote_branch}'"
81
+ # puts `#{git_cmd}`.chomp
82
+ #
83
+ # $ git remote set-branches origin 'remote_branch_name'
84
+ # $ git fetch --depth 1 origin remote_branch_name
85
+ # $ git checkout remote_branch_name
86
+
87
+ g.checkout(@remote_branch)
88
+
89
+ g.pull(remote, @remote_branch)
90
+
91
+ if g.is_local_branch?(@working_branch)
92
+ g.checkout(@working_branch)
93
+ g.pull(remote, @working_branch)
94
+ else
95
+ puts "create branch '#{@working_branch}' for project '#{project.name}'.".green
96
+ # 创建本地工作分支
97
+ g.checkout(@working_branch, :new_branch => true)
98
+ end
99
+
100
+ # 跟踪远程分支
101
+ g.track(remote, @remote_branch)
102
+
103
+ puts "push branch '#{@working_branch}' to remote for project '#{project.name}'.".green
104
+ # push到origin
105
+ g.push(remote, @working_branch)
106
+
107
+ puts
108
+ end
109
+
110
+ #保存新的workspace配置
111
+ self.save_workspace_config(workspace_config)
112
+
113
+ puts "create work branch '#{@working_branch}' from #{@remote_branch} and push to '#{remote}' success.".green
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,78 @@
1
+ require 'sub_command'
2
+
3
+
4
+ module Gb
5
+
6
+ class Status < SubCommand
7
+
8
+ self.summary = '查看工作分支代码状态'
9
+
10
+ self.description = <<-DESC
11
+ 查看工作分支代码状态.
12
+ DESC
13
+
14
+ def run_in_workspace
15
+
16
+ self.gb_config.projects.each do |project|
17
+ project_path = File.expand_path(project.name, './')
18
+
19
+ if File.exist?(project_path)
20
+ info "for project '#{project.name}'..."
21
+ g = Git.open(project_path)
22
+
23
+ info "current branch '#{g.current_branch}'"
24
+
25
+ changed = g.status.changed
26
+ added = g.status.added
27
+ deleted = g.status.deleted
28
+ untracked = g.status.untracked
29
+
30
+ if !changed.empty?
31
+ alert = true
32
+ puts "modified files:".red
33
+ changed.each do |file, status|
34
+ puts (" M: " << file).red
35
+ end
36
+ end
37
+
38
+ if !added.empty?
39
+ alert = true
40
+ puts "added files:".red
41
+ added.each do |file, status|
42
+ puts (" A: " << file).red
43
+ end
44
+ end
45
+
46
+ if !deleted.empty?
47
+ alert = true
48
+ puts "deleted files:".red
49
+ deleted.each do |file, status|
50
+ puts (" D: " << file).red
51
+ end
52
+ end
53
+
54
+ if !untracked.empty?
55
+ alert = true
56
+ puts "untracked files:".red
57
+ untracked.each do |file, status|
58
+ puts (" " << file).red
59
+ end
60
+ end
61
+
62
+ if alert
63
+
64
+ else
65
+ info "git工作区无代码要提交"
66
+ end
67
+ puts
68
+
69
+ else
70
+ error "please run 'gb init first."
71
+ break
72
+ end
73
+
74
+ end
75
+ end
76
+
77
+ end
78
+ end