appydave-tools 0.76.5 → 0.76.7
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/CHANGELOG.md +18 -0
- data/bin/dam +10 -318
- data/docs/planning/extract-vat-cli/IMPLEMENTATION_PLAN.md +3 -3
- data/lib/appydave/tools/dam/s3_arg_parser.rb +136 -0
- data/lib/appydave/tools/dam/s3_scan_command.rb +191 -0
- data/lib/appydave/tools/version.rb +1 -1
- data/lib/appydave/tools.rb +2 -0
- data/package.json +1 -1
- metadata +3 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 51ac1542f215f90d518a24c96b5185cf954b9db2beab4bbb93c8d43f3b106fb7
|
|
4
|
+
data.tar.gz: 11acb6d8817125846945e4f7ba3bfb77b305155093f507f346a21477c4102cdb
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 02a5b3623de62bbb09d343101c1edc48b711fc8682d9396689043afcdd134276c887de57d802e8a717db9adaeb34b48eb14dd6a199e085d64430a0525300cf1e
|
|
7
|
+
data.tar.gz: ce60ac62a7753a206768335c7cc51c8d4765223efd9dd34d4a490fc250f8af63aca11fd532f9918f15ac075be8e7698bd7613704040a16f66777a0455ca54c25
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,21 @@
|
|
|
1
|
+
## [0.76.6](https://github.com/appydave/appydave-tools/compare/v0.76.5...v0.76.6) (2026-03-19)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* extract S3ScanCommand class from VatCLI; add smoke-test spec ([cd03606](https://github.com/appydave/appydave-tools/commit/cd03606e3307665c7f69391d6c160f50df1773ba))
|
|
7
|
+
* remove redundant rubocop disable directives from S3ScanCommand (CI rubocop 1.85.1) ([4c9deb4](https://github.com/appydave/appydave-tools/commit/4c9deb4298d4577a99d0e82e7b72918a26275d40))
|
|
8
|
+
|
|
9
|
+
## [0.76.5](https://github.com/appydave/appydave-tools/compare/v0.76.4...v0.76.5) (2026-03-19)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
### Bug Fixes
|
|
13
|
+
|
|
14
|
+
* extract LocalSyncStatus module from VatCLI; add spec ([0672855](https://github.com/appydave/appydave-tools/commit/0672855a25ebcbb2df3f5eea6208f910aed74124))
|
|
15
|
+
* remove redundant rubocop disable directives in LocalSyncStatus ([9050795](https://github.com/appydave/appydave-tools/commit/905079573caf7555771da02b2d9c6ebfc34d1c95))
|
|
16
|
+
* replace format_bytes with FileHelper.format_size; remove duplicate method from VatCLI ([3cd362f](https://github.com/appydave/appydave-tools/commit/3cd362f79342578ddb7a750b9b404851cf4d1eb4))
|
|
17
|
+
* restore youtube_automation_config require removed by micro-cleanup; fix spec brand dir setup ([a5779a7](https://github.com/appydave/appydave-tools/commit/a5779a7b5dab1697b2a21ca3bbece9c0bff340c2))
|
|
18
|
+
|
|
1
19
|
## [0.76.4](https://github.com/appydave/appydave-tools/compare/v0.76.3...v0.76.4) (2026-03-19)
|
|
2
20
|
|
|
3
21
|
|
data/bin/dam
CHANGED
|
@@ -154,7 +154,7 @@ class VatCLI
|
|
|
154
154
|
|
|
155
155
|
# S3 Upload
|
|
156
156
|
def s3_up_command(args)
|
|
157
|
-
options =
|
|
157
|
+
options = Appydave::Tools::Dam::S3ArgParser.parse_s3(args, 's3-up')
|
|
158
158
|
s3_ops = Appydave::Tools::Dam::S3Operations.new(options[:brand], options[:project])
|
|
159
159
|
s3_ops.upload(dry_run: options[:dry_run])
|
|
160
160
|
rescue StandardError => e
|
|
@@ -164,7 +164,7 @@ class VatCLI
|
|
|
164
164
|
|
|
165
165
|
# S3 Download
|
|
166
166
|
def s3_down_command(args)
|
|
167
|
-
options =
|
|
167
|
+
options = Appydave::Tools::Dam::S3ArgParser.parse_s3(args, 's3-down')
|
|
168
168
|
s3_ops = Appydave::Tools::Dam::S3Operations.new(options[:brand], options[:project])
|
|
169
169
|
s3_ops.download(dry_run: options[:dry_run])
|
|
170
170
|
rescue StandardError => e
|
|
@@ -174,7 +174,7 @@ class VatCLI
|
|
|
174
174
|
|
|
175
175
|
# S3 Status
|
|
176
176
|
def s3_status_command(args)
|
|
177
|
-
options =
|
|
177
|
+
options = Appydave::Tools::Dam::S3ArgParser.parse_s3(args, 's3-status')
|
|
178
178
|
s3_ops = Appydave::Tools::Dam::S3Operations.new(options[:brand], options[:project])
|
|
179
179
|
s3_ops.status
|
|
180
180
|
rescue StandardError => e
|
|
@@ -184,7 +184,7 @@ class VatCLI
|
|
|
184
184
|
|
|
185
185
|
# S3 Cleanup Remote
|
|
186
186
|
def s3_cleanup_remote_command(args)
|
|
187
|
-
options =
|
|
187
|
+
options = Appydave::Tools::Dam::S3ArgParser.parse_s3(args, 's3-cleanup-remote')
|
|
188
188
|
s3_ops = Appydave::Tools::Dam::S3Operations.new(options[:brand], options[:project])
|
|
189
189
|
s3_ops.cleanup(force: options[:force], dry_run: options[:dry_run])
|
|
190
190
|
rescue StandardError => e
|
|
@@ -194,7 +194,7 @@ class VatCLI
|
|
|
194
194
|
|
|
195
195
|
# S3 Cleanup Local
|
|
196
196
|
def s3_cleanup_local_command(args)
|
|
197
|
-
options =
|
|
197
|
+
options = Appydave::Tools::Dam::S3ArgParser.parse_s3(args, 's3-cleanup-local')
|
|
198
198
|
s3_ops = Appydave::Tools::Dam::S3Operations.new(options[:brand], options[:project])
|
|
199
199
|
s3_ops.cleanup_local(force: options[:force], dry_run: options[:dry_run])
|
|
200
200
|
rescue StandardError => e
|
|
@@ -204,7 +204,7 @@ class VatCLI
|
|
|
204
204
|
|
|
205
205
|
# Share file via pre-signed URL
|
|
206
206
|
def s3_share_command(args)
|
|
207
|
-
options =
|
|
207
|
+
options = Appydave::Tools::Dam::S3ArgParser.parse_share(args)
|
|
208
208
|
|
|
209
209
|
share_ops = Appydave::Tools::Dam::ShareOperations.new(options[:brand], options[:project])
|
|
210
210
|
share_ops.generate_links(files: options[:file], expires: options[:expires], download: options[:download])
|
|
@@ -215,7 +215,7 @@ class VatCLI
|
|
|
215
215
|
|
|
216
216
|
# Discover files in S3 for a project
|
|
217
217
|
def s3_discover_command(args)
|
|
218
|
-
options =
|
|
218
|
+
options = Appydave::Tools::Dam::S3ArgParser.parse_discover(args)
|
|
219
219
|
files = fetch_s3_files(options[:brand_key], options[:project_id])
|
|
220
220
|
|
|
221
221
|
return if handle_empty_files?(files, options[:brand_key], options[:project_id])
|
|
@@ -228,7 +228,7 @@ class VatCLI
|
|
|
228
228
|
|
|
229
229
|
# Archive project to SSD
|
|
230
230
|
def archive_command(args)
|
|
231
|
-
options =
|
|
231
|
+
options = Appydave::Tools::Dam::S3ArgParser.parse_s3(args, 'archive')
|
|
232
232
|
s3_ops = Appydave::Tools::Dam::S3Operations.new(options[:brand], options[:project])
|
|
233
233
|
s3_ops.archive(force: options[:force], dry_run: options[:dry_run])
|
|
234
234
|
rescue StandardError => e
|
|
@@ -461,132 +461,6 @@ class VatCLI
|
|
|
461
461
|
exit 1
|
|
462
462
|
end
|
|
463
463
|
|
|
464
|
-
# Parse S3 command arguments
|
|
465
|
-
# rubocop:disable Metrics/MethodLength
|
|
466
|
-
def parse_s3_args(args, command)
|
|
467
|
-
dry_run = args.include?('--dry-run')
|
|
468
|
-
force = args.include?('--force')
|
|
469
|
-
args = args.reject { |arg| arg.start_with?('--') }
|
|
470
|
-
|
|
471
|
-
brand_arg = args[0]
|
|
472
|
-
project_arg = args[1]
|
|
473
|
-
|
|
474
|
-
if brand_arg.nil?
|
|
475
|
-
# Auto-detect from PWD
|
|
476
|
-
brand, project_id = Appydave::Tools::Dam::ProjectResolver.detect_from_pwd
|
|
477
|
-
if brand.nil? || project_id.nil?
|
|
478
|
-
puts '❌ Could not auto-detect brand/project from current directory'
|
|
479
|
-
puts "Usage: dam #{command} <brand> <project> [--dry-run]"
|
|
480
|
-
exit 1
|
|
481
|
-
end
|
|
482
|
-
brand_key = brand # Already detected, use as-is
|
|
483
|
-
else
|
|
484
|
-
# Validate brand exists before trying to resolve project
|
|
485
|
-
unless valid_brand?(brand_arg)
|
|
486
|
-
puts "❌ Invalid brand: '#{brand_arg}'"
|
|
487
|
-
puts ''
|
|
488
|
-
puts 'Valid brands:'
|
|
489
|
-
puts ' appydave → v-appydave (AppyDave brand)'
|
|
490
|
-
puts ' voz → v-voz (VOZ client)'
|
|
491
|
-
puts ' aitldr → v-aitldr (AITLDR brand)'
|
|
492
|
-
puts ' kiros → v-kiros (Kiros client)'
|
|
493
|
-
puts ' joy → v-beauty-and-joy (Beauty & Joy)'
|
|
494
|
-
puts ' ss → v-supportsignal (SupportSignal)'
|
|
495
|
-
puts ''
|
|
496
|
-
puts "Usage: dam #{command} <brand> <project> [--dry-run]"
|
|
497
|
-
exit 1
|
|
498
|
-
end
|
|
499
|
-
|
|
500
|
-
brand_key = brand_arg # Use the shortcut/key (e.g., 'appydave')
|
|
501
|
-
brand = Appydave::Tools::Dam::Config.expand_brand(brand_arg) # Expand for path resolution
|
|
502
|
-
project_id = Appydave::Tools::Dam::ProjectResolver.resolve(brand_arg, project_arg)
|
|
503
|
-
end
|
|
504
|
-
|
|
505
|
-
# Set ENV for compatibility with ConfigLoader
|
|
506
|
-
ENV['BRAND_PATH'] = Appydave::Tools::Dam::Config.brand_path(brand)
|
|
507
|
-
|
|
508
|
-
{ brand: brand_key, project: project_id, dry_run: dry_run, force: force }
|
|
509
|
-
end
|
|
510
|
-
# rubocop:enable Metrics/MethodLength
|
|
511
|
-
|
|
512
|
-
def valid_brand?(brand_key)
|
|
513
|
-
Appydave::Tools::Configuration::Config.configure
|
|
514
|
-
brands = Appydave::Tools::Configuration::Config.brands
|
|
515
|
-
brands.key?(brand_key) || brands.shortcut?(brand_key)
|
|
516
|
-
end
|
|
517
|
-
|
|
518
|
-
def parse_share_args(args)
|
|
519
|
-
# Extract --expires flag
|
|
520
|
-
expires = '7d' # default
|
|
521
|
-
if (expires_index = args.index('--expires'))
|
|
522
|
-
expires = args[expires_index + 1]
|
|
523
|
-
args.delete_at(expires_index + 1)
|
|
524
|
-
args.delete_at(expires_index)
|
|
525
|
-
end
|
|
526
|
-
|
|
527
|
-
# Extract --download flag
|
|
528
|
-
download = args.include?('--download')
|
|
529
|
-
|
|
530
|
-
# Remove other flags
|
|
531
|
-
args = args.reject { |arg| arg.start_with?('--') }
|
|
532
|
-
|
|
533
|
-
brand_arg = args[0]
|
|
534
|
-
project_arg = args[1]
|
|
535
|
-
file_arg = args[2]
|
|
536
|
-
|
|
537
|
-
show_share_usage_and_exit if brand_arg.nil? || project_arg.nil? || file_arg.nil?
|
|
538
|
-
|
|
539
|
-
brand_key = brand_arg
|
|
540
|
-
brand = Appydave::Tools::Dam::Config.expand_brand(brand_arg)
|
|
541
|
-
project_id = Appydave::Tools::Dam::ProjectResolver.resolve(brand_arg, project_arg)
|
|
542
|
-
|
|
543
|
-
# Set ENV for compatibility with ConfigLoader
|
|
544
|
-
ENV['BRAND_PATH'] = Appydave::Tools::Dam::Config.brand_path(brand)
|
|
545
|
-
|
|
546
|
-
{ brand: brand_key, project: project_id, file: file_arg, expires: expires, download: download }
|
|
547
|
-
end
|
|
548
|
-
|
|
549
|
-
def show_share_usage_and_exit
|
|
550
|
-
puts 'Usage: dam s3-share <brand> <project> <file> [--expires 7d] [--download]'
|
|
551
|
-
puts ''
|
|
552
|
-
puts 'Options:'
|
|
553
|
-
puts ' --expires TIME Expiry time (default: 7d)'
|
|
554
|
-
puts ' --download Force download instead of viewing in browser'
|
|
555
|
-
puts ''
|
|
556
|
-
puts 'Examples:'
|
|
557
|
-
puts ' dam s3-share appydave b70 video.mp4'
|
|
558
|
-
puts ' dam s3-share appydave b70 video.mp4 --expires 24h'
|
|
559
|
-
puts ' dam s3-share appydave b70 video.mp4 --download'
|
|
560
|
-
puts ' dam s3-share voz boy-baker final-edit.mov --expires 3d --download'
|
|
561
|
-
exit 1
|
|
562
|
-
end
|
|
563
|
-
|
|
564
|
-
def parse_discover_args(args)
|
|
565
|
-
shareable = args.include?('--shareable')
|
|
566
|
-
args = args.reject { |arg| arg.start_with?('--') }
|
|
567
|
-
|
|
568
|
-
brand_arg = args[0]
|
|
569
|
-
project_arg = args[1]
|
|
570
|
-
|
|
571
|
-
if brand_arg.nil? || project_arg.nil?
|
|
572
|
-
puts 'Usage: dam s3-discover <brand> <project> [--shareable]'
|
|
573
|
-
puts ''
|
|
574
|
-
puts 'Examples:'
|
|
575
|
-
puts ' dam s3-discover appydave b70 # List files'
|
|
576
|
-
puts ' dam s3-discover appydave b70 --shareable # Generate share commands'
|
|
577
|
-
exit 1
|
|
578
|
-
end
|
|
579
|
-
|
|
580
|
-
brand_key = brand_arg
|
|
581
|
-
brand = Appydave::Tools::Dam::Config.expand_brand(brand_arg)
|
|
582
|
-
project_id = Appydave::Tools::Dam::ProjectResolver.resolve(brand_arg, project_arg)
|
|
583
|
-
|
|
584
|
-
# Set ENV for compatibility with ConfigLoader
|
|
585
|
-
ENV['BRAND_PATH'] = Appydave::Tools::Dam::Config.brand_path(brand)
|
|
586
|
-
|
|
587
|
-
{ brand_key: brand_key, project_id: project_id, shareable: shareable }
|
|
588
|
-
end
|
|
589
|
-
|
|
590
464
|
def fetch_s3_files(brand_key, project_id)
|
|
591
465
|
s3_ops = Appydave::Tools::Dam::S3Operations.new(brand_key, project_id)
|
|
592
466
|
s3_ops.list_s3_files
|
|
@@ -1325,9 +1199,9 @@ class VatCLI
|
|
|
1325
1199
|
brand_arg = args[0]
|
|
1326
1200
|
|
|
1327
1201
|
if all_brands
|
|
1328
|
-
|
|
1202
|
+
Appydave::Tools::Dam::S3ScanCommand.new.scan_all
|
|
1329
1203
|
elsif brand_arg
|
|
1330
|
-
|
|
1204
|
+
Appydave::Tools::Dam::S3ScanCommand.new.scan_single(brand_arg)
|
|
1331
1205
|
else
|
|
1332
1206
|
puts 'Usage: dam s3-scan <brand> [--all]'
|
|
1333
1207
|
puts ''
|
|
@@ -1343,188 +1217,6 @@ class VatCLI
|
|
|
1343
1217
|
puts e.backtrace.first(5).join("\n") if ENV['DEBUG']
|
|
1344
1218
|
exit 1
|
|
1345
1219
|
end
|
|
1346
|
-
|
|
1347
|
-
# rubocop:disable Metrics/MethodLength, Metrics/CyclomaticComplexity
|
|
1348
|
-
def scan_single_brand_s3(brand_arg)
|
|
1349
|
-
puts "🔄 Scanning S3 for #{brand_arg}..."
|
|
1350
|
-
puts ''
|
|
1351
|
-
|
|
1352
|
-
brand_key = brand_arg
|
|
1353
|
-
scanner = Appydave::Tools::Dam::S3Scanner.new(brand_key)
|
|
1354
|
-
|
|
1355
|
-
# Get brand info for S3 path
|
|
1356
|
-
Appydave::Tools::Configuration::Config.configure
|
|
1357
|
-
brand_info = Appydave::Tools::Configuration::Config.brands.get_brand(brand_key)
|
|
1358
|
-
bucket = brand_info.aws.s3_bucket
|
|
1359
|
-
prefix = brand_info.aws.s3_prefix
|
|
1360
|
-
region = brand_info.aws.region
|
|
1361
|
-
|
|
1362
|
-
# Spinner characters for progress
|
|
1363
|
-
spinner_chars = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏']
|
|
1364
|
-
spinner_index = 0
|
|
1365
|
-
|
|
1366
|
-
print "🔍 Scanning s3://#{bucket}/#{prefix}\n"
|
|
1367
|
-
print ' Scanning projects... '
|
|
1368
|
-
|
|
1369
|
-
# Scan all projects with progress callback
|
|
1370
|
-
results = scanner.scan_all_projects(show_progress: false) do |current, total|
|
|
1371
|
-
print "\r Scanning projects... #{spinner_chars[spinner_index]} (#{current}/#{total})"
|
|
1372
|
-
spinner_index = (spinner_index + 1) % spinner_chars.length
|
|
1373
|
-
end
|
|
1374
|
-
|
|
1375
|
-
print "\r Scanning projects... ✓ (#{results.size} found)\n"
|
|
1376
|
-
puts ''
|
|
1377
|
-
|
|
1378
|
-
if results.empty?
|
|
1379
|
-
puts "⚠️ No projects found in S3 for #{brand_key}"
|
|
1380
|
-
puts ' This may indicate:'
|
|
1381
|
-
puts ' - No files uploaded to S3 yet'
|
|
1382
|
-
puts ' - S3 bucket or prefix misconfigured'
|
|
1383
|
-
puts ' - AWS credentials issue'
|
|
1384
|
-
return
|
|
1385
|
-
end
|
|
1386
|
-
|
|
1387
|
-
# Load existing manifest
|
|
1388
|
-
brand_path = Appydave::Tools::Dam::Config.brand_path(brand_key)
|
|
1389
|
-
manifest_path = File.join(brand_path, 'projects.json')
|
|
1390
|
-
|
|
1391
|
-
unless File.exist?(manifest_path)
|
|
1392
|
-
puts "❌ Manifest not found: #{manifest_path}"
|
|
1393
|
-
puts " Run: dam manifest #{brand_key}"
|
|
1394
|
-
puts " Then retry: dam s3-scan #{brand_key}"
|
|
1395
|
-
exit 1
|
|
1396
|
-
end
|
|
1397
|
-
|
|
1398
|
-
manifest = JSON.parse(File.read(manifest_path), symbolize_names: true)
|
|
1399
|
-
|
|
1400
|
-
# Identify matched and orphaned S3 projects
|
|
1401
|
-
local_project_ids = manifest[:projects].map { |p| p[:id] }
|
|
1402
|
-
matched_projects = results.slice(*local_project_ids)
|
|
1403
|
-
orphaned_projects = results.reject { |project_id, _| local_project_ids.include?(project_id) }
|
|
1404
|
-
|
|
1405
|
-
# Merge S3 scan data into manifest for matched projects
|
|
1406
|
-
updated_count = 0
|
|
1407
|
-
manifest[:projects].each do |project|
|
|
1408
|
-
project_id = project[:id]
|
|
1409
|
-
s3_data = results[project_id]
|
|
1410
|
-
next unless s3_data
|
|
1411
|
-
|
|
1412
|
-
project[:storage][:s3] = s3_data
|
|
1413
|
-
updated_count += 1
|
|
1414
|
-
end
|
|
1415
|
-
|
|
1416
|
-
# Update timestamp and note
|
|
1417
|
-
manifest[:config][:last_updated] = Time.now.utc.iso8601
|
|
1418
|
-
manifest[:config][:note] = 'Auto-generated manifest with S3 scan data. Regenerate with: dam s3-scan'
|
|
1419
|
-
|
|
1420
|
-
# Write updated manifest
|
|
1421
|
-
File.write(manifest_path, JSON.pretty_generate(manifest))
|
|
1422
|
-
|
|
1423
|
-
# Add local sync status to matched projects
|
|
1424
|
-
Appydave::Tools::Dam::LocalSyncStatus.enrich!(matched_projects, brand_key)
|
|
1425
|
-
|
|
1426
|
-
# Display table
|
|
1427
|
-
display_s3_scan_table(matched_projects, orphaned_projects, bucket, prefix, region)
|
|
1428
|
-
|
|
1429
|
-
# Summary
|
|
1430
|
-
total_manifest_projects = manifest[:projects].size
|
|
1431
|
-
missing_count = total_manifest_projects - matched_projects.size
|
|
1432
|
-
|
|
1433
|
-
puts ''
|
|
1434
|
-
puts 'ℹ️ Summary:'
|
|
1435
|
-
puts " • Updated #{updated_count} projects in manifest"
|
|
1436
|
-
puts " • #{missing_count} local project(s) not yet uploaded to S3" if missing_count.positive?
|
|
1437
|
-
puts " • Manifest: #{manifest_path}"
|
|
1438
|
-
puts ''
|
|
1439
|
-
end
|
|
1440
|
-
# rubocop:enable Metrics/MethodLength, Metrics/CyclomaticComplexity
|
|
1441
|
-
|
|
1442
|
-
# Display S3 scan results in table format
|
|
1443
|
-
# rubocop:disable Metrics/MethodLength, Metrics/CyclomaticComplexity, Style/FormatStringToken
|
|
1444
|
-
def display_s3_scan_table(matched_projects, orphaned_projects, bucket, prefix, region)
|
|
1445
|
-
puts '✅ S3 Projects Report'
|
|
1446
|
-
puts ''
|
|
1447
|
-
puts 'PROJECT FILES SIZE LOCAL S3 MODIFIED'
|
|
1448
|
-
puts '-' * 92
|
|
1449
|
-
|
|
1450
|
-
# Display matched projects first (sorted alphabetically)
|
|
1451
|
-
matched_projects.sort.each do |project_id, data|
|
|
1452
|
-
files = data[:file_count].to_s.rjust(5)
|
|
1453
|
-
size = Appydave::Tools::Dam::FileHelper.format_size(data[:total_bytes]).rjust(10)
|
|
1454
|
-
local_status = Appydave::Tools::Dam::LocalSyncStatus.format(data[:local_status], data[:local_file_count], data[:file_count])
|
|
1455
|
-
modified = data[:last_modified] ? Time.parse(data[:last_modified]).strftime('%Y-%m-%d %H:%M') : 'N/A'
|
|
1456
|
-
|
|
1457
|
-
puts format('%-36s %5s %10s %-9s %s', project_id, files, size, local_status, modified)
|
|
1458
|
-
end
|
|
1459
|
-
|
|
1460
|
-
# Display orphaned projects (sorted alphabetically)
|
|
1461
|
-
return if orphaned_projects.empty?
|
|
1462
|
-
|
|
1463
|
-
puts '-' * 92
|
|
1464
|
-
orphaned_projects.sort.each do |project_id, data|
|
|
1465
|
-
files = data[:file_count].to_s.rjust(5)
|
|
1466
|
-
size = Appydave::Tools::Dam::FileHelper.format_size(data[:total_bytes]).rjust(10)
|
|
1467
|
-
local_status = 'N/A'
|
|
1468
|
-
modified = data[:last_modified] ? Time.parse(data[:last_modified]).strftime('%Y-%m-%d %H:%M') : 'N/A'
|
|
1469
|
-
|
|
1470
|
-
puts format('%-36s %5s %10s %-9s %s', project_id, files, size, local_status, modified)
|
|
1471
|
-
end
|
|
1472
|
-
|
|
1473
|
-
puts ''
|
|
1474
|
-
folder_word = orphaned_projects.size > 1 ? 'folders' : 'folder'
|
|
1475
|
-
puts "⚠️ #{orphaned_projects.size} orphaned #{folder_word} found (no local project)"
|
|
1476
|
-
|
|
1477
|
-
orphaned_projects.sort.each do |project_id, _data|
|
|
1478
|
-
# Build AWS Console URL
|
|
1479
|
-
project_prefix = "#{prefix}#{project_id}/"
|
|
1480
|
-
console_url = "https://#{region}.console.aws.amazon.com/s3/buckets/#{bucket}?prefix=#{project_prefix}®ion=#{region}"
|
|
1481
|
-
puts " → #{project_id}"
|
|
1482
|
-
puts " #{console_url}"
|
|
1483
|
-
end
|
|
1484
|
-
end
|
|
1485
|
-
# rubocop:enable Metrics/MethodLength, Metrics/CyclomaticComplexity, Style/FormatStringToken
|
|
1486
|
-
|
|
1487
|
-
# rubocop:disable Metrics/MethodLength
|
|
1488
|
-
def scan_all_brands_s3
|
|
1489
|
-
Appydave::Tools::Configuration::Config.configure
|
|
1490
|
-
brands_config = Appydave::Tools::Configuration::Config.brands
|
|
1491
|
-
|
|
1492
|
-
results = []
|
|
1493
|
-
brands_config.brands.each do |brand_info|
|
|
1494
|
-
brand_key = brand_info.key
|
|
1495
|
-
puts ''
|
|
1496
|
-
puts '=' * 60
|
|
1497
|
-
|
|
1498
|
-
begin
|
|
1499
|
-
scan_single_brand_s3(brand_key)
|
|
1500
|
-
results << { brand: brand_key, success: true }
|
|
1501
|
-
rescue StandardError => e
|
|
1502
|
-
puts "❌ Failed to scan #{brand_key}: #{e.message}"
|
|
1503
|
-
results << { brand: brand_key, success: false, error: e.message }
|
|
1504
|
-
end
|
|
1505
|
-
end
|
|
1506
|
-
|
|
1507
|
-
puts ''
|
|
1508
|
-
puts '=' * 60
|
|
1509
|
-
puts '📋 Summary - S3 Scans:'
|
|
1510
|
-
puts ''
|
|
1511
|
-
|
|
1512
|
-
successful, failed = results.partition { |r| r[:success] }
|
|
1513
|
-
|
|
1514
|
-
successful.each do |result|
|
|
1515
|
-
brand_display = result[:brand].ljust(15)
|
|
1516
|
-
puts "✅ #{brand_display} Scanned successfully"
|
|
1517
|
-
end
|
|
1518
|
-
|
|
1519
|
-
failed.each do |result|
|
|
1520
|
-
brand_display = result[:brand].ljust(15)
|
|
1521
|
-
puts "❌ #{brand_display} #{result[:error]}"
|
|
1522
|
-
end
|
|
1523
|
-
|
|
1524
|
-
puts ''
|
|
1525
|
-
puts "Total brands scanned: #{successful.size}/#{results.size}"
|
|
1526
|
-
end
|
|
1527
|
-
# rubocop:enable Metrics/MethodLength
|
|
1528
1220
|
end
|
|
1529
1221
|
|
|
1530
1222
|
# Run CLI
|
|
@@ -9,9 +9,9 @@
|
|
|
9
9
|
|
|
10
10
|
## Pending
|
|
11
11
|
- [x] extract-format-bytes — Replaced 4 callers (plan said 3; orphaned-projects loop in display_s3_scan_table was a 4th). format_bytes deleted. rubocop 0 offenses. Commit: 3cd362f.
|
|
12
|
-
- [
|
|
13
|
-
- [
|
|
14
|
-
- [
|
|
12
|
+
- [x] extract-local-sync-status — LocalSyncStatus module created, 7 specs added (838 total), both methods gone from VatCLI. Side-fix: restored youtube_automation_config require incorrectly removed in prior commit. v0.76.5.
|
|
13
|
+
- [x] extract-s3-scan-command — S3ScanCommand created, 2 smoke tests added (840 total), 3 methods gone from VatCLI. Note: rubocop-disable directives became redundant once methods left God class — needed 2nd kfix to remove them. v0.76.6.
|
|
14
|
+
- [~] extract-s3-arg-parser — Extract `parse_s3_args` + `valid_brand?` + `parse_share_args` + `show_share_usage_and_exit` + `parse_discover_args` → new `S3ArgParser` class; add spec
|
|
15
15
|
|
|
16
16
|
## In Progress
|
|
17
17
|
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Appydave
|
|
4
|
+
module Tools
|
|
5
|
+
module Dam
|
|
6
|
+
# Parses and validates CLI arguments for S3-related dam commands
|
|
7
|
+
# Handles brand resolution, project lookup, flag extraction, and ENV setup
|
|
8
|
+
module S3ArgParser
|
|
9
|
+
module_function
|
|
10
|
+
|
|
11
|
+
def parse_s3(args, command)
|
|
12
|
+
dry_run = args.include?('--dry-run')
|
|
13
|
+
force = args.include?('--force')
|
|
14
|
+
args = args.reject { |arg| arg.start_with?('--') }
|
|
15
|
+
|
|
16
|
+
brand_arg = args[0]
|
|
17
|
+
project_arg = args[1]
|
|
18
|
+
|
|
19
|
+
if brand_arg.nil?
|
|
20
|
+
# Auto-detect from PWD
|
|
21
|
+
brand, project_id = Appydave::Tools::Dam::ProjectResolver.detect_from_pwd
|
|
22
|
+
if brand.nil? || project_id.nil?
|
|
23
|
+
puts '❌ Could not auto-detect brand/project from current directory'
|
|
24
|
+
puts "Usage: dam #{command} <brand> <project> [--dry-run]"
|
|
25
|
+
exit 1
|
|
26
|
+
end
|
|
27
|
+
brand_key = brand # Already detected, use as-is
|
|
28
|
+
else
|
|
29
|
+
# Validate brand exists before trying to resolve project
|
|
30
|
+
unless valid_brand?(brand_arg)
|
|
31
|
+
puts "❌ Invalid brand: '#{brand_arg}'"
|
|
32
|
+
puts ''
|
|
33
|
+
puts 'Valid brands:'
|
|
34
|
+
puts ' appydave → v-appydave (AppyDave brand)'
|
|
35
|
+
puts ' voz → v-voz (VOZ client)'
|
|
36
|
+
puts ' aitldr → v-aitldr (AITLDR brand)'
|
|
37
|
+
puts ' kiros → v-kiros (Kiros client)'
|
|
38
|
+
puts ' joy → v-beauty-and-joy (Beauty & Joy)'
|
|
39
|
+
puts ' ss → v-supportsignal (SupportSignal)'
|
|
40
|
+
puts ''
|
|
41
|
+
puts "Usage: dam #{command} <brand> <project> [--dry-run]"
|
|
42
|
+
exit 1
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
brand_key = brand_arg # Use the shortcut/key (e.g., 'appydave')
|
|
46
|
+
brand = Appydave::Tools::Dam::Config.expand_brand(brand_arg) # Expand for path resolution
|
|
47
|
+
project_id = Appydave::Tools::Dam::ProjectResolver.resolve(brand_arg, project_arg)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Set ENV for compatibility with ConfigLoader
|
|
51
|
+
ENV['BRAND_PATH'] = Appydave::Tools::Dam::Config.brand_path(brand)
|
|
52
|
+
|
|
53
|
+
{ brand: brand_key, project: project_id, dry_run: dry_run, force: force }
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def parse_share(args)
|
|
57
|
+
# Extract --expires flag
|
|
58
|
+
expires = '7d' # default
|
|
59
|
+
if (expires_index = args.index('--expires'))
|
|
60
|
+
expires = args[expires_index + 1]
|
|
61
|
+
args.delete_at(expires_index + 1)
|
|
62
|
+
args.delete_at(expires_index)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Extract --download flag
|
|
66
|
+
download = args.include?('--download')
|
|
67
|
+
|
|
68
|
+
# Remove other flags
|
|
69
|
+
args = args.reject { |arg| arg.start_with?('--') }
|
|
70
|
+
|
|
71
|
+
brand_arg = args[0]
|
|
72
|
+
project_arg = args[1]
|
|
73
|
+
file_arg = args[2]
|
|
74
|
+
|
|
75
|
+
show_share_usage_and_exit if brand_arg.nil? || project_arg.nil? || file_arg.nil?
|
|
76
|
+
|
|
77
|
+
brand_key = brand_arg
|
|
78
|
+
brand = Appydave::Tools::Dam::Config.expand_brand(brand_arg)
|
|
79
|
+
project_id = Appydave::Tools::Dam::ProjectResolver.resolve(brand_arg, project_arg)
|
|
80
|
+
|
|
81
|
+
# Set ENV for compatibility with ConfigLoader
|
|
82
|
+
ENV['BRAND_PATH'] = Appydave::Tools::Dam::Config.brand_path(brand)
|
|
83
|
+
|
|
84
|
+
{ brand: brand_key, project: project_id, file: file_arg, expires: expires, download: download }
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def parse_discover(args)
|
|
88
|
+
shareable = args.include?('--shareable')
|
|
89
|
+
args = args.reject { |arg| arg.start_with?('--') }
|
|
90
|
+
|
|
91
|
+
brand_arg = args[0]
|
|
92
|
+
project_arg = args[1]
|
|
93
|
+
|
|
94
|
+
if brand_arg.nil? || project_arg.nil?
|
|
95
|
+
puts 'Usage: dam s3-discover <brand> <project> [--shareable]'
|
|
96
|
+
puts ''
|
|
97
|
+
puts 'Examples:'
|
|
98
|
+
puts ' dam s3-discover appydave b70 # List files'
|
|
99
|
+
puts ' dam s3-discover appydave b70 --shareable # Generate share commands'
|
|
100
|
+
exit 1
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
brand_key = brand_arg
|
|
104
|
+
brand = Appydave::Tools::Dam::Config.expand_brand(brand_arg)
|
|
105
|
+
project_id = Appydave::Tools::Dam::ProjectResolver.resolve(brand_arg, project_arg)
|
|
106
|
+
|
|
107
|
+
# Set ENV for compatibility with ConfigLoader
|
|
108
|
+
ENV['BRAND_PATH'] = Appydave::Tools::Dam::Config.brand_path(brand)
|
|
109
|
+
|
|
110
|
+
{ brand_key: brand_key, project_id: project_id, shareable: shareable }
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def valid_brand?(brand_key)
|
|
114
|
+
Appydave::Tools::Configuration::Config.configure
|
|
115
|
+
brands = Appydave::Tools::Configuration::Config.brands
|
|
116
|
+
brands.key?(brand_key) || brands.shortcut?(brand_key)
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def show_share_usage_and_exit
|
|
120
|
+
puts 'Usage: dam s3-share <brand> <project> <file> [--expires 7d] [--download]'
|
|
121
|
+
puts ''
|
|
122
|
+
puts 'Options:'
|
|
123
|
+
puts ' --expires TIME Expiry time (default: 7d)'
|
|
124
|
+
puts ' --download Force download instead of viewing in browser'
|
|
125
|
+
puts ''
|
|
126
|
+
puts 'Examples:'
|
|
127
|
+
puts ' dam s3-share appydave b70 video.mp4'
|
|
128
|
+
puts ' dam s3-share appydave b70 video.mp4 --expires 24h'
|
|
129
|
+
puts ' dam s3-share appydave b70 video.mp4 --download'
|
|
130
|
+
puts ' dam s3-share voz boy-baker final-edit.mov --expires 3d --download'
|
|
131
|
+
exit 1
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Appydave
|
|
4
|
+
module Tools
|
|
5
|
+
module Dam
|
|
6
|
+
# Encapsulates S3 scan logic: single-brand and all-brands scanning
|
|
7
|
+
class S3ScanCommand
|
|
8
|
+
# Scan a single brand's S3 bucket and update its manifest
|
|
9
|
+
def scan_single(brand_key)
|
|
10
|
+
puts "🔄 Scanning S3 for #{brand_key}..."
|
|
11
|
+
puts ''
|
|
12
|
+
|
|
13
|
+
scanner = Appydave::Tools::Dam::S3Scanner.new(brand_key)
|
|
14
|
+
|
|
15
|
+
# Get brand info for S3 path
|
|
16
|
+
Appydave::Tools::Configuration::Config.configure
|
|
17
|
+
brand_info = Appydave::Tools::Configuration::Config.brands.get_brand(brand_key)
|
|
18
|
+
bucket = brand_info.aws.s3_bucket
|
|
19
|
+
prefix = brand_info.aws.s3_prefix
|
|
20
|
+
region = brand_info.aws.region
|
|
21
|
+
|
|
22
|
+
# Spinner characters for progress
|
|
23
|
+
spinner_chars = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏']
|
|
24
|
+
spinner_index = 0
|
|
25
|
+
|
|
26
|
+
print "🔍 Scanning s3://#{bucket}/#{prefix}\n"
|
|
27
|
+
print ' Scanning projects... '
|
|
28
|
+
|
|
29
|
+
# Scan all projects with progress callback
|
|
30
|
+
results = scanner.scan_all_projects(show_progress: false) do |current, total|
|
|
31
|
+
print "\r Scanning projects... #{spinner_chars[spinner_index]} (#{current}/#{total})"
|
|
32
|
+
spinner_index = (spinner_index + 1) % spinner_chars.length
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
print "\r Scanning projects... ✓ (#{results.size} found)\n"
|
|
36
|
+
puts ''
|
|
37
|
+
|
|
38
|
+
if results.empty?
|
|
39
|
+
puts "⚠️ No projects found in S3 for #{brand_key}"
|
|
40
|
+
puts ' This may indicate:'
|
|
41
|
+
puts ' - No files uploaded to S3 yet'
|
|
42
|
+
puts ' - S3 bucket or prefix misconfigured'
|
|
43
|
+
puts ' - AWS credentials issue'
|
|
44
|
+
return
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Load existing manifest
|
|
48
|
+
brand_path = Appydave::Tools::Dam::Config.brand_path(brand_key)
|
|
49
|
+
manifest_path = File.join(brand_path, 'projects.json')
|
|
50
|
+
|
|
51
|
+
unless File.exist?(manifest_path)
|
|
52
|
+
puts "❌ Manifest not found: #{manifest_path}"
|
|
53
|
+
puts " Run: dam manifest #{brand_key}"
|
|
54
|
+
puts " Then retry: dam s3-scan #{brand_key}"
|
|
55
|
+
exit 1
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
manifest = JSON.parse(File.read(manifest_path), symbolize_names: true)
|
|
59
|
+
|
|
60
|
+
# Identify matched and orphaned S3 projects
|
|
61
|
+
local_project_ids = manifest[:projects].map { |p| p[:id] }
|
|
62
|
+
matched_projects = results.slice(*local_project_ids)
|
|
63
|
+
orphaned_projects = results.reject { |project_id, _| local_project_ids.include?(project_id) }
|
|
64
|
+
|
|
65
|
+
# Merge S3 scan data into manifest for matched projects
|
|
66
|
+
updated_count = 0
|
|
67
|
+
manifest[:projects].each do |project|
|
|
68
|
+
project_id = project[:id]
|
|
69
|
+
s3_data = results[project_id]
|
|
70
|
+
next unless s3_data
|
|
71
|
+
|
|
72
|
+
project[:storage][:s3] = s3_data
|
|
73
|
+
updated_count += 1
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Update timestamp and note
|
|
77
|
+
manifest[:config][:last_updated] = Time.now.utc.iso8601
|
|
78
|
+
manifest[:config][:note] = 'Auto-generated manifest with S3 scan data. Regenerate with: dam s3-scan'
|
|
79
|
+
|
|
80
|
+
# Write updated manifest
|
|
81
|
+
File.write(manifest_path, JSON.pretty_generate(manifest))
|
|
82
|
+
|
|
83
|
+
# Add local sync status to matched projects
|
|
84
|
+
Appydave::Tools::Dam::LocalSyncStatus.enrich!(matched_projects, brand_key)
|
|
85
|
+
|
|
86
|
+
# Display table
|
|
87
|
+
display_table(matched_projects, orphaned_projects, bucket, prefix, region)
|
|
88
|
+
|
|
89
|
+
# Summary
|
|
90
|
+
total_manifest_projects = manifest[:projects].size
|
|
91
|
+
missing_count = total_manifest_projects - matched_projects.size
|
|
92
|
+
|
|
93
|
+
puts ''
|
|
94
|
+
puts 'ℹ️ Summary:'
|
|
95
|
+
puts " • Updated #{updated_count} projects in manifest"
|
|
96
|
+
puts " • #{missing_count} local project(s) not yet uploaded to S3" if missing_count.positive?
|
|
97
|
+
puts " • Manifest: #{manifest_path}"
|
|
98
|
+
puts ''
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# Scan all brands' S3 buckets
|
|
102
|
+
def scan_all
|
|
103
|
+
Appydave::Tools::Configuration::Config.configure
|
|
104
|
+
brands_config = Appydave::Tools::Configuration::Config.brands
|
|
105
|
+
|
|
106
|
+
results = []
|
|
107
|
+
brands_config.brands.each do |brand_info|
|
|
108
|
+
brand_key = brand_info.key
|
|
109
|
+
puts ''
|
|
110
|
+
puts '=' * 60
|
|
111
|
+
|
|
112
|
+
begin
|
|
113
|
+
scan_single(brand_key)
|
|
114
|
+
results << { brand: brand_key, success: true }
|
|
115
|
+
rescue StandardError => e
|
|
116
|
+
puts "❌ Failed to scan #{brand_key}: #{e.message}"
|
|
117
|
+
results << { brand: brand_key, success: false, error: e.message }
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
puts ''
|
|
122
|
+
puts '=' * 60
|
|
123
|
+
puts '📋 Summary - S3 Scans:'
|
|
124
|
+
puts ''
|
|
125
|
+
|
|
126
|
+
successful, failed = results.partition { |r| r[:success] }
|
|
127
|
+
|
|
128
|
+
successful.each do |result|
|
|
129
|
+
brand_display = result[:brand].ljust(15)
|
|
130
|
+
puts "✅ #{brand_display} Scanned successfully"
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
failed.each do |result|
|
|
134
|
+
brand_display = result[:brand].ljust(15)
|
|
135
|
+
puts "❌ #{brand_display} #{result[:error]}"
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
puts ''
|
|
139
|
+
puts "Total brands scanned: #{successful.size}/#{results.size}"
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
private
|
|
143
|
+
|
|
144
|
+
# Display S3 scan results in table format
|
|
145
|
+
# rubocop:disable Style/FormatStringToken
|
|
146
|
+
def display_table(matched_projects, orphaned_projects, bucket, prefix, region)
|
|
147
|
+
puts '✅ S3 Projects Report'
|
|
148
|
+
puts ''
|
|
149
|
+
puts 'PROJECT FILES SIZE LOCAL S3 MODIFIED'
|
|
150
|
+
puts '-' * 92
|
|
151
|
+
|
|
152
|
+
# Display matched projects first (sorted alphabetically)
|
|
153
|
+
matched_projects.sort.each do |project_id, data|
|
|
154
|
+
files = data[:file_count].to_s.rjust(5)
|
|
155
|
+
size = Appydave::Tools::Dam::FileHelper.format_size(data[:total_bytes]).rjust(10)
|
|
156
|
+
local_status = Appydave::Tools::Dam::LocalSyncStatus.format(data[:local_status], data[:local_file_count], data[:file_count])
|
|
157
|
+
modified = data[:last_modified] ? Time.parse(data[:last_modified]).strftime('%Y-%m-%d %H:%M') : 'N/A'
|
|
158
|
+
|
|
159
|
+
puts format('%-36s %5s %10s %-9s %s', project_id, files, size, local_status, modified)
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
# Display orphaned projects (sorted alphabetically)
|
|
163
|
+
return if orphaned_projects.empty?
|
|
164
|
+
|
|
165
|
+
puts '-' * 92
|
|
166
|
+
orphaned_projects.sort.each do |project_id, data|
|
|
167
|
+
files = data[:file_count].to_s.rjust(5)
|
|
168
|
+
size = Appydave::Tools::Dam::FileHelper.format_size(data[:total_bytes]).rjust(10)
|
|
169
|
+
local_status = 'N/A'
|
|
170
|
+
modified = data[:last_modified] ? Time.parse(data[:last_modified]).strftime('%Y-%m-%d %H:%M') : 'N/A'
|
|
171
|
+
|
|
172
|
+
puts format('%-36s %5s %10s %-9s %s', project_id, files, size, local_status, modified)
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
puts ''
|
|
176
|
+
folder_word = orphaned_projects.size > 1 ? 'folders' : 'folder'
|
|
177
|
+
puts "⚠️ #{orphaned_projects.size} orphaned #{folder_word} found (no local project)"
|
|
178
|
+
|
|
179
|
+
orphaned_projects.sort.each do |project_id, _data|
|
|
180
|
+
# Build AWS Console URL
|
|
181
|
+
project_prefix = "#{prefix}#{project_id}/"
|
|
182
|
+
console_url = "https://#{region}.console.aws.amazon.com/s3/buckets/#{bucket}?prefix=#{project_prefix}®ion=#{region}"
|
|
183
|
+
puts " → #{project_id}"
|
|
184
|
+
puts " #{console_url}"
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
# rubocop:enable Style/FormatStringToken
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
end
|
data/lib/appydave/tools.rb
CHANGED
|
@@ -79,6 +79,8 @@ require 'appydave/tools/dam/repo_status'
|
|
|
79
79
|
require 'appydave/tools/dam/repo_sync'
|
|
80
80
|
require 'appydave/tools/dam/repo_push'
|
|
81
81
|
require 'appydave/tools/dam/local_sync_status'
|
|
82
|
+
require 'appydave/tools/dam/s3_scan_command'
|
|
83
|
+
require 'appydave/tools/dam/s3_arg_parser'
|
|
82
84
|
|
|
83
85
|
require 'appydave/tools/jump/path_validator'
|
|
84
86
|
require 'appydave/tools/jump/location'
|
data/package.json
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: appydave-tools
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.76.
|
|
4
|
+
version: 0.76.7
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- David Cruwys
|
|
@@ -361,7 +361,9 @@ files:
|
|
|
361
361
|
- lib/appydave/tools/dam/repo_push.rb
|
|
362
362
|
- lib/appydave/tools/dam/repo_status.rb
|
|
363
363
|
- lib/appydave/tools/dam/repo_sync.rb
|
|
364
|
+
- lib/appydave/tools/dam/s3_arg_parser.rb
|
|
364
365
|
- lib/appydave/tools/dam/s3_operations.rb
|
|
366
|
+
- lib/appydave/tools/dam/s3_scan_command.rb
|
|
365
367
|
- lib/appydave/tools/dam/s3_scanner.rb
|
|
366
368
|
- lib/appydave/tools/dam/share_operations.rb
|
|
367
369
|
- lib/appydave/tools/dam/ssd_status.rb
|