m-git 2.5.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.md +85 -0
  4. data/lib/m-git.rb +66 -0
  5. data/lib/m-git/argv.rb +170 -0
  6. data/lib/m-git/argv/opt.rb +38 -0
  7. data/lib/m-git/argv/opt_list.rb +71 -0
  8. data/lib/m-git/argv/parser.rb +66 -0
  9. data/lib/m-git/base_command.rb +271 -0
  10. data/lib/m-git/command/add.rb +41 -0
  11. data/lib/m-git/command/branch.rb +90 -0
  12. data/lib/m-git/command/checkout.rb +106 -0
  13. data/lib/m-git/command/clean.rb +64 -0
  14. data/lib/m-git/command/commit.rb +84 -0
  15. data/lib/m-git/command/config.rb +202 -0
  16. data/lib/m-git/command/delete.rb +99 -0
  17. data/lib/m-git/command/fetch.rb +32 -0
  18. data/lib/m-git/command/forall.rb +81 -0
  19. data/lib/m-git/command/info.rb +74 -0
  20. data/lib/m-git/command/init.rb +324 -0
  21. data/lib/m-git/command/log.rb +73 -0
  22. data/lib/m-git/command/merge.rb +381 -0
  23. data/lib/m-git/command/pull.rb +364 -0
  24. data/lib/m-git/command/push.rb +311 -0
  25. data/lib/m-git/command/rebase.rb +348 -0
  26. data/lib/m-git/command/reset.rb +31 -0
  27. data/lib/m-git/command/self.rb +223 -0
  28. data/lib/m-git/command/stash.rb +189 -0
  29. data/lib/m-git/command/status.rb +135 -0
  30. data/lib/m-git/command/sync.rb +327 -0
  31. data/lib/m-git/command/tag.rb +67 -0
  32. data/lib/m-git/command_manager.rb +24 -0
  33. data/lib/m-git/error.rb +20 -0
  34. data/lib/m-git/foundation.rb +25 -0
  35. data/lib/m-git/foundation/constants.rb +107 -0
  36. data/lib/m-git/foundation/dir.rb +25 -0
  37. data/lib/m-git/foundation/duration_recorder.rb +92 -0
  38. data/lib/m-git/foundation/git_message_parser.rb +50 -0
  39. data/lib/m-git/foundation/lock.rb +32 -0
  40. data/lib/m-git/foundation/loger.rb +129 -0
  41. data/lib/m-git/foundation/mgit_config.rb +222 -0
  42. data/lib/m-git/foundation/operation_progress_manager.rb +139 -0
  43. data/lib/m-git/foundation/timer.rb +74 -0
  44. data/lib/m-git/foundation/utils.rb +361 -0
  45. data/lib/m-git/hooks_manager.rb +96 -0
  46. data/lib/m-git/manifest.rb +181 -0
  47. data/lib/m-git/manifest/cache_manager.rb +44 -0
  48. data/lib/m-git/manifest/internal.rb +182 -0
  49. data/lib/m-git/manifest/light_repo.rb +108 -0
  50. data/lib/m-git/manifest/light_repo_generator.rb +87 -0
  51. data/lib/m-git/manifest/linter.rb +153 -0
  52. data/lib/m-git/open_api.rb +427 -0
  53. data/lib/m-git/open_api/script_download_info.rb +37 -0
  54. data/lib/m-git/output/output.rb +461 -0
  55. data/lib/m-git/plugin_manager.rb +112 -0
  56. data/lib/m-git/repo.rb +133 -0
  57. data/lib/m-git/repo/status.rb +481 -0
  58. data/lib/m-git/repo/sync_helper.rb +254 -0
  59. data/lib/m-git/template.rb +9 -0
  60. data/lib/m-git/template/local_manifest.rb +27 -0
  61. data/lib/m-git/template/manifest_hook.rb +28 -0
  62. data/lib/m-git/template/post_download_hook.rb +29 -0
  63. data/lib/m-git/template/post_hook.rb +31 -0
  64. data/lib/m-git/template/pre_exec_hook.rb +31 -0
  65. data/lib/m-git/template/pre_hook.rb +29 -0
  66. data/lib/m-git/template/pre_push_hook.rb +32 -0
  67. data/lib/m-git/version.rb +6 -0
  68. data/lib/m-git/workspace.rb +648 -0
  69. data/lib/m-git/workspace/path_helper.rb +56 -0
  70. data/lib/m-git/workspace/workspace_helper.rb +159 -0
  71. data/m-git +1 -0
  72. data/mgit +19 -0
  73. metadata +218 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 061c41a63ff3870becb7688fd0006b85c57423d3fd909e6dde81df7756f3dc3b
4
+ data.tar.gz: d9da7bf09c24160ef38953892306ac3fa659400fe1742c59a621b0d6f1c6be10
5
+ SHA512:
6
+ metadata.gz: 57cef37878e9c37fe761717385a83c5237dcec0ab14057ab3013eae05ee353426031556888420322c621051d8331e6c522d65119439b61b2f260f0a3a6f0eb5f
7
+ data.tar.gz: 710a2e9b7de9b273b4ddd40a8e8d3d3a252e2cbd97a94bb6b66b3aeea91b21c1afc9388efd63f8102a42e986188c46a5b97f2b9bce70327461455ca3a594c72c
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2020 Baidu, Inc. All Rights Reserved.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,85 @@
1
+ # MGit
2
+
3
+ MGit是一款ruby封装的基于Git的多仓库管理工具,可以高效的、同时的对多个Git仓库执行Git命令。
4
+ 适合于在多个仓库中进行关联开发的项目,提高git操作的效率,避免逐个执行Git命令带来的误操作风险。
5
+
6
+ - **易用的命令**
7
+ 封装Git命令,命令和参数均由Git衍生而来,会使用Git就可以成本低上手MGit。
8
+
9
+ - **直观高效的执行命令**
10
+ 提供图表化的结果展示,开发者可以快速查看命令在多个仓库的执行结果;
11
+ 多线程并发执行多仓库命令,通过仓库缓存机制提高仓库的拉取效率;
12
+
13
+ - **安全的执行命令**
14
+ 在执行命令前对多仓库状态进行安全检查:分支是否异常,工作区是否未提交代码等;
15
+ 对.git进行托管与Git工作区分类,避免误删丢失改动或提交;
16
+ 执行存在风险的操作时,会给与风险操作提示,避免误操作;
17
+
18
+ - **方便扩展**
19
+ 支持加载ruby-gem包作为插件,gem包名格式 `m-git-${suffix}`和`mgit-${suffix}`
20
+ 快速的扩展MGit的命令,增加自定义命令,扩展已有命令的功能;
21
+ 提供类似`git hook`的 hook点,方便开发者实现自定义逻辑;
22
+
23
+ ## 快速开始
24
+ #### 1、安装MGit工具
25
+
26
+ 环境要求:
27
+
28
+ - 系统:支持 macOS、Ubuntu,暂时不支持 window-
29
+ - Ruby版本: >= 2.3.7
30
+
31
+ ```ruby
32
+ $ gem install m-git
33
+ ```
34
+
35
+ #### 2、初始化多仓库
36
+
37
+ 初始化多仓库使用 `mgit init` 命令;
38
+
39
+ 类似于 Git 从远程 clone 新仓库, 会将多个仓库 clone 到本地;
40
+
41
+ 下面通过一个demo体验一下MGit命令:
42
+
43
+ ```ruby
44
+ # 2.1 建议在一个新文件夹中拉取demo
45
+ $ mgit init -g https://github.com/baidu/m-git.git
46
+
47
+ # 2.2 体验一下mgit命令
48
+ $ mgit -l 显示所有migt管理的仓库
49
+ $ mgit branch --compact 查看多仓库的分支
50
+ $ mgit status 产看仓库分支超前/落后情况
51
+ ```
52
+
53
+
54
+
55
+ #### 3、进一步了解MGit
56
+
57
+ [常用命令](docs/use/common-commands.md)
58
+
59
+ [manifest文件介绍](docs/config/manifest.md)
60
+
61
+ [配置多仓库](docs/config/config-env.md)
62
+
63
+ [了解更多](docs/references.md)
64
+
65
+
66
+ ## 测试
67
+
68
+ 单测在MGit仓库内的test文件夹下
69
+ 新建单测文件,必须以‘test_’开头,
70
+ 执行单测:rake (如果报错尝试执行 bundle install)
71
+
72
+
73
+ ## 如何贡献
74
+
75
+ 欢迎开发者向MGit贡献代码。如果您开发了新功能或发现了bug,欢迎给我们提交PR。
76
+
77
+ 代码贡献要求:
78
+ 1. 功能和实现应该具有通用性, 不是为了解决某个具体业务而定制的代码逻辑
79
+ 2. 代码质量高,符合Ruby编码规范
80
+ 3. 需要补充对应的单测case
81
+
82
+ issues贡献: 如在使用中遇到问题,请在 https://github.com/baidu/m-git/issues 新建 issues 反馈问题。
83
+
84
+
85
+
data/lib/m-git.rb ADDED
@@ -0,0 +1,66 @@
1
+
2
+ $:.unshift __dir__
3
+
4
+ require 'open3'
5
+ require 'fileutils'
6
+ require 'json'
7
+ require 'digest'
8
+ require 'pathname'
9
+ require 'uri'
10
+ require 'yaml'
11
+ require 'securerandom'
12
+
13
+ require 'colored2'
14
+ require 'peach'
15
+ require 'tty-pager'
16
+
17
+ require 'm-git/foundation'
18
+ require 'm-git/output/output'
19
+ module MGit
20
+ include MGit::Foundation
21
+ end
22
+
23
+ require 'm-git/argv'
24
+ require 'm-git/hooks_manager'
25
+ require 'm-git/command_manager'
26
+ require 'm-git/base_command'
27
+ require 'm-git/error'
28
+ require 'm-git/repo'
29
+ require 'm-git/manifest'
30
+ require 'm-git/template'
31
+ require 'm-git/version'
32
+ require 'm-git/workspace'
33
+
34
+ # 对外其他ruby脚本调用接口
35
+ require 'm-git/open_api'
36
+
37
+ # load plugin
38
+ require 'm-git/plugin_manager'
39
+
40
+
41
+ module MGit
42
+ # 加载插件
43
+ PluginManager.setup
44
+
45
+ module_function
46
+ # input
47
+ def run(raw_argv)
48
+ # 处理不带子命令或带全局参数的输入,如果带全局参数,目前版本对后续附加的子命令不处理。
49
+ raw_argv.unshift('self') if (raw_argv.first.nil? || (raw_argv.first =~ /-/) == 0)
50
+ need_verbose = raw_argv.delete('--verbose') || $__VERBOSE__ || false
51
+ argv = ARGV::Parser.parse(raw_argv)
52
+
53
+ begin
54
+ # 特殊处理'base'
55
+ cmd_class = CommandManager[argv.cmd]
56
+ Foundation.help!("调用非法指令\"#{argv.cmd}\"") if cmd_class.nil?
57
+ cmd_class.new(argv).run
58
+ rescue => e
59
+ Output.puts_fail_message("执行该指令时发生异常:#{argv.cmd}")
60
+ Output.puts_fail_message("异常信息:#{e.message}")
61
+ Output.puts_fail_message("异常位置:#{e.backtrace.join("\n")}") if need_verbose
62
+ exit
63
+ end
64
+ end
65
+ end
66
+
data/lib/m-git/argv.rb ADDED
@@ -0,0 +1,170 @@
1
+ #coding=utf-8
2
+
3
+ module MGit
4
+
5
+ # 参数处理类
6
+ class ARGV
7
+
8
+ require 'm-git/argv/opt'
9
+ require 'm-git/argv/opt_list'
10
+ require 'm-git/argv/parser'
11
+
12
+ # 指令名,如:"mgit checkout -b branch_name"的"checkout"
13
+ attr_reader :cmd
14
+
15
+ # 所有参数,如:"mgit checkout -b branch_name"的"checkout -b branch_name"
16
+ attr_reader :pure_opts
17
+
18
+ # 完整指令,如:"mgit checkout -b branch_name"
19
+ attr_reader :absolute_cmd
20
+
21
+ # 本次传入的mgit指令中自定义的部分,如:"mgit checkout -b branch_name --mrepo boxapp BBAAccount --command test"的"[[--mrepo boxapp BBAAccount],[--command test]]"
22
+ attr_reader :raw_opts
23
+
24
+ # 本次传入的mgit指令中git透传的部分,如:"mgit checkout -b branch_name --mrepo boxapp BBAAccount"的"[[-b branch_name]]"
25
+ # has define method git_opts
26
+
27
+ # 所有已注册的参数列表
28
+ attr_reader :opt_list
29
+
30
+ def initialize(cmd, pure_opts, absolute_cmd, raw_opts)
31
+ @cmd = cmd
32
+ @pure_opts = pure_opts
33
+ @absolute_cmd = absolute_cmd
34
+ @raw_opts = raw_opts
35
+ @git_opts = []
36
+ end
37
+
38
+ def register_opts(opts)
39
+ return if opts.nil?
40
+ @opt_list = OptList.new(opts)
41
+ end
42
+
43
+ # 注册解析指令
44
+ def resolve!
45
+ @raw_opts.each { |raw_opt|
46
+ next if @opt_list.did_register_opt?(raw_opt.first)
47
+ @git_opts.push(raw_opt)
48
+ }
49
+
50
+ @raw_opts -= @git_opts
51
+
52
+ __resolve_git_opts
53
+ __resolve_raw_opts
54
+ end
55
+
56
+ # 更新指令值
57
+ # @!attribute [Array / String / true / false] value
58
+ #
59
+ def update_opt(key, value, priority:nil, info:nil)
60
+ return unless @opt_list.did_register_opt?(key)
61
+ opt = @opt_list.registered_opt(key)
62
+ case opt.value_type
63
+ when Array
64
+ opt.value = Array(value)
65
+ when String
66
+ opt.value = value.is_a?(Array) ? value.first.to_s : value.to_s
67
+ else # boolean
68
+ opt.value = value
69
+ end
70
+
71
+ opt.priority = priority if !priority.nil?
72
+ opt.info = info if info.is_a?(String)
73
+ end
74
+
75
+ # 获取某个option
76
+ def opt(key)
77
+ @opt_list.opt(key)
78
+ end
79
+
80
+ # 获取某个option的描述信息
81
+ def info(key)
82
+ return '' unless @opt_list.did_register_opt?(key)
83
+ @opt_list.registered_opt(key)&.info
84
+ end
85
+
86
+ # 获取原生git指令(非自定义的指令)
87
+ #
88
+ # @param raw [Boolean] default: true,true:用空格拼接成一个字符串返回。false:直接返回数组,如‘-k k1 k2’ -> 【'-k','k1','k2'】
89
+ #
90
+ # @return [Type] description_of_returned_object
91
+ #
92
+ def git_opts(raw: true)
93
+ return @git_opts unless raw
94
+ opts = []
95
+ @git_opts.each { |e_arr|
96
+ opts += e_arr
97
+ }
98
+ opts.join(' ')
99
+ end
100
+
101
+ # 遍历本次调用中传入过值(或有默认值)的选项,未传入值且无默认值则不遍历
102
+ def enumerate_valid_opts
103
+ @opt_list.opts_ordered_by_priority.each { |opt|
104
+ next unless @opt_list.did_set_opt?(opt.key)
105
+ yield(opt) if block_given?
106
+ }
107
+ end
108
+
109
+ # 判断一个字符串是否是option(以'--'或'-'开头)
110
+ def is_option?(opt_str)
111
+ (opt_str =~ /-/) == 0 || (opt_str =~ /--/) == 0
112
+ end
113
+
114
+ # 输出本次指令的具体值信息,调试时使用
115
+ def show_detail
116
+ @opt_list.opts.each { |opt|
117
+ puts '======='
118
+ puts "key:#{opt.key}"
119
+ puts "value:#{opt.value}"
120
+ puts "info:#{opt.info}"
121
+ puts "\n"
122
+ }
123
+ end
124
+
125
+ # 输出参数说明信息
126
+ def show_info
127
+ @opt_list.opts.each { |opt|
128
+ short_key = "#{opt.short_key}, " if !opt.short_key.nil?
129
+ puts "\n"
130
+ puts Output.blue_message("[#{short_key}#{opt.key}]")
131
+ puts "#{opt.info}"
132
+ }
133
+ end
134
+
135
+ private
136
+
137
+ def __resolve_git_opts
138
+ # 统一将值用双引号括起来,避免空格和特殊字符等引起错误
139
+ @git_opts.each { |e_arr|
140
+ next unless is_option?(e_arr.first)
141
+ e_arr.map!.with_index { |e, i|
142
+ # 如果是 -- / - 开始的option,则增加"" 避免特殊字符的错误,eg: --yoo=ajsdaf => --yoo="ajsdaf"
143
+ # 如果是 repo1 repo2 这样的option,则不作处理,eg: yoo ajsdaf => yoo ajsdaf
144
+ e = "\"#{e}\"" if !is_option?(e) && i > 0
145
+ e
146
+ }
147
+ }
148
+ end
149
+
150
+ def __resolve_raw_opts
151
+ @raw_opts.each { |raw_opt|
152
+ key = raw_opt.first
153
+ opt = @opt_list.registered_opt(key)
154
+
155
+ case opt.value_type
156
+ when :boolean
157
+ raise "参数#{key}格式错误,禁止传入参数值!(用法:#{key})" if raw_opt.count != 1
158
+ opt.value = true
159
+ when :string
160
+ raise "参数#{key}格式错误,只能传入一个参数值!(用法:#{key} xxx)" if raw_opt.count != 2
161
+ opt.value = raw_opt.last.to_s
162
+ when :array
163
+ raise "参数#{key}格式错误,至少传入一个参数值!(用法:#{key} xxx xxx ...)" if raw_opt.count < 2
164
+ opt.value = raw_opt[1..-1]
165
+ end
166
+ }
167
+ end
168
+ end
169
+
170
+ end
@@ -0,0 +1,38 @@
1
+ #coding=utf-8
2
+
3
+ module MGit
4
+
5
+ class ARGV
6
+ # 单个选项, 如‘--k1=v1 --k2 v2 v3 --flag’
7
+ # '--k1=v1' key: '--k1', value: 'v1'
8
+ # '--k2 v2 v3' key: '--k2', value: ['v2', 'v3']
9
+ # '--flag' key: '--flag', value: true
10
+ class Opt
11
+ attr_reader :key
12
+ attr_accessor :value
13
+ attr_accessor :short_key # 短参数格式,如’--command’对应的‘-c’
14
+ attr_accessor :priority # 参数解析优先级
15
+ attr_accessor :info # 参数说明
16
+
17
+ # @!attribute value值类型
18
+ # :array :string :boolean
19
+ attr_accessor :value_type
20
+
21
+ def initialize(key, default:nil, short_key:nil, priority:-1, info:nil, type: :array)
22
+ raise("初始化Opt选项必须有key") if key.nil?
23
+ @key, @value, @short_key, @priority, @info = key, default, short_key, priority, info
24
+ @value_type = type
25
+ end
26
+
27
+ def empty?
28
+ value.nil? || value == '' || value == [] || value == false
29
+ end
30
+
31
+ def validate?
32
+ return false if empty?
33
+ value.is_a?(value_type)
34
+ end
35
+ end
36
+ end
37
+
38
+ end
@@ -0,0 +1,71 @@
1
+ #coding=utf-8
2
+
3
+ module MGit
4
+ class ARGV
5
+ # 参数对象列表
6
+ class OptList
7
+
8
+ # [Array<ARGV::Opt>] 参数对象数组
9
+ attr_accessor :opts
10
+
11
+ # attr_reader :valid_opts
12
+
13
+ def initialize(opts)
14
+ @opts = opts
15
+ end
16
+
17
+ def valid_opts
18
+ @opts.select { |e| !e.empty? }
19
+ end
20
+
21
+ # 获取某个参数对象
22
+ #
23
+ # @param key [String] 参数名,如‘--key’
24
+ #
25
+ # @return [ARGV::Opt] 参数对象,若参数未设置过则返回nil
26
+ #
27
+ def opt(key)
28
+ valid_opts.find { |e| (e.key == key || e.short_key == key) }
29
+ end
30
+ alias_method :opt_with, :opt
31
+
32
+ # 判断参数是否设置过值
33
+ #
34
+ # @return [Boolean] 参数是否设置过值
35
+ #
36
+ def did_set_opt?(key)
37
+ !opt(key).nil?
38
+ end
39
+
40
+ ## all opts ###
41
+
42
+ # 返回某个注册过的参数对象
43
+ #
44
+ # @param key [String] 参数名,如‘--key’
45
+ #
46
+ # @return [ARGV::Opt] 参数对象,无论参数是否设置过,只要注册过就返回
47
+ #
48
+ def registered_opt(key)
49
+ @opts.find { |e| (e.key == key || e.short_key == key) }
50
+ end
51
+
52
+ # 判断参数是否注册过
53
+ #
54
+ # @return [Boolean] 参数是否注册过
55
+ #
56
+ def did_register_opt?(key)
57
+ !registered_opt(key).nil?
58
+ end
59
+
60
+ # 将参数根据优先级排序(逆序)后返回
61
+ #
62
+ # @return [Array<ARGV::Opt>] 包含参数对象的数组
63
+ #
64
+ def opts_ordered_by_priority
65
+ # 按照优先级进行降序排序
66
+ opts.sort_by { |e| e.priority }.reverse
67
+ end
68
+ end
69
+ end
70
+
71
+ end