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.
@@ -0,0 +1,18 @@
1
+ require 'claide'
2
+ require 'json'
3
+ require 'git-thin/command/action'
4
+
5
+ module GitThin
6
+
7
+ class Pull < Thin
8
+ include Action
9
+ self.arguments = Action.arguments
10
+ self.summary = Action.summary 'pull'
11
+ self.description = Action.description 'pull'
12
+
13
+ def initialize(argv)
14
+ super
15
+ setup(argv,'pull')
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,326 @@
1
+ require 'claide'
2
+ require 'json'
3
+ # require 'git-thin/utils/utils'
4
+
5
+ module GitThin
6
+ class ThinConfig
7
+ include GitThinUtils
8
+ DEFAULT = 'default'.freeze
9
+ def initialize(name,keys)
10
+ @name = name
11
+ @keys = keys
12
+ @config = {}
13
+ end
14
+
15
+ def name
16
+ return @name
17
+ end
18
+ def keys
19
+ return @keys
20
+ end
21
+ def setValue(value,key = nil )
22
+ if key
23
+ if @keys.include? key
24
+ @config[key] = value
25
+ end
26
+ else
27
+ for key in @keys
28
+ @config[key] = value
29
+ end
30
+ end
31
+ end
32
+
33
+ def getValue(key = nil )
34
+ if key
35
+ value = @config[key]
36
+ if value.nil? && key == 'path'
37
+ value = @config['lfs']
38
+ end
39
+ return value
40
+ else
41
+ return @config.values
42
+ end
43
+ end
44
+
45
+ def self.prase_config(configs)
46
+ ret_configs = {}
47
+ for config in configs
48
+ items = config.split('=')
49
+ if items.length != 2
50
+ logE 'error thin config:'+config
51
+ next
52
+ end
53
+ name = items[0].strip.downcase
54
+ value = items[1].strip.split(',')
55
+ name_items = name.split('.')
56
+ if name_items.length <= 1
57
+ logE 'error thin config:'+config
58
+ next
59
+ end
60
+ if name_items[0] != 'thin'
61
+ # logE 'error thin config:'+config
62
+ next
63
+ end
64
+
65
+ config_name = name_items[1]
66
+ config = ret_configs[config_name]
67
+ if not config
68
+ config = ThinConfig.new config_name,['lfs','path']
69
+ ret_configs[config_name] = config
70
+ end
71
+
72
+ if name_items.length > 2
73
+ config_key = name_items[2]
74
+ config.setValue(value,config_key)
75
+ else
76
+ config.setValue value
77
+ end
78
+ end
79
+
80
+ return ret_configs
81
+ end
82
+
83
+ def self.prase_pwd_config(configs,source_root,pwd)
84
+ types = []
85
+ if pwd.index(source_root) == 0
86
+ # 在git 目录中,判断是否命中path路径
87
+ length = source_root.length
88
+ sub = pwd[length+1..-1]
89
+ if sub
90
+ for key in configs.keys
91
+ paths = configs[key].getValue('path')
92
+ for path in paths
93
+ if sub.index(path) == 0
94
+ types.push key.downcase
95
+ end
96
+ end
97
+ end
98
+ end
99
+ else
100
+ logW 'You are out of the repo'
101
+ end
102
+ return types
103
+ end
104
+
105
+ def self.prase_type_config(argv,configs,source_root=nil ,pwd=nil )
106
+ types = []
107
+ if argv.arguments.length > 0 && argv.arguments[0].index('-')!=0
108
+ first_args = argv.arguments[0].split '|'
109
+ need_shift = false
110
+ for arg in first_args
111
+ if configs.keys.include? arg.downcase
112
+ types.push arg.downcase
113
+ need_shift = true
114
+ end
115
+ end
116
+ if need_shift
117
+ argv.shift_argument
118
+ end
119
+ elsif pwd && source_root
120
+ types = types.concat prase_pwd_config(configs,source_root,pwd)
121
+ end
122
+ if types.length == 0
123
+ types.push(DEFAULT)
124
+ end
125
+ return types
126
+ end
127
+
128
+ end
129
+ class Config < Thin
130
+ include GitThinUtils
131
+ self.summary = 'Config lfs with .thinconfig'
132
+
133
+ self.arguments = [
134
+ CLAide::Argument.new('TYPE', false )
135
+ ]
136
+ self.description = <<-DESC
137
+ According to .thinconfig, configure the platform directory to LFS
138
+ DESC
139
+ def self.options
140
+ [
141
+ ['--source_root', 'Specify the warehouse address manually if necessary.'],
142
+ ['--store', 'Store config to lfs'],
143
+ ['--list', 'List the configs supported by the locally repository, (configured by.thinconfig) '],
144
+ ['--current', 'Displays the current configuration'],
145
+ ['--reset', 'Reset config to thin and lfs'],
146
+ ['--check', 'Check the integrity of the config'],
147
+ ].concat(super)
148
+ end
149
+ def initialize(argv)
150
+ super
151
+ @pwd = Dir.pwd
152
+ @types = []
153
+ @configs = {}
154
+ @source_root = argv.option('source_root')
155
+ @store = argv.flag?('store')
156
+ @list = argv.flag?('list')
157
+ @current = argv.flag?('current')
158
+ @reset = argv.flag?('reset')
159
+ @check = argv.flag?('check')
160
+
161
+ if not @source_root
162
+ run_shell 'git rev-parse --show-toplevel',false ,LOGNone do |out,err,status|
163
+ if status == 0
164
+ @source_root = out[0].strip
165
+ end
166
+ end
167
+
168
+ if not File.exist? @source_root+'/.git'
169
+ UI.puts "git repository not found"
170
+ exit 1
171
+ end
172
+ else
173
+ if @source_root[-1] == '/'
174
+ @source_root = @source_root[0..-2 ]
175
+ end
176
+ end
177
+ if not Dir.exist? @source_root
178
+ @source_root = nil
179
+ return
180
+ end
181
+ if FileTest.exist? @source_root+'/.thinconfig'
182
+ run_shell "git config -lf #{@source_root}/.thinconfig",true ,true do |out,err,status|
183
+ @configs = ThinConfig.prase_config out
184
+ end
185
+ end
186
+ @types =ThinConfig.prase_type_config argv,@configs
187
+ end
188
+
189
+ def validate!
190
+ super
191
+ help! 'validate SOURCE_ROOT is required' unless @source_root
192
+ end
193
+
194
+ def git_config
195
+ if not @git_configs
196
+ run_shell 'git config -l',true ,true do |outs,errs,status|
197
+ @git_configs = ThinConfig.prase_config outs
198
+ end
199
+ end
200
+ end
201
+ def run_config
202
+ values=[]
203
+ for type in @types
204
+ config = @configs[type]
205
+ if type == ThinConfig::DEFAULT
206
+ git_config
207
+ config = @git_configs[ThinConfig::DEFAULT]
208
+ end
209
+ if config
210
+ values.push config.getValue('lfs')
211
+ end
212
+ end
213
+ if values.length > 0
214
+ run_shell "git config thin.#{ThinConfig::DEFAULT} "+values.join(','),true ,true
215
+ if @store
216
+ run_shell "git config lfs.fetchinclude "+values.join(',')
217
+ end
218
+ end
219
+ return values
220
+ end
221
+
222
+ def list
223
+ logN 'List the configs supported by the locally repository: '
224
+ git_config
225
+ config = @git_configs[ThinConfig::DEFAULT]
226
+ if config
227
+ log = "name:#{config.name}"
228
+ for key in config.keys
229
+ log += " #{key}:#{config.getValue key}"
230
+ end
231
+ logN log
232
+ end
233
+ for config in @configs.values
234
+ log = "name:#{config.name}"
235
+ for key in config.keys
236
+ log += " #{key}:#{config.getValue key}"
237
+ end
238
+ logN log
239
+ end
240
+ end
241
+ def reset
242
+ run_shell "git config --unset thin.#{ThinConfig::DEFAULT} ",true ,true
243
+ run_shell "git config --unset lfs.fetchinclude ",true ,true
244
+ end
245
+ def current
246
+
247
+ types = ThinConfig::prase_pwd_config(@configs,@source_root,@pwd)
248
+ if types.length == 0
249
+ types.push ThinConfig::DEFAULT
250
+ end
251
+ for type in types
252
+ config = @configs[type]
253
+ if type == ThinConfig::DEFAULT
254
+ git_config
255
+ config = @git_configs[ThinConfig::DEFAULT]
256
+ end
257
+ if config
258
+ logN "name:#{type} lfs:#{config.getValue('lfs')}"
259
+ end
260
+ end
261
+ end
262
+
263
+ def match_config(match_file)
264
+ for config in @configs.values
265
+ lfs = config.getValue 'lfs'
266
+ if lfs
267
+ lfs = lfs.map do|file|
268
+ file.strip
269
+ end
270
+ for lf in lfs
271
+ if match_file.index(lf) == 0
272
+ return config
273
+ end
274
+ end
275
+ end
276
+ end
277
+ return nil
278
+ end
279
+ def check
280
+ lfs_files = []
281
+ run_shell "git lfs ls-files",false ,LOGNone do |outs,errs,status|
282
+ if status
283
+ for line in outs
284
+ line[13..-2]
285
+ lfs_files.push line[13..-2]
286
+ end
287
+ end
288
+ end
289
+ unmatch_files = []
290
+ for lfs_file in lfs_files
291
+
292
+ if match_config(lfs_file).nil?
293
+ unmatch_files.push lfs_file
294
+ end
295
+ end
296
+ if unmatch_files.length > 0
297
+ logN 'The following LFS files are not configured:'
298
+ for unmatch_file in unmatch_files
299
+ logW unmatch_file
300
+ end
301
+ else
302
+ logN 'All LFS files are configured'
303
+ end
304
+ end
305
+ def run
306
+ Dir.chdir @source_root
307
+ if @list
308
+ list
309
+ elsif @reset
310
+ reset
311
+ elsif @current
312
+ current
313
+ elsif @check
314
+ check
315
+ else
316
+ values = run_config
317
+ if values.length > 0
318
+ logN "git config thin.#{ThinConfig::DEFAULT} "+values.join(",")
319
+ else
320
+ logW "not match analyze config"
321
+ end
322
+ end
323
+ Dir.chdir @pwd
324
+ end
325
+ end
326
+ end
@@ -0,0 +1,3 @@
1
+ module GitThin
2
+ VERSION = "0.0.13"
3
+ end
@@ -0,0 +1,133 @@
1
+ require 'open3'
2
+ require 'io/console'
3
+ module GitThinUtils
4
+
5
+ LOGC= 1<<0
6
+ LOGN= 1<<1
7
+ LOGPRUNE = 1<<2
8
+ LOGNone= 0
9
+ LOGA = LOGC|LOGN
10
+
11
+
12
+ def set_progress(index, char = '*')
13
+ print (char * (index / 2.5).floor).ljust(40, " "), " #{index}%\r"
14
+ end
15
+
16
+ def run_shell(command,force = 0,log_type = LOGA,retryCount = 0 )
17
+ if log_type === false
18
+ log_type = LOGPRUNE
19
+ elsif log_type === true
20
+ log_type = LOGNone
21
+ end
22
+ if (log_type & LOGC ) == LOGC
23
+ logC command+"\n",(log_type & LOGPRUNE )!=LOGPRUNE
24
+ end
25
+ stdin, stdout, stderr,wait_thr = Open3.popen3(command)
26
+ pid = wait_thr[:pid]
27
+ out_lines = []
28
+ error_lines = []
29
+ stdout.sync = true
30
+ stderr.sync = true
31
+ out = Thread.new do
32
+ # while !stdout.eof?
33
+ # c = stdout.getc
34
+ # putc c
35
+ # stdout.flush
36
+ # end
37
+ stdout.each do |line|
38
+ out_lines.push line
39
+ if log_type && log_type > LOGC
40
+ logN line,(log_type & LOGPRUNE )!=LOGPRUNE
41
+ end
42
+ end
43
+ end
44
+ err = Thread.new do
45
+ # while !stderr.eof?
46
+ # c = stderr.getc
47
+ # putc c
48
+ # stderr.flush
49
+ # end
50
+ stderr.each do |line|
51
+ error_lines.push line
52
+
53
+ if log_type
54
+ logW line,(log_type & LOGPRUNE )!=LOGPRUNE
55
+ end
56
+ end
57
+ end
58
+ out.join
59
+ err.join
60
+
61
+ stderr.close
62
+ stdin.close
63
+ stdout.close
64
+ status = wait_thr.value
65
+ if status.exitstatus != 0
66
+ if !force
67
+ if retryCount > 0
68
+ sleep 1
69
+ run_shell command,force,log_type,retryCount-1
70
+ return
71
+ else
72
+ logE error_lines,(log_type & LOGPRUNE )
73
+
74
+ exit 1
75
+ end
76
+ end
77
+ end
78
+ unless block_given?
79
+
80
+ return [out_lines,error_lines,status.exitstatus]
81
+ else
82
+ yield out_lines, error_lines,status.exitstatus
83
+ end
84
+ end
85
+
86
+ def print_console(str)
87
+ run_shell "echo #{str}"
88
+ end
89
+
90
+ def logInner(color_code,text)
91
+ clolr="\033[#{color_code}m"
92
+ nc="\033[0m"
93
+ puts "#{clolr}#{text}#{nc}"
94
+ end
95
+
96
+ # 打印不同级别的 log。根据级别不同,样式(颜色)不同
97
+ def logE(text,note = true )
98
+ if note
99
+ logInner '31',"[ERROR] !!#{text}"
100
+ else
101
+ print(text)
102
+ end
103
+ end
104
+
105
+ def logP(text)
106
+ print("\r")
107
+ print(text)
108
+ STDOUT.flush
109
+ end
110
+ def logW(text,note = true )
111
+ if note
112
+ logInner '33',"[WARNING] #{text}"
113
+ else
114
+ print(text)
115
+ end
116
+ end
117
+
118
+ def logN(text,note = true)
119
+ if note
120
+ logInner '32',"[NOTE] #{text}"
121
+ else
122
+ print(text)
123
+ end
124
+ end
125
+
126
+ def logC(text,note = true)
127
+ if note
128
+ logInner '34',"[COMMAND] #{text}"
129
+ else
130
+ print(text)
131
+ end
132
+ end
133
+ end