stg 0.1.2 → 0.1.5
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 +4 -4
- data/lib/{actions.rb → stg/actions.rb} +245 -64
- data/lib/{differencing.rb → stg/differencing.rb} +6 -5
- data/lib/{help.rb → stg/help.rb} +3 -3
- data/lib/{utils.rb → stg/utils.rb} +14 -0
- data/lib/stg/version.rb +3 -0
- data/lib/stg.rb +67 -40
- metadata +7 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0f993bbd2bd4575637beb24485c54a88a2679551000551df0f1b1a552249922f
|
|
4
|
+
data.tar.gz: cca41c04c1ab146a16055debbf6364081993d4afb647222865a219d88d9a40bb
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 745cc975c54fc9e1449a514c711ca2a3ab98df951deb554b6e37de8f5e01ddbacf4e2001a20d0cd512d4ed5411291b4a213e0293928878b805ee5395acbd02c7
|
|
7
|
+
data.tar.gz: 9afe52e540571bd3330743229d8e267150d243a9e28a815a503841199979c1a156434ad07b4a4d828a3f5db042710a3a5756999c8bf525a10aafa17f3dd0ff26
|
|
@@ -9,6 +9,22 @@ module Actions
|
|
|
9
9
|
include DiffCalc
|
|
10
10
|
|
|
11
11
|
def p_initialize
|
|
12
|
+
begin
|
|
13
|
+
OptionParser.new do |opts|
|
|
14
|
+
opts.banner = 'Usage: stg init'
|
|
15
|
+
|
|
16
|
+
opts.on_tail('-h', '--help', 'Show this help') do
|
|
17
|
+
puts opts
|
|
18
|
+
exit
|
|
19
|
+
end
|
|
20
|
+
end.parse!
|
|
21
|
+
rescue OptionParser::ParseError => e
|
|
22
|
+
puts e.message
|
|
23
|
+
puts 'Usage: stg init'
|
|
24
|
+
puts ' -h, --help Show this help'
|
|
25
|
+
exit 1
|
|
26
|
+
end
|
|
27
|
+
|
|
12
28
|
# Check if already initialized
|
|
13
29
|
if File.exist?('.stolen-git')
|
|
14
30
|
if confirm?('An instance of stolen-git is already up here do you want to replace it')
|
|
@@ -41,6 +57,7 @@ module Actions
|
|
|
41
57
|
|
|
42
58
|
# main files
|
|
43
59
|
File.write('.stolen-git/project_info.json', {})
|
|
60
|
+
File.write('.stg-ignore', JSON.pretty_generate(['.*/']))
|
|
44
61
|
File.write('.stolen-git/commits.json', JSON.pretty_generate({ commits: [] }))
|
|
45
62
|
File.write('.stolen-git/index.json', {})
|
|
46
63
|
|
|
@@ -54,16 +71,36 @@ module Actions
|
|
|
54
71
|
end
|
|
55
72
|
|
|
56
73
|
def stage
|
|
74
|
+
begin
|
|
75
|
+
OptionParser.new do |opts|
|
|
76
|
+
opts.banner = 'Usage: stg stage <file> [files...]'
|
|
77
|
+
|
|
78
|
+
opts.on_tail('-h', '--help', 'Show this help') do
|
|
79
|
+
puts opts
|
|
80
|
+
exit
|
|
81
|
+
end
|
|
82
|
+
end.parse!
|
|
83
|
+
rescue OptionParser::ParseError => e
|
|
84
|
+
puts e.message
|
|
85
|
+
puts 'Usage: stg stage <file> [files...]'
|
|
86
|
+
puts ' -h, --help Show this help'
|
|
87
|
+
exit 1
|
|
88
|
+
end
|
|
89
|
+
|
|
57
90
|
inp = ARGV
|
|
58
91
|
|
|
59
92
|
if inp.empty?
|
|
60
|
-
puts 'Usage: stg stage <
|
|
93
|
+
puts 'Usage: stg stage <file> [files...]'
|
|
61
94
|
return
|
|
62
95
|
end
|
|
63
96
|
|
|
64
|
-
index =
|
|
65
|
-
|
|
66
|
-
|
|
97
|
+
index = read_json('.stolen-git/index.json')
|
|
98
|
+
ignore = read_json('.stg-ignore')
|
|
99
|
+
stage_file = lambda do |file_path|
|
|
100
|
+
ignore&.each do |ignore_pattern|
|
|
101
|
+
return if File.fnmatch(ignore_pattern, file_path)
|
|
102
|
+
end
|
|
103
|
+
file_path = clean_path(file_path)
|
|
67
104
|
file_hash = get_file_hash(file_path)
|
|
68
105
|
file_content = File.read(file_path)
|
|
69
106
|
|
|
@@ -78,30 +115,31 @@ module Actions
|
|
|
78
115
|
index[file_path]['hash'] = file_hash
|
|
79
116
|
end
|
|
80
117
|
|
|
81
|
-
|
|
118
|
+
stage_directory = lambda do |dir_path|
|
|
119
|
+
dir_path = clean_path(dir_path)
|
|
82
120
|
Dir.children(dir_path).each do |entry|
|
|
83
|
-
|
|
121
|
+
next if entry == '.stolen-git'
|
|
122
|
+
|
|
84
123
|
path = File.join(dir_path, entry)
|
|
85
124
|
if File.file?(path)
|
|
86
|
-
|
|
87
|
-
stage_file(path)
|
|
125
|
+
stage_file.call(path)
|
|
88
126
|
else
|
|
89
|
-
|
|
90
|
-
stage_directory(path)
|
|
127
|
+
stage_directory.call(path)
|
|
91
128
|
end
|
|
92
129
|
end
|
|
93
130
|
end
|
|
94
131
|
|
|
95
132
|
inp.each do |inp_path|
|
|
133
|
+
inp_path = clean_path(inp_path)
|
|
96
134
|
unless File.exist? inp_path
|
|
97
135
|
puts "#{inp_path} doesn't exist"
|
|
98
136
|
next
|
|
99
137
|
end
|
|
100
138
|
|
|
101
139
|
if File.file?(inp_path)
|
|
102
|
-
stage_file(inp_path)
|
|
140
|
+
stage_file.call(inp_path)
|
|
103
141
|
elsif File.directory? inp_path
|
|
104
|
-
stage_directory(inp_path)
|
|
142
|
+
stage_directory.call(inp_path)
|
|
105
143
|
else
|
|
106
144
|
puts "Error logging #{inp_path}. It's neither a file or a directory"
|
|
107
145
|
end
|
|
@@ -114,17 +152,31 @@ module Actions
|
|
|
114
152
|
options = { name: '', description: '' }
|
|
115
153
|
|
|
116
154
|
# Getting commit name & description
|
|
117
|
-
|
|
118
|
-
|
|
155
|
+
begin
|
|
156
|
+
OptionParser.new do |opts|
|
|
157
|
+
opts.banner = 'Usage: stg commit [options]'
|
|
119
158
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
159
|
+
opts.on('-n', '--name NAME', 'Add a commit name') do |name|
|
|
160
|
+
options[:name] = name
|
|
161
|
+
end
|
|
123
162
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
163
|
+
opts.on('-d', '--description DESCRIPTION', 'Add a commit description') do |description|
|
|
164
|
+
options[:description] = description
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
opts.on_tail('-h', '--help', 'Show this help') do
|
|
168
|
+
puts opts
|
|
169
|
+
exit
|
|
170
|
+
end
|
|
171
|
+
end.parse!
|
|
172
|
+
rescue OptionParser::ParseError => e
|
|
173
|
+
puts e.message
|
|
174
|
+
puts 'Usage: stg commit [options]'
|
|
175
|
+
puts ' -n, --name NAME Add a commit name'
|
|
176
|
+
puts ' -d, --description DESCRIPTION Add a commit description'
|
|
177
|
+
puts ' -h, --help Show this help'
|
|
178
|
+
exit 1
|
|
179
|
+
end
|
|
128
180
|
|
|
129
181
|
options[:name] = ask('Add a commit name: ') if options[:name].empty?
|
|
130
182
|
|
|
@@ -142,35 +194,57 @@ module Actions
|
|
|
142
194
|
parent_commit = branch_content['commit_pointer']
|
|
143
195
|
|
|
144
196
|
# Getting differences to last commit
|
|
145
|
-
|
|
146
197
|
no_insertions = 0
|
|
147
198
|
no_deletions = 0
|
|
148
199
|
no_file_changed = 0
|
|
200
|
+
|
|
149
201
|
commit_diff = {}
|
|
150
202
|
|
|
151
203
|
getting_diff = lambda do |entries|
|
|
152
|
-
|
|
204
|
+
if entries.nil?
|
|
205
|
+
index.each do |key, value|
|
|
206
|
+
key = clean_path(key)
|
|
207
|
+
new_entry_content = File.read(".stolen-git/storage/blobs/#{value['hash']}").lines.to_a
|
|
208
|
+
compute_diff([], new_entry_content)
|
|
209
|
+
diff = build_sequences
|
|
210
|
+
no_insertions += diff[:insertions]
|
|
211
|
+
no_deletions += diff[:deletions]
|
|
212
|
+
no_file_changed += 1
|
|
213
|
+
commit_diff[key] = diff
|
|
214
|
+
end
|
|
215
|
+
else
|
|
216
|
+
parent_map = entries.to_h { |e| [e['path'], e['hash']] }
|
|
153
217
|
|
|
154
|
-
|
|
155
|
-
|
|
218
|
+
index.each do |key, value|
|
|
219
|
+
key = clean_path(key)
|
|
156
220
|
new_hash = value['hash']
|
|
157
|
-
old_hash =
|
|
158
|
-
|
|
159
|
-
|
|
221
|
+
old_hash = parent_map[key]
|
|
222
|
+
|
|
223
|
+
if old_hash
|
|
224
|
+
next if old_hash == new_hash
|
|
225
|
+
|
|
226
|
+
entry_content = File.read(".stolen-git/storage/blobs/#{old_hash}").lines.to_a
|
|
227
|
+
new_entry_content = File.read(".stolen-git/storage/blobs/#{new_hash}").lines.to_a
|
|
228
|
+
compute_diff(entry_content, new_entry_content)
|
|
229
|
+
else
|
|
230
|
+
new_entry_content = File.read(".stolen-git/storage/blobs/#{new_hash}").lines.to_a
|
|
231
|
+
compute_diff([], new_entry_content)
|
|
232
|
+
end
|
|
160
233
|
|
|
161
|
-
entry_content = File.read(".stolen-git/storage/blobs/#{old_hash}").lines.to_a
|
|
162
|
-
new_entry_content = File.read(".stolen-git/storage/blobs/#{new_hash}").lines.to_a
|
|
163
|
-
compute_diff(entry_content, new_entry_content)
|
|
164
234
|
diff = build_sequences
|
|
165
235
|
no_insertions += diff[:insertions]
|
|
166
236
|
no_deletions += diff[:deletions]
|
|
167
237
|
no_file_changed += 1
|
|
168
238
|
commit_diff[key] = diff
|
|
169
|
-
|
|
170
|
-
new_entry_content = File.read(".stolen-git/storage/blobs/#{value['hash']}").lines.to_a
|
|
171
|
-
compute_diff('', new_entry_content)
|
|
172
|
-
diff = build_sequences
|
|
239
|
+
end
|
|
173
240
|
|
|
241
|
+
parent_map.each do |key, old_hash|
|
|
242
|
+
key = clean_path(key)
|
|
243
|
+
next if index.key?(key)
|
|
244
|
+
|
|
245
|
+
entry_content = File.read(".stolen-git/storage/blobs/#{old_hash}").lines.to_a
|
|
246
|
+
compute_diff(entry_content, [])
|
|
247
|
+
diff = build_sequences
|
|
174
248
|
no_insertions += diff[:insertions]
|
|
175
249
|
no_deletions += diff[:deletions]
|
|
176
250
|
no_file_changed += 1
|
|
@@ -196,6 +270,7 @@ module Actions
|
|
|
196
270
|
|
|
197
271
|
# Making the tree
|
|
198
272
|
index.each do |key, value|
|
|
273
|
+
key = clean_path(key)
|
|
199
274
|
tree_content[:entries].push({
|
|
200
275
|
path: key,
|
|
201
276
|
type: 'blob',
|
|
@@ -246,6 +321,22 @@ module Actions
|
|
|
246
321
|
end
|
|
247
322
|
|
|
248
323
|
def reset
|
|
324
|
+
begin
|
|
325
|
+
OptionParser.new do |opts|
|
|
326
|
+
opts.banner = 'Usage: stg reset [commit_id]'
|
|
327
|
+
|
|
328
|
+
opts.on_tail('-h', '--help', 'Show this help') do
|
|
329
|
+
puts opts
|
|
330
|
+
exit
|
|
331
|
+
end
|
|
332
|
+
end.parse!
|
|
333
|
+
rescue OptionParser::ParseError => e
|
|
334
|
+
puts e.message
|
|
335
|
+
puts 'Usage: stg reset [commit_id]'
|
|
336
|
+
puts ' -h, --help Show this help'
|
|
337
|
+
exit 1
|
|
338
|
+
end
|
|
339
|
+
|
|
249
340
|
commit_id = ARGV.first
|
|
250
341
|
commit_history = read_json('.stolen-git/commits.json')
|
|
251
342
|
pointer = read_json('.stolen-git/pointer.json')
|
|
@@ -275,13 +366,27 @@ module Actions
|
|
|
275
366
|
options = { commit: false }
|
|
276
367
|
|
|
277
368
|
# Getting commit name & description
|
|
278
|
-
|
|
279
|
-
|
|
369
|
+
begin
|
|
370
|
+
OptionParser.new do |opts|
|
|
371
|
+
opts.banner = 'Usage: stg checkout [options]'
|
|
372
|
+
|
|
373
|
+
opts.on('-c', '--commit', 'Add a commit id instead') do
|
|
374
|
+
options[:commit] = true
|
|
375
|
+
end
|
|
376
|
+
|
|
377
|
+
opts.on_tail('-h', '--help', 'Show this help') do
|
|
378
|
+
puts opts
|
|
379
|
+
exit
|
|
380
|
+
end
|
|
381
|
+
end.parse!
|
|
382
|
+
rescue OptionParser::ParseError => e
|
|
383
|
+
puts e.message
|
|
384
|
+
puts 'Usage: stg checkout [options]'
|
|
385
|
+
puts ' -c, --commit Add a commit id instead'
|
|
386
|
+
puts ' -h, --help Show this help'
|
|
387
|
+
exit 1
|
|
388
|
+
end
|
|
280
389
|
|
|
281
|
-
opts.on('-c', '--commit', 'Add a commit id instead') do
|
|
282
|
-
options[:commit] = true
|
|
283
|
-
end
|
|
284
|
-
end.parse!
|
|
285
390
|
inp = ARGV.last
|
|
286
391
|
if !inp
|
|
287
392
|
puts 'Please Enter the name of a branch or commit_id'
|
|
@@ -290,7 +395,7 @@ module Actions
|
|
|
290
395
|
current_commit_hash = commit_history['commits'].find { |x| x['id'] == inp }['hash']
|
|
291
396
|
revert_to_commit(current_commit_hash)
|
|
292
397
|
else
|
|
293
|
-
# TODO: Handle if user enters branch_id instead
|
|
398
|
+
# TODO: Handle if user enters branch_id instead of name
|
|
294
399
|
branch_content = {}
|
|
295
400
|
branch_id = ''
|
|
296
401
|
Dir.children('.stolen-git/branches').each do |entry|
|
|
@@ -305,28 +410,47 @@ module Actions
|
|
|
305
410
|
nil
|
|
306
411
|
end
|
|
307
412
|
commit_hash = branch_content['commit_pointer']
|
|
308
|
-
revert_to_commit(commit_hash)
|
|
413
|
+
revert_to_commit(commit_hash) if commit_hash&.length&.positive?
|
|
309
414
|
pointer = read_json('.stolen-git/pointer.json')
|
|
310
415
|
pointer['point_to'] = branch_id
|
|
311
416
|
pointer['type'] = 'branch'
|
|
312
417
|
File.write('.stolen-git/pointer.json', JSON.pretty_generate(pointer))
|
|
418
|
+
|
|
313
419
|
end
|
|
314
420
|
end
|
|
315
421
|
|
|
316
422
|
def branch
|
|
317
|
-
|
|
423
|
+
begin
|
|
424
|
+
OptionParser.new do |opts|
|
|
425
|
+
opts.banner = 'Usage: stg branch [name]'
|
|
426
|
+
|
|
427
|
+
opts.on_tail('-h', '--help', 'Show this help') do
|
|
428
|
+
puts opts
|
|
429
|
+
exit
|
|
430
|
+
end
|
|
431
|
+
end.parse!
|
|
432
|
+
rescue OptionParser::ParseError => e
|
|
433
|
+
puts e.message
|
|
434
|
+
puts 'Usage: stg branch [name]'
|
|
435
|
+
puts ' -h, --help Show this help'
|
|
436
|
+
exit 1
|
|
437
|
+
end
|
|
438
|
+
|
|
439
|
+
names = ARGV
|
|
318
440
|
pointer = read_json('.stolen-git/pointer.json')
|
|
319
441
|
pointed_branch = pointer['type'] == 'branch' ? pointer['point_to'] : ''
|
|
320
|
-
if
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
442
|
+
if names && names.length.positive?
|
|
443
|
+
names.each do |name|
|
|
444
|
+
first_commit = pointer['type'] == 'branch' ? read_json(".stolen-git/branches/#{pointed_branch}.json")['commit_pointer'] : pointer['point_to']
|
|
445
|
+
id = SecureRandom.uuid
|
|
446
|
+
File.write(".stolen-git/branches/#{id}.json", JSON.pretty_generate({
|
|
447
|
+
name: name,
|
|
448
|
+
created_at: Time.now,
|
|
449
|
+
commit_pointer: first_commit
|
|
450
|
+
}))
|
|
451
|
+
puts "branch #{name} created"
|
|
452
|
+
end
|
|
328
453
|
return
|
|
329
|
-
puts "branch #{name} created"
|
|
330
454
|
end
|
|
331
455
|
Dir.children('.stolen-git/branches').each do |entry|
|
|
332
456
|
branch_content = read_json(".stolen-git/branches/#{entry}")
|
|
@@ -341,8 +465,25 @@ module Actions
|
|
|
341
465
|
end
|
|
342
466
|
|
|
343
467
|
def diff
|
|
468
|
+
begin
|
|
469
|
+
OptionParser.new do |opts|
|
|
470
|
+
opts.banner = 'Usage: stg diff'
|
|
471
|
+
|
|
472
|
+
opts.on_tail('-h', '--help', 'Show this help') do
|
|
473
|
+
puts opts
|
|
474
|
+
exit
|
|
475
|
+
end
|
|
476
|
+
end.parse!
|
|
477
|
+
rescue OptionParser::ParseError => e
|
|
478
|
+
puts e.message
|
|
479
|
+
puts 'Usage: stg diff'
|
|
480
|
+
puts ' -h, --help Show this help'
|
|
481
|
+
exit 1
|
|
482
|
+
end
|
|
483
|
+
|
|
344
484
|
index = read_json('.stolen-git/index.json')
|
|
345
485
|
index.each do |key, value|
|
|
486
|
+
key = clean_path(key)
|
|
346
487
|
new_file_content = File.exist?(key) ? File.read(key) : nil
|
|
347
488
|
file_name = File.basename(key)
|
|
348
489
|
if new_file_content.nil?
|
|
@@ -360,25 +501,65 @@ module Actions
|
|
|
360
501
|
end
|
|
361
502
|
|
|
362
503
|
def log
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
504
|
+
# Handle if the user wants to -[num]
|
|
505
|
+
ARGV.map! do |arg|
|
|
506
|
+
if arg =~ /^-(\d+)$/
|
|
507
|
+
['-l', ::Regexp.last_match(1)]
|
|
508
|
+
else
|
|
509
|
+
arg
|
|
510
|
+
end
|
|
511
|
+
end.flatten!
|
|
366
512
|
|
|
367
|
-
|
|
368
|
-
|
|
513
|
+
options = { limit: 0 }
|
|
514
|
+
begin
|
|
515
|
+
OptionParser.new do |opts|
|
|
516
|
+
opts.banner = 'Usage: stg log [limit]'
|
|
369
517
|
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
518
|
+
opts.on('-l', '--limit LIMIT', 'limit showed logs') do |num|
|
|
519
|
+
options[:limit] = num.to_i
|
|
520
|
+
end
|
|
521
|
+
|
|
522
|
+
opts.on_tail('-h', '--help', 'Show this help') do
|
|
523
|
+
puts opts
|
|
524
|
+
exit
|
|
525
|
+
end
|
|
526
|
+
end.parse!
|
|
527
|
+
rescue OptionParser::ParseError => e
|
|
528
|
+
puts e.message
|
|
529
|
+
puts 'Usage: stg log [limit]'
|
|
530
|
+
puts ' -[num], --limit limit showed logs i.e. stg log -5'
|
|
531
|
+
puts ' -l, --limit limit showed logs'
|
|
532
|
+
puts ' -h, --help Show this help'
|
|
533
|
+
exit 1
|
|
534
|
+
end
|
|
535
|
+
|
|
536
|
+
is_limited = options[:limit] > 0
|
|
537
|
+
pointer = read_json('.stolen-git/pointer.json')
|
|
538
|
+
last_commit = pointer['type'] == 'commit' ? pointer['point_to'] : read_json(".stolen-git/branches/#{pointer['point_to']}.json")['commit_pointer']
|
|
539
|
+
unless last_commit
|
|
540
|
+
puts "Couldn't find last commits. The setup might have been corrupted. If that's the case run 'stg init'"
|
|
541
|
+
end
|
|
542
|
+
i = 0
|
|
543
|
+
|
|
544
|
+
print_commit = lambda do |commit_hash, commit_content|
|
|
375
545
|
puts
|
|
376
546
|
puts "commit #{commit_content['id']}".green
|
|
547
|
+
puts "hash: #{commit_hash[0..5]}...#{commit_hash[-5..]}".green
|
|
377
548
|
puts "Author #{commit_content['author_profile']['username']} <#{commit_content['author_profile']['email']}>"
|
|
378
549
|
puts "Date: #{commit_content['created_at']}"
|
|
379
550
|
puts
|
|
380
551
|
puts " #{commit_content['name']}"
|
|
381
|
-
|
|
552
|
+
end
|
|
553
|
+
|
|
554
|
+
while (is_limited && i < options[:limit] || !is_limited) && last_commit && last_commit.length.positive?
|
|
555
|
+
last_commit_content = read_json(".stolen-git/commits/#{last_commit}.json")
|
|
556
|
+
print_commit.call(last_commit, last_commit_content)
|
|
557
|
+
last_commit = last_commit_content['parent_commit']
|
|
558
|
+
i += 1
|
|
559
|
+
if !is_limited && i >= 5
|
|
560
|
+
q = ask(':')
|
|
561
|
+
break if q == 'q'
|
|
562
|
+
end
|
|
382
563
|
end
|
|
383
564
|
end
|
|
384
565
|
end
|
|
@@ -27,14 +27,12 @@ module DiffCalc
|
|
|
27
27
|
if i1 >= @old_s.length
|
|
28
28
|
result = { diff_cnt: @new_s.length - i2, insertions: @new_s.length - i2, deletions: 0, action: :insert }
|
|
29
29
|
@mem[[i1, i2]] = result
|
|
30
|
-
differencing(i1, i2 + 1) if i2 < @new_s.length
|
|
31
30
|
return result
|
|
32
31
|
end
|
|
33
32
|
|
|
34
33
|
if i2 >= @new_s.length
|
|
35
34
|
result = { diff_cnt: @old_s.length - i1, insertions: 0, deletions: @old_s.length - i1, action: :delete }
|
|
36
35
|
@mem[[i1, i2]] = result
|
|
37
|
-
differencing(i1 + 1, i2) if i1 < @old_s.length
|
|
38
36
|
return result
|
|
39
37
|
end
|
|
40
38
|
|
|
@@ -69,7 +67,10 @@ module DiffCalc
|
|
|
69
67
|
deletion_seq = {}
|
|
70
68
|
|
|
71
69
|
while i1 < @old_s.length || i2 < @new_s.length
|
|
72
|
-
|
|
70
|
+
entry = @mem[[i1, i2]]
|
|
71
|
+
break unless entry
|
|
72
|
+
|
|
73
|
+
action = entry[:action]
|
|
73
74
|
|
|
74
75
|
case action
|
|
75
76
|
when :done
|
|
@@ -82,12 +83,12 @@ module DiffCalc
|
|
|
82
83
|
deletion_seq[i2].push({ old_index: i1, ma_type: 'bs' })
|
|
83
84
|
i1 += 1
|
|
84
85
|
when :insert
|
|
85
|
-
insertion_seq[i2] = { value: @new_s[i2], old_index: i1 }
|
|
86
|
+
insertion_seq[i2] = { value: @new_s[i2].encode('UTF-8', invalid: :replace, undef: :replace, replace: ''), old_index: i1 }
|
|
86
87
|
i2 += 1
|
|
87
88
|
end
|
|
88
89
|
end
|
|
89
90
|
|
|
90
|
-
result = @mem[[0, 0]]
|
|
91
|
+
result = @mem[[0, 0]] || { insertions: 0, deletions: 0, diff_cnt: 0 }
|
|
91
92
|
{
|
|
92
93
|
insertion_seq: insertion_seq,
|
|
93
94
|
deletion_seq: deletion_seq,
|
data/lib/{help.rb → stg/help.rb}
RENAMED
|
@@ -8,11 +8,11 @@ module Help
|
|
|
8
8
|
stage: 'add a file or directory to be tracked ',
|
|
9
9
|
commit: 'Save the current tracked state ',
|
|
10
10
|
diff: 'get the difference between working directory and the last commit ',
|
|
11
|
-
log: 'print out commit history
|
|
11
|
+
log: 'print out commit history',
|
|
12
12
|
reset: 'Revert to commit',
|
|
13
13
|
checkout: 'check a commit or a branch without loss in data',
|
|
14
|
-
branch: 'List all branches.
|
|
15
|
-
|
|
14
|
+
branch: 'List all branches.',
|
|
15
|
+
help: 'show this list'
|
|
16
16
|
}
|
|
17
17
|
max_len = 0
|
|
18
18
|
commands_docs.each_key do |command|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
require 'fileutils'
|
|
2
2
|
require 'optparse'
|
|
3
3
|
require 'digest'
|
|
4
|
+
require 'pathname'
|
|
4
5
|
module Utils
|
|
5
6
|
def confirm?(prompt)
|
|
6
7
|
loop do
|
|
@@ -28,6 +29,8 @@ module Utils
|
|
|
28
29
|
|
|
29
30
|
def read_json(path)
|
|
30
31
|
JSON.parse(File.read(path))
|
|
32
|
+
rescue StandardError
|
|
33
|
+
nil
|
|
31
34
|
end
|
|
32
35
|
|
|
33
36
|
def get_file_hash(path)
|
|
@@ -58,6 +61,17 @@ module Utils
|
|
|
58
61
|
|
|
59
62
|
File.write('.stolen-git/index.json', JSON.pretty_generate(index))
|
|
60
63
|
end
|
|
64
|
+
|
|
65
|
+
def clean_path(path)
|
|
66
|
+
Pathname.new(path).cleanpath.to_s
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def check_program_exists
|
|
70
|
+
return true if File.exist? '.stolen-git'
|
|
71
|
+
|
|
72
|
+
puts "There is no instance of stolen-git found. Please run 'stg init' first."
|
|
73
|
+
false
|
|
74
|
+
end
|
|
61
75
|
end
|
|
62
76
|
|
|
63
77
|
include Utils
|
data/lib/stg/version.rb
ADDED
data/lib/stg.rb
CHANGED
|
@@ -1,47 +1,74 @@
|
|
|
1
|
-
|
|
2
|
-
require_relative '
|
|
1
|
+
require 'optparse'
|
|
2
|
+
require_relative 'stg/help'
|
|
3
|
+
require_relative 'stg/actions'
|
|
4
|
+
require_relative 'stg/version'
|
|
3
5
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
case command
|
|
9
|
-
when 'init'
|
|
10
|
-
p_initialize
|
|
6
|
+
module Stg
|
|
7
|
+
class CLI
|
|
8
|
+
extend Actions
|
|
9
|
+
extend Help
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
def self.start
|
|
12
|
+
begin
|
|
13
|
+
OptionParser.new do |opts|
|
|
14
|
+
opts.banner = 'Usage: stg <command> [options]'
|
|
14
15
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
opts.on('-v', '--version', 'Show version') do
|
|
17
|
+
puts "stg version #{VERSION}"
|
|
18
|
+
exit
|
|
19
|
+
end
|
|
19
20
|
|
|
20
|
-
|
|
21
|
-
|
|
21
|
+
opts.on('-h', '--help', 'Show this help') do
|
|
22
|
+
puts print_usage
|
|
23
|
+
exit
|
|
24
|
+
end
|
|
25
|
+
end.order!
|
|
26
|
+
rescue OptionParser::ParseError
|
|
27
|
+
# Ignore unknown options, let command handlers deal with them
|
|
28
|
+
end
|
|
22
29
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
30
|
+
command = ARGV.shift
|
|
31
|
+
if !command || command.empty?
|
|
32
|
+
puts print_usage
|
|
33
|
+
return
|
|
34
|
+
elsif command == 'init'
|
|
35
|
+
p_initialize
|
|
36
|
+
return
|
|
37
|
+
else
|
|
38
|
+
return unless check_program_exists
|
|
39
|
+
end
|
|
29
40
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
when '
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
41
|
+
case command
|
|
42
|
+
when 'commit'
|
|
43
|
+
commit
|
|
44
|
+
when 'diff'
|
|
45
|
+
diff
|
|
46
|
+
when 'test'
|
|
47
|
+
test
|
|
48
|
+
when 'stage'
|
|
49
|
+
stage
|
|
50
|
+
when 'check_router'
|
|
51
|
+
check_router
|
|
52
|
+
when 'reset'
|
|
53
|
+
reset
|
|
54
|
+
when 'log'
|
|
55
|
+
log
|
|
56
|
+
when 'checkout'
|
|
57
|
+
checkout
|
|
58
|
+
when 'branch'
|
|
59
|
+
branch
|
|
60
|
+
when 'help'
|
|
61
|
+
puts print_usage
|
|
62
|
+
exit 1
|
|
63
|
+
when nil
|
|
64
|
+
puts print_usage
|
|
65
|
+
exit 1
|
|
66
|
+
else
|
|
67
|
+
puts "Unknown command: #{command}"
|
|
68
|
+
exit 1
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
47
72
|
end
|
|
73
|
+
|
|
74
|
+
Stg::CLI.start if __FILE__ == $PROGRAM_NAME
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: stg
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Amr ElTaweel
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-05-
|
|
11
|
+
date: 2026-05-08 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: colorize
|
|
@@ -35,11 +35,12 @@ extra_rdoc_files: []
|
|
|
35
35
|
files:
|
|
36
36
|
- README.md
|
|
37
37
|
- bin/stg
|
|
38
|
-
- lib/actions.rb
|
|
39
|
-
- lib/differencing.rb
|
|
40
|
-
- lib/help.rb
|
|
41
38
|
- lib/stg.rb
|
|
42
|
-
- lib/
|
|
39
|
+
- lib/stg/actions.rb
|
|
40
|
+
- lib/stg/differencing.rb
|
|
41
|
+
- lib/stg/help.rb
|
|
42
|
+
- lib/stg/utils.rb
|
|
43
|
+
- lib/stg/version.rb
|
|
43
44
|
homepage: https://github.com/amrbassem218/stolen-git
|
|
44
45
|
licenses:
|
|
45
46
|
- MIT
|