git-thin 0.0.13
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.
- checksums.yaml +7 -0
- data/.gitignore +3 -0
- data/Gemfile +9 -0
- data/LICENSE.txt +22 -0
- data/README.md +11 -0
- data/Rakefile +13 -0
- data/bin/git-thin +10 -0
- data/bin/thin +10 -0
- data/git-thin.gemspec +26 -0
- data/lib/git-thin.rb +5 -0
- data/lib/git-thin/command.rb +40 -0
- data/lib/git-thin/command/action.rb +117 -0
- data/lib/git-thin/command/checkout.rb +17 -0
- data/lib/git-thin/command/clone.rb +30 -0
- data/lib/git-thin/command/detect.rb +192 -0
- data/lib/git-thin/command/expire.rb +125 -0
- data/lib/git-thin/command/export.rb +256 -0
- data/lib/git-thin/command/fetch.rb +17 -0
- data/lib/git-thin/command/hook.rb +357 -0
- data/lib/git-thin/command/pull.rb +18 -0
- data/lib/git-thin/command/thin_config.rb +326 -0
- data/lib/git-thin/gem_version.rb +3 -0
- data/lib/git-thin/utils/utils.rb +133 -0
- data/spec/command/thin_spec.rb +12 -0
- data/spec/spec_helper.rb +50 -0
- metadata +111 -0
@@ -0,0 +1,125 @@
|
|
1
|
+
require 'claide'
|
2
|
+
require 'json'
|
3
|
+
require "time"
|
4
|
+
module GitThin
|
5
|
+
|
6
|
+
class Expire < Thin
|
7
|
+
include GitThinUtils
|
8
|
+
self.summary = 'Delete expire branch'
|
9
|
+
# self.plugin_prefixes = %w(claide cocoapods)
|
10
|
+
self.arguments = [
|
11
|
+
CLAide::Argument.new('BRANCHS', false ),
|
12
|
+
]
|
13
|
+
|
14
|
+
self.description = <<-DESC
|
15
|
+
Deletes a list of branches. Branches are specified by [BRANCHS] parameter, which can be a list of branch names or a file
|
16
|
+
DESC
|
17
|
+
|
18
|
+
def self.options
|
19
|
+
[
|
20
|
+
['--source_root', 'Specify the warehouse address manually if necessary.'],
|
21
|
+
['--exclude_branchs', 'The name of the excluded branch,file or string.'],
|
22
|
+
].concat(super)
|
23
|
+
|
24
|
+
end
|
25
|
+
def initialize(argv)
|
26
|
+
super
|
27
|
+
|
28
|
+
@branchs = argv.shift_argument
|
29
|
+
if not @branchs
|
30
|
+
return
|
31
|
+
end
|
32
|
+
@source_root = argv.option('source_root')
|
33
|
+
@exclude_branchs = argv.option('exclude_branchs')
|
34
|
+
if @source_root
|
35
|
+
Dir.chdir @source_root
|
36
|
+
end
|
37
|
+
run_shell 'git rev-parse --show-toplevel',false ,LOGNone do |out,err,status|
|
38
|
+
if status == 0
|
39
|
+
@source_root = out[0].strip
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
if not Dir.exist? @source_root
|
44
|
+
@source_root = nil
|
45
|
+
return
|
46
|
+
end
|
47
|
+
|
48
|
+
if FileTest.exist? @branchs
|
49
|
+
File.open(@branchs, "r") do |aFile|
|
50
|
+
@branchs = ""
|
51
|
+
aFile.each do |line|
|
52
|
+
@branchs += line
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
@branchs = @branchs.gsub(',',' ')
|
57
|
+
@branchs = @branchs.split ' '
|
58
|
+
|
59
|
+
if FileTest.exist? @exclude_branchs
|
60
|
+
File.open(@exclude_branchs, "r") do |aFile|
|
61
|
+
@exclude_branchs = ""
|
62
|
+
aFile.each do |line|
|
63
|
+
@exclude_branchs += line
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
@exclude_branchs = @exclude_branchs.gsub(',',' ')
|
68
|
+
@exclude_branchs = @exclude_branchs.split ' '
|
69
|
+
|
70
|
+
run_shell 'git branch -r',false ,true do |out,err,status|
|
71
|
+
if status == 0
|
72
|
+
@remote_branchs = out.map { |line| line = line.strip }
|
73
|
+
@remote_branchs.delete_if do |item|
|
74
|
+
ret = false
|
75
|
+
if item.include? '->'
|
76
|
+
ret = true
|
77
|
+
end
|
78
|
+
ret
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
def validate!
|
86
|
+
super
|
87
|
+
help! 'validate SOURCE_ROOT is required.' unless @source_root
|
88
|
+
end
|
89
|
+
|
90
|
+
def expire_branchs
|
91
|
+
Dir.chdir(@source_root)
|
92
|
+
error_branchs = []
|
93
|
+
exclude_count = 0
|
94
|
+
@branchs.each do |branch|
|
95
|
+
if @exclude_branchs.include? branch
|
96
|
+
logN "#{branch}分支名字黑名单,跳过"
|
97
|
+
exclude_count += 1
|
98
|
+
else
|
99
|
+
if @remote_branchs.include? branch
|
100
|
+
index = branch.index('/')
|
101
|
+
branch[index] = ' '
|
102
|
+
# "git push -d #{branch}"
|
103
|
+
run_shell "git push -d #{branch}",true ,true do|out,err,status|
|
104
|
+
if status!= 0
|
105
|
+
error_branchs.push branch
|
106
|
+
else
|
107
|
+
logN "#{branch}分支删除成功"
|
108
|
+
end
|
109
|
+
end
|
110
|
+
else
|
111
|
+
error_branchs.push branch
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
error_branchs.each do |branch|
|
116
|
+
logE "#{branch}分支删除失败"
|
117
|
+
end
|
118
|
+
logN "总共#{@remote_branchs.length}个分支,计划删除#{@branchs.length}个分支,黑名单跳过#{exclude_count}个,删除失败#{error_branchs.length}个分支"
|
119
|
+
end
|
120
|
+
def run
|
121
|
+
expire_branchs
|
122
|
+
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
@@ -0,0 +1,256 @@
|
|
1
|
+
require 'claide'
|
2
|
+
require 'json'
|
3
|
+
module GitThin
|
4
|
+
|
5
|
+
class Export < Thin
|
6
|
+
include GitThinUtils
|
7
|
+
self.summary = 'Export a git repository and lfs files.'
|
8
|
+
# self.plugin_prefixes = %w(claide cocoapods)
|
9
|
+
self.arguments = [
|
10
|
+
# CLAide::Argument.new('TYPE', false )
|
11
|
+
]
|
12
|
+
|
13
|
+
self.description = <<-DESC
|
14
|
+
recode: Export COMMIT and TAG records for each branch
|
15
|
+
lfs: fetch all lfs object
|
16
|
+
local: checkout all local branch,lfs object
|
17
|
+
DESC
|
18
|
+
|
19
|
+
def self.options
|
20
|
+
[
|
21
|
+
['--force', 'Overwrite existing branch.'],
|
22
|
+
['--target_git', 'Export to the target Git repository'],
|
23
|
+
['--type', 'Export "local","record","git" or "lfs".defalue all'],
|
24
|
+
['--source_root', 'Specify the warehouse address manually if necessary.'],
|
25
|
+
].concat(super)
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
def initialize(argv)
|
30
|
+
super
|
31
|
+
@verbose = argv.flag?('verbose',LOGNone )
|
32
|
+
if @verbose
|
33
|
+
@verbose = LOGC|LOGN
|
34
|
+
end
|
35
|
+
@force = argv.flag?('force')
|
36
|
+
@support_types = ["local","record","git","lfs"]
|
37
|
+
@type = argv.option('type')
|
38
|
+
if not @support_types.include? @type
|
39
|
+
@type = nil
|
40
|
+
logE 'type not support'
|
41
|
+
return
|
42
|
+
end
|
43
|
+
@source_root = argv.option('source_root')
|
44
|
+
@target_git = argv.option('target_git')
|
45
|
+
if @type=='git' && !@target_git
|
46
|
+
logE 'need a target_git if type is git'
|
47
|
+
return
|
48
|
+
end
|
49
|
+
if not @source_root
|
50
|
+
run_shell 'git rev-parse --show-toplevel',false ,LOGNone do |out,err,status|
|
51
|
+
if status == 0
|
52
|
+
@source_root = out[0].strip
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
if not File.exist? @source_root+'/.git'
|
57
|
+
UI.puts "git repository not found"
|
58
|
+
exit 1
|
59
|
+
end
|
60
|
+
end
|
61
|
+
if not Dir.exist? @source_root
|
62
|
+
@source_root = nil
|
63
|
+
return
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def fetch_branch
|
68
|
+
Dir.chdir(@source_root)
|
69
|
+
run_shell 'git branch -r',false ,LOGNone do |out,err,status|
|
70
|
+
if status == 0
|
71
|
+
@branchs = out.map { |line| line = line.strip }
|
72
|
+
@branchs.delete_if do |item|
|
73
|
+
ret = false
|
74
|
+
if item.include? '->'
|
75
|
+
ret = true
|
76
|
+
end
|
77
|
+
ret
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
run_shell 'git branch',false ,LOGNone do |out,err,status|
|
83
|
+
if status == 0
|
84
|
+
@local_branchs = out.map { |line| line = line.strip }
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def validate!
|
90
|
+
super
|
91
|
+
help! 'validate SOURCE_ROOT is required' unless @source_root
|
92
|
+
help! 'validate TYPE is required' unless @type
|
93
|
+
end
|
94
|
+
|
95
|
+
def export_local
|
96
|
+
Dir.chdir(@source_root)
|
97
|
+
run_shell 'git lfs fetch --all',false ,LOGA ,1
|
98
|
+
|
99
|
+
fetch_branch
|
100
|
+
run_shell "git remote",false ,LOGNone do |out,err,status|
|
101
|
+
@remote=out[0].strip
|
102
|
+
end
|
103
|
+
|
104
|
+
progress = 0.0
|
105
|
+
logP "当前进度:#{format("%0.2f",progress*100).to_f}%"
|
106
|
+
@branchs.each_index do|index|
|
107
|
+
branch = @branchs[index]
|
108
|
+
if index*1.0/@branchs.length - progress > 0.001
|
109
|
+
progress = index*1.0/@branchs.length
|
110
|
+
logP "当前进度:#{format("%0.2f",progress*100).to_f}%"
|
111
|
+
end
|
112
|
+
branch=branch[@remote.length+1..-1]
|
113
|
+
run_shell "git checkout -B #{branch} #{@remote}/#{branch} -f",true ,@verbose
|
114
|
+
end
|
115
|
+
|
116
|
+
# run_shell 'git lfs install',true ,true
|
117
|
+
# run_shell 'git lfs fetch --all',false ,false ,1
|
118
|
+
end
|
119
|
+
def export_record
|
120
|
+
fetch_branch
|
121
|
+
Dir.chdir(@source_root)
|
122
|
+
if Dir.exist? ('branchs.bak')
|
123
|
+
FileUtils.rm_rf('branchs.bak')
|
124
|
+
end
|
125
|
+
FileUtils.mkdir('branchs.bak')
|
126
|
+
FileUtils.mkdir('branchs.bak/branchs')
|
127
|
+
|
128
|
+
|
129
|
+
File.open("branchs.bak/branchs.json", "w+") do |aFile|
|
130
|
+
aFile.syswrite(@branchs.join("\n"))
|
131
|
+
end
|
132
|
+
|
133
|
+
logN '开始导出分支'
|
134
|
+
progress = 0.0
|
135
|
+
@branchs.each_index do|index|
|
136
|
+
branch = @branchs[index]
|
137
|
+
if index*1.0/@branchs.length - progress > 0.001
|
138
|
+
progress = index*1.0/@branchs.length
|
139
|
+
logP "当前进度:#{format("%0.2f",progress*100).to_f}%"
|
140
|
+
end
|
141
|
+
|
142
|
+
run_shell "git log --oneline #{branch}",true ,LOGNone do |out,err,status|
|
143
|
+
items = branch.split '/'
|
144
|
+
name = items[-1]
|
145
|
+
items.delete_at -1
|
146
|
+
FileUtils.mkdir_p "branchs.bak/branchs/#{items.join '/'}"
|
147
|
+
File.open("branchs.bak/branchs/#{branch}", "w+") do |aFile|
|
148
|
+
aFile.syswrite(out.join(""))
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
logN '开始导出tags'
|
154
|
+
run_shell 'git ls-remote -t --refs',false ,LOGNone do |out,err,status|
|
155
|
+
if status == 0
|
156
|
+
@tags = {}
|
157
|
+
out.each { |item|
|
158
|
+
items = item.split ' '
|
159
|
+
ref = items[0]
|
160
|
+
tag = items[1]
|
161
|
+
tag = tag['refs/tags/'.length..-1]
|
162
|
+
@tags[tag] = ref
|
163
|
+
}
|
164
|
+
|
165
|
+
end
|
166
|
+
end
|
167
|
+
File.open("branchs.bak/tags.json", "w+") do |aFile|
|
168
|
+
aFile.syswrite(@tags.to_json)
|
169
|
+
end
|
170
|
+
logN '导出完成'
|
171
|
+
|
172
|
+
end
|
173
|
+
def export_lfs
|
174
|
+
Dir.chdir(@source_root)
|
175
|
+
run_shell 'git lfs install',true ,true
|
176
|
+
run_shell 'git lfs fetch --all',false ,false ,1
|
177
|
+
|
178
|
+
end
|
179
|
+
def export_git
|
180
|
+
fetch_branch
|
181
|
+
Dir.chdir(@source_root)
|
182
|
+
progress = 0.0
|
183
|
+
run_shell "git remote",false ,true do |out,err,status|
|
184
|
+
@remote=out[0].strip
|
185
|
+
end
|
186
|
+
run_shell "git remote add tmp "+@target_git,true ,true
|
187
|
+
run_shell "git fetch #{@remote} -pf",true ,true
|
188
|
+
|
189
|
+
error_branch = []
|
190
|
+
success_branch = []
|
191
|
+
@branchs.each_index do|index|
|
192
|
+
branch = @branchs[index]
|
193
|
+
if index*1.0/@branchs.length - progress > 0.001
|
194
|
+
progress = index*1.0/@branchs.length
|
195
|
+
set_progress(progress*1000.to_int)
|
196
|
+
# logN "#{format("%0.2f",progress*100).to_f}%"
|
197
|
+
end
|
198
|
+
branch=branch[@remote.length+1..-1]
|
199
|
+
run_shell "git checkout -B #{branch} #{@remote}/#{branch} -f",true ,true do |out,err,status|
|
200
|
+
if status == 0 && out.length > 0
|
201
|
+
head=nil
|
202
|
+
run_shell "git rev-parse HEAD",true ,true do |out,err,status|
|
203
|
+
if status == 0
|
204
|
+
head = out[0].strip
|
205
|
+
end
|
206
|
+
end
|
207
|
+
need_update = true
|
208
|
+
if head
|
209
|
+
run_shell "git log tmp/#{branch} -1 --pretty=format:%H",true ,true do|out,err,status|
|
210
|
+
if out.length > 0 && out[0].index(head) == 0
|
211
|
+
need_update = false
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
if need_update
|
216
|
+
run_shell "git push -u tmp --no-verify",true ,true do|out,err,status|
|
217
|
+
if status == 0
|
218
|
+
success_branch.push branch
|
219
|
+
else
|
220
|
+
logE err.join('')
|
221
|
+
error_branch.push branch
|
222
|
+
end
|
223
|
+
end
|
224
|
+
else
|
225
|
+
logW 'jump branch:'+branch
|
226
|
+
end
|
227
|
+
|
228
|
+
else
|
229
|
+
logE err.join('')
|
230
|
+
error_branch.push branch
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
logN 'success branchs:\n'+success_branch.join('')
|
235
|
+
logN 'error branchs:\n'+error_branch.join('')
|
236
|
+
|
237
|
+
|
238
|
+
end
|
239
|
+
def run
|
240
|
+
if @type.nil? || @type == "local"
|
241
|
+
export_local
|
242
|
+
end
|
243
|
+
if @type.nil? || @type == "record"
|
244
|
+
export_record
|
245
|
+
end
|
246
|
+
if @type.nil? || @type == "lfs"
|
247
|
+
export_lfs
|
248
|
+
end
|
249
|
+
if @type=='git' && @target_git
|
250
|
+
export_git
|
251
|
+
end
|
252
|
+
|
253
|
+
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'claide'
|
2
|
+
require 'json'
|
3
|
+
require 'git-thin/command/action'
|
4
|
+
module GitThin
|
5
|
+
|
6
|
+
class Fetch < Thin
|
7
|
+
include Action
|
8
|
+
self.arguments = Action.arguments
|
9
|
+
self.summary = Action.summary 'fetch'
|
10
|
+
self.description = Action.description 'fetch'
|
11
|
+
|
12
|
+
def initialize(argv)
|
13
|
+
super
|
14
|
+
setup(argv,'fetch')
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,357 @@
|
|
1
|
+
module GitThin
|
2
|
+
class Hook < Thin
|
3
|
+
include GitThinUtils
|
4
|
+
self.description= <<-DESC
|
5
|
+
install|unstall,hooks for thin.
|
6
|
+
The names specifies the name of the hook, multiple names can use '|' in combination
|
7
|
+
|
8
|
+
push_count_checker: Check exception case for pushing too many COMMITS.
|
9
|
+
commit_lfs_checker: Check for large files that are not managed by LFS, or for incorrect usage of LFS.
|
10
|
+
commands: The optimization policy for git thin is automatically executed when the git command is executed
|
11
|
+
DESC
|
12
|
+
|
13
|
+
def self.arguments
|
14
|
+
[
|
15
|
+
CLAide::Argument.new('install|unstall', false )
|
16
|
+
]
|
17
|
+
end
|
18
|
+
self.summary= 'Action install|unstall hooks'
|
19
|
+
|
20
|
+
|
21
|
+
def self.options
|
22
|
+
[
|
23
|
+
['--source_root', 'Specify the warehouse address manually if necessary.'],
|
24
|
+
['--names', 'set hook name,include "push_count_checker|commit_lfs_checker|commands|all",defaule commands'],
|
25
|
+
['--commit_limit', 'Upper count limit checked in the prepush hook. default 5000'],
|
26
|
+
['--master_name', 'The name of the repository main branch,defalut is develop'],
|
27
|
+
['--file_size_limit', 'Upper file size limit checked in the prepush hook.default 2097152B (2MB)'],
|
28
|
+
].concat(super)
|
29
|
+
end
|
30
|
+
|
31
|
+
def commands_hook
|
32
|
+
<<-DESC
|
33
|
+
function git(){
|
34
|
+
o_git=`whereis git`
|
35
|
+
|
36
|
+
if [ -z "$o_git" ] || ! command -v git-thin >/dev/null 2>&1;then
|
37
|
+
echo 'git or git-thin command failed, finish hook'
|
38
|
+
unset -f git
|
39
|
+
git "$@"
|
40
|
+
else
|
41
|
+
if [[ "$1" == "checkout" ]] || [[ "$1" == "pull" ]] || [[ "$1" == "fetch" ]];then
|
42
|
+
git-thin "$@"
|
43
|
+
ret=$?
|
44
|
+
if [ $ret -gt 100 ];then
|
45
|
+
return $ret-100
|
46
|
+
elif [ $ret -ne 0 ];then
|
47
|
+
echo 'git-thin command error,retry with git'
|
48
|
+
$o_git "$@"
|
49
|
+
else
|
50
|
+
return $ret
|
51
|
+
fi
|
52
|
+
else
|
53
|
+
$o_git "$@"
|
54
|
+
fi
|
55
|
+
fi
|
56
|
+
return $?
|
57
|
+
}
|
58
|
+
export -f git > /dev/null
|
59
|
+
DESC
|
60
|
+
end
|
61
|
+
|
62
|
+
def pre_push_hook
|
63
|
+
<<-DESC
|
64
|
+
count=`git log --oneline #{@origin}/#{@master_name}..HEAD | wc -l`
|
65
|
+
if [ $count -gt #{@commit_limit} ];then
|
66
|
+
echo "commit count:${count} is greater than #{@commit_limit} (base #{@master_name}), please contact kyle.zhou"
|
67
|
+
exit 1
|
68
|
+
fi
|
69
|
+
DESC
|
70
|
+
end
|
71
|
+
|
72
|
+
def commit_msg_hook
|
73
|
+
%Q{
|
74
|
+
echo ''
|
75
|
+
echo '======start lfs check========'
|
76
|
+
root=`git rev-parse --show-toplevel`
|
77
|
+
START_LINE=`head -n1 $1`
|
78
|
+
if [[ -f $root/.git/MERGE_MSG ]] || [[ $START_LINE == "Merge"* ]];then
|
79
|
+
echo "Current in merging,skip lfs check"
|
80
|
+
exit 0
|
81
|
+
fi
|
82
|
+
map(){
|
83
|
+
function_name=$1
|
84
|
+
shift
|
85
|
+
while read line
|
86
|
+
do
|
87
|
+
$function_name "$line" "$@"
|
88
|
+
done
|
89
|
+
}
|
90
|
+
|
91
|
+
white_list=(mm m cpp c cc h hpp java cs cjs js css txt doc docx pdf ppt pptx xls htm html shtm shtml jsp xjsp jspf jsf jsx jspx md pl pm sass sh zsh bash rb json xml yml yaml cjsx uml es6 mjs ejs bat cgi cmd csv jam log opts mpmrc nvmrc vue xhtml xsl xslt elt)
|
92
|
+
OLDIFS=$IFS
|
93
|
+
IFS=$'\n'
|
94
|
+
lfs_files=`git lfs ls-files`
|
95
|
+
lfs_files=($lfs_files)
|
96
|
+
IFS='*'
|
97
|
+
for (( i = 0; i < ${#lfs_files[@]}; i++ )); do
|
98
|
+
file_item=(${lfs_files[i]})
|
99
|
+
lfs_files[i]=${file_item[1]}
|
100
|
+
done
|
101
|
+
export has_gitattributes=0
|
102
|
+
check_file(){
|
103
|
+
echo $1
|
104
|
+
if [[ $1 =~ 'gitattributes' ]];then
|
105
|
+
export has_gitattributes=1
|
106
|
+
echo "has_gitattributes:$has_gitattributes"
|
107
|
+
fi
|
108
|
+
file_name=$1
|
109
|
+
file_ext=${file_name##*.}
|
110
|
+
file_ext=$(echo "$file_ext" | tr [A-Z] [a-z])
|
111
|
+
for item in ${white_list[@]};do
|
112
|
+
if [ "$file_ext" = "$item" ];then
|
113
|
+
return
|
114
|
+
fi
|
115
|
+
done
|
116
|
+
|
117
|
+
for (( i = 0; i < ${#lfs_files[@]}; i++ )); do
|
118
|
+
if [[ "${lfs_files[i]}" == " $file_name" ]];then
|
119
|
+
echo "file ${file_name} already in lfs, pass"
|
120
|
+
return
|
121
|
+
fi
|
122
|
+
done
|
123
|
+
|
124
|
+
if [ -f "$file_name" ];then
|
125
|
+
size=`ls -l $file_name | awk '{ print $5 }'`
|
126
|
+
if [ "$size" -gt #{@file_size_limit} ];then
|
127
|
+
echo "修改的非代码文件超过#{@file_size_limit}KB,请使用git lfs管理,文件名称:$file_name"
|
128
|
+
exit 1
|
129
|
+
fi
|
130
|
+
fi
|
131
|
+
}
|
132
|
+
|
133
|
+
git diff --name-only --staged | map check_file
|
134
|
+
if [ $? -ne 0 ];then
|
135
|
+
echo "lfs check failed"
|
136
|
+
exit 1
|
137
|
+
fi
|
138
|
+
IFS=$OLDIFS
|
139
|
+
if [ `git diff --name-only | grep '.gitattributes' -c` -gt 0 ];then
|
140
|
+
echo '存在未提交的.gitattributes文件,请主动add改文件。如果确认不需要则请重置该文件'
|
141
|
+
echo "lfs check failed"
|
142
|
+
exit 1
|
143
|
+
fi
|
144
|
+
echo "lfs check pass"
|
145
|
+
echo ""
|
146
|
+
}
|
147
|
+
end
|
148
|
+
def check_name
|
149
|
+
pass = true
|
150
|
+
for name in @names
|
151
|
+
name = name.downcase
|
152
|
+
if !@support_names.include?(name) && name.downcase != 'all'
|
153
|
+
logE "name [#{name}] is not supported"
|
154
|
+
pass = false
|
155
|
+
end
|
156
|
+
end
|
157
|
+
if false
|
158
|
+
@names = []
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def initialize(argv)
|
163
|
+
super
|
164
|
+
@pwd = Dir.pwd
|
165
|
+
if argv.arguments.length > 0 &&( argv.arguments[0] == 'install' || argv.arguments[0] == 'uninstall')
|
166
|
+
@action = argv.shift_argument
|
167
|
+
end
|
168
|
+
@source_root = argv.option('source_root')
|
169
|
+
@file_size_limit = argv.option('file_size_limit','2048')
|
170
|
+
@commit_limit = argv.option('commit_limit','5000')
|
171
|
+
@master_name = argv.option('master_name','develop')
|
172
|
+
@names = argv.option('names','commands')
|
173
|
+
@names = @names.split('|')
|
174
|
+
@names = @names.map { |item|item.downcase }
|
175
|
+
@support_names = ['push_count_checker','commit_lfs_checker','commands']
|
176
|
+
if @names.include? 'all'
|
177
|
+
@names = @support_names
|
178
|
+
end
|
179
|
+
check_name
|
180
|
+
|
181
|
+
if not @source_root
|
182
|
+
run_shell 'git rev-parse --show-toplevel',false ,LOGNone do |out,err,status|
|
183
|
+
if status == 0
|
184
|
+
@source_root = out[0].strip
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
if not File.exist? @source_root+'/.git'
|
189
|
+
UI.puts "git repository not found"
|
190
|
+
exit 1
|
191
|
+
end
|
192
|
+
else
|
193
|
+
if @source_root[-1] == '/'
|
194
|
+
@source_root = @source_root[0..-2 ]
|
195
|
+
end
|
196
|
+
end
|
197
|
+
if not Dir.exist? @source_root
|
198
|
+
@source_root = nil
|
199
|
+
return
|
200
|
+
end
|
201
|
+
@hook_path = "#{@source_root}/.git/hooks"
|
202
|
+
if not Dir.exist? @hook_path
|
203
|
+
FileUtils.mkdir_p @hook_path
|
204
|
+
end
|
205
|
+
@start_flag = '>>>>>>>>>>>>>>>>>>>'
|
206
|
+
@end_flag = '<<<<<<<<<<<<<<<<<<<'
|
207
|
+
end
|
208
|
+
|
209
|
+
def validate!
|
210
|
+
super
|
211
|
+
help! 'validate SOURCE_ROOT is required' unless @source_root
|
212
|
+
help! 'action must install/uninstall' unless @action
|
213
|
+
help! 'validate names is required' unless @names.length
|
214
|
+
|
215
|
+
end
|
216
|
+
|
217
|
+
def prune_hook(name,content)
|
218
|
+
start_flag = '# '+@start_flag+' git thin '+name+@start_flag
|
219
|
+
end_flag = '# '+@end_flag+' git thin '+name+@end_flag
|
220
|
+
find_start = false
|
221
|
+
find_end = false
|
222
|
+
lines = []
|
223
|
+
content.each do |line|
|
224
|
+
if line.index(start_flag)
|
225
|
+
find_start = true
|
226
|
+
end
|
227
|
+
if line.index(end_flag) && find_start
|
228
|
+
find_end = true
|
229
|
+
end
|
230
|
+
|
231
|
+
if !find_start && !find_end
|
232
|
+
lines.push line
|
233
|
+
end
|
234
|
+
|
235
|
+
if find_start && find_end
|
236
|
+
find_start = find_end = false
|
237
|
+
end
|
238
|
+
end
|
239
|
+
return lines
|
240
|
+
end
|
241
|
+
|
242
|
+
def append_hook(name,content,hook)
|
243
|
+
start_flag = '# '+@start_flag+' git thin '+name+@start_flag+"\n"
|
244
|
+
end_flag = '# '+@end_flag+' git thin '+name+@end_flag+"\n"
|
245
|
+
content += "\n\n #{start_flag}\n"
|
246
|
+
content += hook
|
247
|
+
content += "\n #{end_flag}"
|
248
|
+
|
249
|
+
end
|
250
|
+
def uninstall_hook(path,name)
|
251
|
+
origin = []
|
252
|
+
if File.exist? path
|
253
|
+
File.open(path, "r") do |aFile|
|
254
|
+
origin = aFile.readlines
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
prune = prune_hook(name,origin)
|
259
|
+
content = prune.join("")
|
260
|
+
File.open(path, "w+") do |aFile|
|
261
|
+
aFile.write content
|
262
|
+
end
|
263
|
+
if prune.length != origin.length
|
264
|
+
logN 'success uninstall hook:'+name+' to path:'+path
|
265
|
+
end
|
266
|
+
end
|
267
|
+
def install_hook(path,name,hook)
|
268
|
+
origin = []
|
269
|
+
if File.exist? path
|
270
|
+
File.open(path, "r") do |aFile|
|
271
|
+
origin = aFile.readlines
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
prune = prune_hook(name,origin).join("")
|
276
|
+
content = append_hook name,prune,hook
|
277
|
+
File.open(path, "w+") do |aFile|
|
278
|
+
aFile.write content
|
279
|
+
end
|
280
|
+
logN 'success install hook:'+name+' to path:'+path
|
281
|
+
end
|
282
|
+
|
283
|
+
def install
|
284
|
+
if @names.include? 'push_count_checker'
|
285
|
+
Dir.chdir @source_root
|
286
|
+
find_branch = false
|
287
|
+
run_shell 'git branch -r',true ,true do |outs,errs,status|
|
288
|
+
if status == 0
|
289
|
+
for out in outs
|
290
|
+
items = out.strip.split '/'
|
291
|
+
if items.length == 2 && items[1] == @master_name
|
292
|
+
find_branch = true
|
293
|
+
break
|
294
|
+
end
|
295
|
+
end
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
299
|
+
run_shell 'git remote',true ,true do |outs,errs,status|
|
300
|
+
if status == 0 && outs.length > 0
|
301
|
+
@origin = outs[0]
|
302
|
+
else
|
303
|
+
@origin = 'origin'
|
304
|
+
end
|
305
|
+
end
|
306
|
+
if !find_branch
|
307
|
+
logE "install push_count_checker hook error:the main branch [#{@master_name}] is not exist,please specify an appropriate parameter for master_name"
|
308
|
+
exit 1
|
309
|
+
end
|
310
|
+
|
311
|
+
install_hook @hook_path+'/pre-push','push_count_checker',pre_push_hook
|
312
|
+
end
|
313
|
+
if @names.include? 'commit_lfs_checker'
|
314
|
+
install_hook @hook_path+'/commit-msg','commit_lfs_checker',commit_msg_hook
|
315
|
+
end
|
316
|
+
|
317
|
+
if @names.include? 'commands'
|
318
|
+
profile = Dir.home+"/.bash_profile"
|
319
|
+
install_hook profile,'commands_hook',commands_hook
|
320
|
+
run_shell"cat #{profile}>tmp && source tmp && rm tmp",true ,LOGPRUNE
|
321
|
+
logN 'This will take effect after restarting the computer'
|
322
|
+
end
|
323
|
+
|
324
|
+
end
|
325
|
+
|
326
|
+
def uninstall
|
327
|
+
if @names.include? 'push_count_checker'
|
328
|
+
uninstall_hook @hook_path+'/pre-push','push_count_checker'
|
329
|
+
end
|
330
|
+
if @names.include? 'commit_lfs_checker'
|
331
|
+
uninstall_hook @hook_path+'/commit-msg','commit_lfs_checker'
|
332
|
+
end
|
333
|
+
if @names.include? 'commands'
|
334
|
+
profile = Dir.home+"/.bash_profile"
|
335
|
+
uninstall_hook profile,'commands_hook'
|
336
|
+
run_shell'echo "unset -f git" >tmp && source tmp && rm tmp',true ,LOGPRUNE
|
337
|
+
logN 'This will take effect after restarting the computer'
|
338
|
+
end
|
339
|
+
logN 'finish uninstall'
|
340
|
+
end
|
341
|
+
|
342
|
+
def run_config
|
343
|
+
values=[]
|
344
|
+
|
345
|
+
return values
|
346
|
+
end
|
347
|
+
|
348
|
+
def run
|
349
|
+
Dir.chdir @source_root
|
350
|
+
if @action == 'install'
|
351
|
+
install
|
352
|
+
elsif @action =='uninstall'
|
353
|
+
uninstall
|
354
|
+
end
|
355
|
+
end
|
356
|
+
end
|
357
|
+
end
|