gb 0.1.1

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.
@@ -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