appydave-tools 0.19.0 → 0.20.0
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 +7 -0
- data/bin/dam +110 -0
- data/docs/dam/usage.md +138 -1
- data/lib/appydave/tools/dam/repo_push.rb +131 -0
- data/lib/appydave/tools/dam/repo_status.rb +140 -0
- data/lib/appydave/tools/dam/repo_sync.rb +122 -0
- data/lib/appydave/tools/dam/status.rb +278 -0
- data/lib/appydave/tools/version.rb +1 -1
- data/lib/appydave/tools.rb +4 -0
- data/package.json +1 -1
- metadata +5 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: fa0d28f2da43b19537700a122baaea2401ea5c7b545d687a1bff64150d1c7d88
|
|
4
|
+
data.tar.gz: 98b8575d8af3b09e0dbc025b076d9b221d0d5b28705ee714a2483f74022c73c6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2f3c69c161ac3b1ca8642db8d1f6a15317510956ffe396635d6bf2f49e1be6bc6b22c4b5b9e9694b9b40ffbb9214da8487979078740a68a0b2dcec7c07a42ba1
|
|
7
|
+
data.tar.gz: de05f01bba2420b7c287cd28ac499ca56af5b7277c88522d867280e27be99d821baf2cb9d389beefe0c3e6573b6eee6095c0eafdd1a2806f1e49ec782f0de54f
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
# [0.19.0](https://github.com/appydave/appydave-tools/compare/v0.18.5...v0.19.0) (2025-11-10)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* Phase 1: add git_remote, S3 tracking, and hasStorylineJson to manifest ([4622271](https://github.com/appydave/appydave-tools/commit/4622271a9e1a01a7145981db4837ed9b69e8f721))
|
|
7
|
+
|
|
1
8
|
## [0.18.5](https://github.com/appydave/appydave-tools/compare/v0.18.4...v0.18.5) (2025-11-10)
|
|
2
9
|
|
|
3
10
|
|
data/bin/dam
CHANGED
|
@@ -13,6 +13,7 @@ class VatCLI
|
|
|
13
13
|
@commands = {
|
|
14
14
|
'help' => method(:help_command),
|
|
15
15
|
'list' => method(:list_command),
|
|
16
|
+
'status' => method(:status_command),
|
|
16
17
|
's3-up' => method(:s3_up_command),
|
|
17
18
|
's3-down' => method(:s3_down_command),
|
|
18
19
|
's3-status' => method(:s3_status_command),
|
|
@@ -21,6 +22,9 @@ class VatCLI
|
|
|
21
22
|
'archive' => method(:archive_command),
|
|
22
23
|
'manifest' => method(:manifest_command),
|
|
23
24
|
'sync-ssd' => method(:sync_ssd_command),
|
|
25
|
+
'repo-status' => method(:repo_status_command),
|
|
26
|
+
'repo-sync' => method(:repo_sync_command),
|
|
27
|
+
'repo-push' => method(:repo_push_command),
|
|
24
28
|
# Deprecated aliases (for backward compatibility)
|
|
25
29
|
's3-cleanup' => method(:s3_cleanup_remote_command),
|
|
26
30
|
'cleanup-local' => method(:s3_cleanup_local_command)
|
|
@@ -262,6 +266,112 @@ class VatCLI
|
|
|
262
266
|
exit 1
|
|
263
267
|
end
|
|
264
268
|
|
|
269
|
+
# Show unified status (local/S3/SSD/git)
|
|
270
|
+
def status_command(args)
|
|
271
|
+
args = args.reject { |arg| arg.start_with?('--') }
|
|
272
|
+
brand_arg = args[0]
|
|
273
|
+
project_arg = args[1]
|
|
274
|
+
|
|
275
|
+
if brand_arg.nil?
|
|
276
|
+
# Auto-detect from PWD
|
|
277
|
+
brand, project_id = Appydave::Tools::Dam::ProjectResolver.detect_from_pwd
|
|
278
|
+
if brand.nil?
|
|
279
|
+
puts '❌ Could not auto-detect brand from current directory'
|
|
280
|
+
puts 'Usage: dam status <brand> [project]'
|
|
281
|
+
exit 1
|
|
282
|
+
end
|
|
283
|
+
brand_key = brand
|
|
284
|
+
else
|
|
285
|
+
brand_key = brand_arg
|
|
286
|
+
project_id = project_arg ? Appydave::Tools::Dam::ProjectResolver.resolve(brand_arg, project_arg) : nil
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
status = Appydave::Tools::Dam::Status.new(brand_key, project_id)
|
|
290
|
+
status.show
|
|
291
|
+
rescue StandardError => e
|
|
292
|
+
puts "❌ Error: #{e.message}"
|
|
293
|
+
exit 1
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
# Show git status for brand repositories
|
|
297
|
+
def repo_status_command(args)
|
|
298
|
+
all = args.include?('--all')
|
|
299
|
+
args = args.reject { |arg| arg.start_with?('--') }
|
|
300
|
+
brand_arg = args[0]
|
|
301
|
+
|
|
302
|
+
if all
|
|
303
|
+
# Show status for all brands
|
|
304
|
+
Appydave::Tools::Dam::RepoStatus.new.show_all
|
|
305
|
+
elsif brand_arg
|
|
306
|
+
# Show status for specific brand
|
|
307
|
+
Appydave::Tools::Dam::RepoStatus.new(brand_arg).show
|
|
308
|
+
else
|
|
309
|
+
puts 'Usage: dam repo-status <brand> [--all]'
|
|
310
|
+
puts ''
|
|
311
|
+
puts 'Check git status for brand repositories.'
|
|
312
|
+
puts ''
|
|
313
|
+
puts 'Examples:'
|
|
314
|
+
puts ' dam repo-status appydave # Show git status for AppyDave brand'
|
|
315
|
+
puts ' dam repo-status --all # Show git status for all brands'
|
|
316
|
+
exit 1
|
|
317
|
+
end
|
|
318
|
+
rescue StandardError => e
|
|
319
|
+
puts "❌ Error: #{e.message}"
|
|
320
|
+
exit 1
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
# Sync (pull) brand repositories
|
|
324
|
+
def repo_sync_command(args)
|
|
325
|
+
all = args.include?('--all')
|
|
326
|
+
args = args.reject { |arg| arg.start_with?('--') }
|
|
327
|
+
brand_arg = args[0]
|
|
328
|
+
|
|
329
|
+
if all
|
|
330
|
+
# Sync all brands
|
|
331
|
+
Appydave::Tools::Dam::RepoSync.new.sync_all
|
|
332
|
+
elsif brand_arg
|
|
333
|
+
# Sync specific brand
|
|
334
|
+
Appydave::Tools::Dam::RepoSync.new(brand_arg).sync
|
|
335
|
+
else
|
|
336
|
+
puts 'Usage: dam repo-sync <brand> [--all]'
|
|
337
|
+
puts ''
|
|
338
|
+
puts 'Pull updates for brand repositories.'
|
|
339
|
+
puts ''
|
|
340
|
+
puts 'Examples:'
|
|
341
|
+
puts ' dam repo-sync appydave # Pull updates for AppyDave brand'
|
|
342
|
+
puts ' dam repo-sync --all # Pull updates for all brands'
|
|
343
|
+
exit 1
|
|
344
|
+
end
|
|
345
|
+
rescue StandardError => e
|
|
346
|
+
puts "❌ Error: #{e.message}"
|
|
347
|
+
exit 1
|
|
348
|
+
end
|
|
349
|
+
|
|
350
|
+
# Push brand repository changes
|
|
351
|
+
def repo_push_command(args)
|
|
352
|
+
args = args.reject { |arg| arg.start_with?('--') }
|
|
353
|
+
brand_arg = args[0]
|
|
354
|
+
project_arg = args[1]
|
|
355
|
+
|
|
356
|
+
if brand_arg.nil?
|
|
357
|
+
puts 'Usage: dam repo-push <brand> [project]'
|
|
358
|
+
puts ''
|
|
359
|
+
puts 'Push changes for brand repository.'
|
|
360
|
+
puts ''
|
|
361
|
+
puts 'Examples:'
|
|
362
|
+
puts ' dam repo-push appydave # Push all changes for AppyDave brand'
|
|
363
|
+
puts ' dam repo-push appydave b65 # Validate project exists before push'
|
|
364
|
+
exit 1
|
|
365
|
+
end
|
|
366
|
+
|
|
367
|
+
project_id = project_arg ? Appydave::Tools::Dam::ProjectResolver.resolve(brand_arg, project_arg) : nil
|
|
368
|
+
|
|
369
|
+
Appydave::Tools::Dam::RepoPush.new(brand_arg, project_id).push
|
|
370
|
+
rescue StandardError => e
|
|
371
|
+
puts "❌ Error: #{e.message}"
|
|
372
|
+
exit 1
|
|
373
|
+
end
|
|
374
|
+
|
|
265
375
|
# Parse S3 command arguments
|
|
266
376
|
def parse_s3_args(args, command)
|
|
267
377
|
dry_run = args.include?('--dry-run')
|
data/docs/dam/usage.md
CHANGED
|
@@ -154,6 +154,143 @@ dam list appydave 'b6*'
|
|
|
154
154
|
# Output: Lists b60, b61, b62...b69 projects
|
|
155
155
|
```
|
|
156
156
|
|
|
157
|
+
### Status & Monitoring
|
|
158
|
+
|
|
159
|
+
#### `dam status [brand] [project]`
|
|
160
|
+
Show unified status for project or brand (local, S3, SSD, git).
|
|
161
|
+
|
|
162
|
+
**Brand status:**
|
|
163
|
+
```bash
|
|
164
|
+
dam status appydave
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
**Output:**
|
|
168
|
+
```
|
|
169
|
+
📊 Brand Status: v-appydave
|
|
170
|
+
📡 Git Remote: git@github.com:klueless-io/v-appydave.git
|
|
171
|
+
|
|
172
|
+
🌿 Branch: main
|
|
173
|
+
📡 Remote: git@github.com:klueless-io/v-appydave.git
|
|
174
|
+
✓ Working directory clean
|
|
175
|
+
✓ Up to date with remote
|
|
176
|
+
|
|
177
|
+
📋 Manifest Summary:
|
|
178
|
+
Total projects: 114
|
|
179
|
+
Local: 74
|
|
180
|
+
S3 staging: 12
|
|
181
|
+
SSD backup: 67
|
|
182
|
+
|
|
183
|
+
Storyline projects: 3
|
|
184
|
+
FliVideo projects: 111
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
**Project status:**
|
|
188
|
+
```bash
|
|
189
|
+
dam status appydave b65
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
**Output:**
|
|
193
|
+
```
|
|
194
|
+
📊 Status: v-appydave/b65-guy-monroe-marketing-plan
|
|
195
|
+
|
|
196
|
+
Storage:
|
|
197
|
+
📁 Local: ✓ exists (flat structure)
|
|
198
|
+
Heavy files: no
|
|
199
|
+
Light files: yes
|
|
200
|
+
|
|
201
|
+
☁️ S3 Staging: ✓ exists
|
|
202
|
+
Local staging files: 3
|
|
203
|
+
|
|
204
|
+
💾 SSD Backup: ✓ exists
|
|
205
|
+
Path: b65-guy-monroe-marketing-plan
|
|
206
|
+
|
|
207
|
+
Git:
|
|
208
|
+
🌿 Branch: main
|
|
209
|
+
📡 Remote: git@github.com:klueless-io/v-appydave.git
|
|
210
|
+
↕️ Status: Clean working directory
|
|
211
|
+
🔄 Sync: Up to date
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
**Auto-detect from PWD:**
|
|
215
|
+
```bash
|
|
216
|
+
cd ~/dev/video-projects/v-appydave/b65-project
|
|
217
|
+
dam status
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### Git Repository Commands
|
|
221
|
+
|
|
222
|
+
#### `dam repo-status [brand] [--all]`
|
|
223
|
+
Check git status for brand repositories.
|
|
224
|
+
|
|
225
|
+
```bash
|
|
226
|
+
# Single brand
|
|
227
|
+
dam repo-status appydave
|
|
228
|
+
|
|
229
|
+
# All brands
|
|
230
|
+
dam repo-status --all
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
**Output:**
|
|
234
|
+
```
|
|
235
|
+
🔍 Git Status: v-appydave
|
|
236
|
+
|
|
237
|
+
🌿 Branch: main
|
|
238
|
+
📡 Remote: git@github.com:klueless-io/v-appydave.git
|
|
239
|
+
✓ Working directory clean
|
|
240
|
+
✓ Up to date with remote
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
#### `dam repo-sync [brand] [--all]`
|
|
244
|
+
Pull updates for brand repositories.
|
|
245
|
+
|
|
246
|
+
```bash
|
|
247
|
+
# Single brand
|
|
248
|
+
dam repo-sync appydave
|
|
249
|
+
|
|
250
|
+
# All brands
|
|
251
|
+
dam repo-sync --all
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
**Output:**
|
|
255
|
+
```
|
|
256
|
+
🔄 Syncing: v-appydave
|
|
257
|
+
|
|
258
|
+
✓ Already up to date
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
**Safety features:**
|
|
262
|
+
- Skips brands with uncommitted changes (prevents conflicts)
|
|
263
|
+
- Shows summary when syncing multiple brands
|
|
264
|
+
|
|
265
|
+
#### `dam repo-push [brand] [project]`
|
|
266
|
+
Push changes for brand repository.
|
|
267
|
+
|
|
268
|
+
```bash
|
|
269
|
+
# Push all changes
|
|
270
|
+
dam repo-push appydave
|
|
271
|
+
|
|
272
|
+
# Validate project exists before push
|
|
273
|
+
dam repo-push appydave b65
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
**Output:**
|
|
277
|
+
```
|
|
278
|
+
📤 Pushing: v-appydave
|
|
279
|
+
|
|
280
|
+
✓ Project validated: b65-guy-monroe-marketing-plan
|
|
281
|
+
|
|
282
|
+
📤 Pushing 2 commit(s)...
|
|
283
|
+
|
|
284
|
+
✓ Push successful
|
|
285
|
+
|
|
286
|
+
main -> main
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
**Safety features:**
|
|
290
|
+
- Warns if uncommitted changes detected
|
|
291
|
+
- Optional project validation against manifest
|
|
292
|
+
- Shows push summary
|
|
293
|
+
|
|
157
294
|
### S3 Sync Commands
|
|
158
295
|
|
|
159
296
|
#### `dam s3-up [brand] [project] [--dry-run]`
|
|
@@ -649,4 +786,4 @@ dam s3-up appydave b65
|
|
|
649
786
|
|
|
650
787
|
---
|
|
651
788
|
|
|
652
|
-
**Last Updated:** 2025-11-
|
|
789
|
+
**Last Updated:** 2025-11-10
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Appydave
|
|
4
|
+
module Tools
|
|
5
|
+
module Dam
|
|
6
|
+
# Push brand repository changes
|
|
7
|
+
class RepoPush
|
|
8
|
+
attr_reader :brand, :project_id, :brand_info, :brand_path
|
|
9
|
+
|
|
10
|
+
def initialize(brand, project_id = nil)
|
|
11
|
+
@brand_info = load_brand_info(brand)
|
|
12
|
+
@brand = @brand_info.key
|
|
13
|
+
@brand_path = Config.brand_path(@brand)
|
|
14
|
+
@project_id = project_id
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Push changes
|
|
18
|
+
def push
|
|
19
|
+
puts "📤 Pushing: v-#{brand}"
|
|
20
|
+
puts ''
|
|
21
|
+
|
|
22
|
+
unless git_repo?
|
|
23
|
+
puts "❌ Not a git repository: #{brand_path}"
|
|
24
|
+
return
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# If project specified, validate it exists in manifest
|
|
28
|
+
validate_project if project_id
|
|
29
|
+
|
|
30
|
+
perform_push
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
private
|
|
34
|
+
|
|
35
|
+
def load_brand_info(brand)
|
|
36
|
+
Appydave::Tools::Configuration::Config.configure
|
|
37
|
+
Appydave::Tools::Configuration::Config.brands.get_brand(brand)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def git_repo?
|
|
41
|
+
git_dir = File.join(brand_path, '.git')
|
|
42
|
+
Dir.exist?(git_dir)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def validate_project
|
|
46
|
+
manifest = load_manifest
|
|
47
|
+
unless manifest
|
|
48
|
+
puts '⚠️ Warning: Manifest not found'
|
|
49
|
+
puts ' Continuing with push (manifest is optional for validation)'
|
|
50
|
+
return
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Resolve short name if needed (b65 -> b65-full-name)
|
|
54
|
+
resolved = ProjectResolver.new.resolve(brand, project_id)
|
|
55
|
+
|
|
56
|
+
project_entry = manifest[:projects].find { |p| p[:id] == resolved }
|
|
57
|
+
if project_entry
|
|
58
|
+
puts "✓ Project validated: #{resolved}"
|
|
59
|
+
else
|
|
60
|
+
puts "⚠️ Warning: Project '#{resolved}' not found in manifest"
|
|
61
|
+
puts ' Continuing with push (manifest may be outdated)'
|
|
62
|
+
end
|
|
63
|
+
puts ''
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def load_manifest
|
|
67
|
+
manifest_path = File.join(brand_path, 'projects.json')
|
|
68
|
+
return nil unless File.exist?(manifest_path)
|
|
69
|
+
|
|
70
|
+
JSON.parse(File.read(manifest_path), symbolize_names: true)
|
|
71
|
+
rescue JSON::ParserError
|
|
72
|
+
nil
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def perform_push
|
|
76
|
+
# Check for uncommitted changes
|
|
77
|
+
if uncommitted_changes?
|
|
78
|
+
puts '⚠️ Warning: Uncommitted changes detected'
|
|
79
|
+
puts ''
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Check if ahead of remote
|
|
83
|
+
ahead = commits_ahead
|
|
84
|
+
if ahead.zero?
|
|
85
|
+
puts '✓ Nothing to push (up to date with remote)'
|
|
86
|
+
return
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
puts "📤 Pushing #{ahead} commit(s)..."
|
|
90
|
+
puts ''
|
|
91
|
+
|
|
92
|
+
# Perform git push
|
|
93
|
+
output = `git -C "#{brand_path}" push 2>&1`
|
|
94
|
+
exit_code = $CHILD_STATUS.exitstatus
|
|
95
|
+
|
|
96
|
+
if exit_code.zero?
|
|
97
|
+
puts '✓ Push successful'
|
|
98
|
+
puts ''
|
|
99
|
+
show_push_summary(output)
|
|
100
|
+
else
|
|
101
|
+
puts '❌ Push failed:'
|
|
102
|
+
puts output
|
|
103
|
+
exit 1
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def uncommitted_changes?
|
|
108
|
+
output = `git -C "#{brand_path}" status --porcelain 2>/dev/null`.strip
|
|
109
|
+
!output.empty?
|
|
110
|
+
rescue StandardError
|
|
111
|
+
false
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def commits_ahead
|
|
115
|
+
`git -C "#{brand_path}" rev-list --count @{upstream}..HEAD 2>/dev/null`.strip.to_i
|
|
116
|
+
rescue StandardError
|
|
117
|
+
0
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def show_push_summary(output)
|
|
121
|
+
# Extract useful info from git push output
|
|
122
|
+
lines = output.lines.map(&:strip).reject(&:empty?)
|
|
123
|
+
|
|
124
|
+
lines.each do |line|
|
|
125
|
+
puts " #{line}" if line.include?('->') || line.include?('branch')
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Appydave
|
|
4
|
+
module Tools
|
|
5
|
+
module Dam
|
|
6
|
+
# Show git status for brand repositories
|
|
7
|
+
class RepoStatus
|
|
8
|
+
attr_reader :brand, :brand_info, :brand_path
|
|
9
|
+
|
|
10
|
+
def initialize(brand = nil)
|
|
11
|
+
return unless brand
|
|
12
|
+
|
|
13
|
+
@brand_info = load_brand_info(brand)
|
|
14
|
+
@brand = @brand_info.key
|
|
15
|
+
@brand_path = Config.brand_path(@brand)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Show status for single brand
|
|
19
|
+
def show
|
|
20
|
+
puts "🔍 Git Status: v-#{brand}"
|
|
21
|
+
puts ''
|
|
22
|
+
|
|
23
|
+
unless git_repo?
|
|
24
|
+
puts "❌ Not a git repository: #{brand_path}"
|
|
25
|
+
return
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
show_git_info
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Show status for all brands
|
|
32
|
+
def show_all
|
|
33
|
+
puts '🔍 Git Status - All Brands'
|
|
34
|
+
puts ''
|
|
35
|
+
|
|
36
|
+
Appydave::Tools::Configuration::Config.configure
|
|
37
|
+
brands_config = Appydave::Tools::Configuration::Config.brands
|
|
38
|
+
|
|
39
|
+
brands_config.brands.each do |brand_info|
|
|
40
|
+
@brand_info = brand_info
|
|
41
|
+
@brand = brand_info.key
|
|
42
|
+
@brand_path = Config.brand_path(@brand)
|
|
43
|
+
|
|
44
|
+
next unless git_repo?
|
|
45
|
+
|
|
46
|
+
puts "📦 v-#{brand}"
|
|
47
|
+
show_git_info(indent: ' ')
|
|
48
|
+
puts ''
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
private
|
|
53
|
+
|
|
54
|
+
def load_brand_info(brand)
|
|
55
|
+
Appydave::Tools::Configuration::Config.configure
|
|
56
|
+
Appydave::Tools::Configuration::Config.brands.get_brand(brand)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def git_repo?
|
|
60
|
+
git_dir = File.join(brand_path, '.git')
|
|
61
|
+
Dir.exist?(git_dir)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def show_git_info(indent: '')
|
|
65
|
+
status = git_status_info
|
|
66
|
+
|
|
67
|
+
puts "#{indent}🌿 Branch: #{status[:branch]}"
|
|
68
|
+
puts "#{indent}📡 Remote: #{status[:remote]}" if status[:remote]
|
|
69
|
+
|
|
70
|
+
if status[:modified_count].positive? || status[:untracked_count].positive?
|
|
71
|
+
puts "#{indent}↕️ Changes: #{status[:modified_count]} modified, #{status[:untracked_count]} untracked"
|
|
72
|
+
else
|
|
73
|
+
puts "#{indent}✓ Working directory clean"
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
if status[:ahead].positive? || status[:behind].positive?
|
|
77
|
+
puts "#{indent}🔄 Sync: #{sync_status_text(status[:ahead], status[:behind])}"
|
|
78
|
+
else
|
|
79
|
+
puts "#{indent}✓ Up to date with remote"
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def sync_status_text(ahead, behind)
|
|
84
|
+
parts = []
|
|
85
|
+
parts << "#{ahead} ahead" if ahead.positive?
|
|
86
|
+
parts << "#{behind} behind" if behind.positive?
|
|
87
|
+
parts.join(', ')
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def git_status_info
|
|
91
|
+
{
|
|
92
|
+
branch: current_branch,
|
|
93
|
+
remote: remote_url,
|
|
94
|
+
modified_count: modified_files_count,
|
|
95
|
+
untracked_count: untracked_files_count,
|
|
96
|
+
ahead: commits_ahead,
|
|
97
|
+
behind: commits_behind
|
|
98
|
+
}
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def current_branch
|
|
102
|
+
`git -C "#{brand_path}" rev-parse --abbrev-ref HEAD 2>/dev/null`.strip
|
|
103
|
+
rescue StandardError
|
|
104
|
+
'unknown'
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def remote_url
|
|
108
|
+
result = `git -C "#{brand_path}" remote get-url origin 2>/dev/null`.strip
|
|
109
|
+
result.empty? ? nil : result
|
|
110
|
+
rescue StandardError
|
|
111
|
+
nil
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def modified_files_count
|
|
115
|
+
`git -C "#{brand_path}" status --porcelain 2>/dev/null | grep -E "^.M|^M" | wc -l`.strip.to_i
|
|
116
|
+
rescue StandardError
|
|
117
|
+
0
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def untracked_files_count
|
|
121
|
+
`git -C "#{brand_path}" status --porcelain 2>/dev/null | grep -E "^\\?\\?" | wc -l`.strip.to_i
|
|
122
|
+
rescue StandardError
|
|
123
|
+
0
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def commits_ahead
|
|
127
|
+
`git -C "#{brand_path}" rev-list --count @{upstream}..HEAD 2>/dev/null`.strip.to_i
|
|
128
|
+
rescue StandardError
|
|
129
|
+
0
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def commits_behind
|
|
133
|
+
`git -C "#{brand_path}" rev-list --count HEAD..@{upstream} 2>/dev/null`.strip.to_i
|
|
134
|
+
rescue StandardError
|
|
135
|
+
0
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Appydave
|
|
4
|
+
module Tools
|
|
5
|
+
module Dam
|
|
6
|
+
# Sync (git pull) brand repositories
|
|
7
|
+
class RepoSync
|
|
8
|
+
attr_reader :brand, :brand_info, :brand_path
|
|
9
|
+
|
|
10
|
+
def initialize(brand = nil)
|
|
11
|
+
return unless brand
|
|
12
|
+
|
|
13
|
+
@brand_info = load_brand_info(brand)
|
|
14
|
+
@brand = @brand_info.key
|
|
15
|
+
@brand_path = Config.brand_path(@brand)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Sync single brand
|
|
19
|
+
def sync
|
|
20
|
+
puts "🔄 Syncing: v-#{brand}"
|
|
21
|
+
puts ''
|
|
22
|
+
|
|
23
|
+
unless git_repo?
|
|
24
|
+
puts "❌ Not a git repository: #{brand_path}"
|
|
25
|
+
return
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
perform_sync
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Sync all brands
|
|
32
|
+
def sync_all
|
|
33
|
+
puts '🔄 Syncing All Brands'
|
|
34
|
+
puts ''
|
|
35
|
+
|
|
36
|
+
Appydave::Tools::Configuration::Config.configure
|
|
37
|
+
brands_config = Appydave::Tools::Configuration::Config.brands
|
|
38
|
+
|
|
39
|
+
results = []
|
|
40
|
+
|
|
41
|
+
brands_config.brands.each do |brand_info|
|
|
42
|
+
@brand_info = brand_info
|
|
43
|
+
@brand = brand_info.key
|
|
44
|
+
@brand_path = Config.brand_path(@brand)
|
|
45
|
+
|
|
46
|
+
next unless git_repo?
|
|
47
|
+
|
|
48
|
+
puts "📦 v-#{brand}"
|
|
49
|
+
result = perform_sync(indent: ' ')
|
|
50
|
+
results << result
|
|
51
|
+
puts ''
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
show_summary(results)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
private
|
|
58
|
+
|
|
59
|
+
def load_brand_info(brand)
|
|
60
|
+
Appydave::Tools::Configuration::Config.configure
|
|
61
|
+
Appydave::Tools::Configuration::Config.brands.get_brand(brand)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def git_repo?
|
|
65
|
+
git_dir = File.join(brand_path, '.git')
|
|
66
|
+
Dir.exist?(git_dir)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def perform_sync(indent: '')
|
|
70
|
+
# Check for uncommitted changes
|
|
71
|
+
if uncommitted_changes?
|
|
72
|
+
puts "#{indent}⚠️ Uncommitted changes detected"
|
|
73
|
+
puts "#{indent} Skipping pull (would cause conflicts)"
|
|
74
|
+
return { brand: brand, status: 'skipped', reason: 'uncommitted changes' }
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Perform git pull
|
|
78
|
+
output = `git -C "#{brand_path}" pull 2>&1`
|
|
79
|
+
exit_code = $CHILD_STATUS.exitstatus
|
|
80
|
+
|
|
81
|
+
if exit_code.zero?
|
|
82
|
+
if output.include?('Already up to date')
|
|
83
|
+
puts "#{indent}✓ Already up to date"
|
|
84
|
+
{ brand: brand, status: 'current' }
|
|
85
|
+
else
|
|
86
|
+
puts "#{indent}✓ Updated successfully"
|
|
87
|
+
puts "#{indent} #{output.lines.first.strip}" if output.lines.any?
|
|
88
|
+
{ brand: brand, status: 'updated' }
|
|
89
|
+
end
|
|
90
|
+
else
|
|
91
|
+
puts "#{indent}❌ Pull failed: #{output.strip}"
|
|
92
|
+
{ brand: brand, status: 'error', reason: output.strip }
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def uncommitted_changes?
|
|
97
|
+
output = `git -C "#{brand_path}" status --porcelain 2>/dev/null`.strip
|
|
98
|
+
!output.empty?
|
|
99
|
+
rescue StandardError
|
|
100
|
+
false
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def show_summary(results)
|
|
104
|
+
puts '=' * 60
|
|
105
|
+
puts '📊 Sync Summary:'
|
|
106
|
+
puts ''
|
|
107
|
+
|
|
108
|
+
updated = results.count { |r| r[:status] == 'updated' }
|
|
109
|
+
current = results.count { |r| r[:status] == 'current' }
|
|
110
|
+
skipped = results.count { |r| r[:status] == 'skipped' }
|
|
111
|
+
errors = results.count { |r| r[:status] == 'error' }
|
|
112
|
+
|
|
113
|
+
puts " Total repos checked: #{results.size}"
|
|
114
|
+
puts " Updated: #{updated}"
|
|
115
|
+
puts " Already current: #{current}"
|
|
116
|
+
puts " Skipped: #{skipped}" if skipped.positive?
|
|
117
|
+
puts " Errors: #{errors}" if errors.positive?
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'json'
|
|
4
|
+
|
|
5
|
+
module Appydave
|
|
6
|
+
module Tools
|
|
7
|
+
module Dam
|
|
8
|
+
# Show unified status for video project (local, S3, SSD, git)
|
|
9
|
+
class Status
|
|
10
|
+
attr_reader :brand, :project_id, :brand_info, :brand_path, :project_path
|
|
11
|
+
|
|
12
|
+
def initialize(brand, project_id = nil)
|
|
13
|
+
@brand_info = load_brand_info(brand)
|
|
14
|
+
@brand = @brand_info.key
|
|
15
|
+
@brand_path = Config.brand_path(@brand)
|
|
16
|
+
@project_id = project_id
|
|
17
|
+
@project_path = project_id ? resolve_project_path(project_id) : nil
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Show status for project or brand
|
|
21
|
+
def show
|
|
22
|
+
if project_id
|
|
23
|
+
show_project_status
|
|
24
|
+
else
|
|
25
|
+
show_brand_status
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
def load_brand_info(brand)
|
|
32
|
+
Appydave::Tools::Configuration::Config.configure
|
|
33
|
+
Appydave::Tools::Configuration::Config.brands.get_brand(brand)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def resolve_project_path(project_id)
|
|
37
|
+
# Resolve short name if needed (b65 -> b65-full-name)
|
|
38
|
+
resolved = ProjectResolver.new.resolve(brand, project_id)
|
|
39
|
+
File.join(brand_path, resolved)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def show_project_status
|
|
43
|
+
puts "📊 Status: v-#{brand}/#{File.basename(project_path)}"
|
|
44
|
+
puts ''
|
|
45
|
+
|
|
46
|
+
manifest = load_manifest
|
|
47
|
+
project_entry = find_project_in_manifest(manifest)
|
|
48
|
+
|
|
49
|
+
unless project_entry
|
|
50
|
+
puts '❌ Project not found in manifest'
|
|
51
|
+
puts " Run: dam manifest #{brand}"
|
|
52
|
+
return
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
show_storage_status(project_entry)
|
|
56
|
+
show_git_status if git_repo?
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def show_brand_status
|
|
60
|
+
puts "📊 Brand Status: v-#{brand}"
|
|
61
|
+
puts ''
|
|
62
|
+
|
|
63
|
+
# Show git remote (with self-healing)
|
|
64
|
+
remote = Config.git_remote(brand)
|
|
65
|
+
if remote
|
|
66
|
+
puts "📡 Git Remote: #{remote}"
|
|
67
|
+
else
|
|
68
|
+
puts '📡 Git Remote: Not configured (not a git repository)'
|
|
69
|
+
end
|
|
70
|
+
puts ''
|
|
71
|
+
|
|
72
|
+
# Show git status
|
|
73
|
+
if git_repo?
|
|
74
|
+
show_brand_git_status
|
|
75
|
+
else
|
|
76
|
+
puts 'Git: Not a git repository'
|
|
77
|
+
end
|
|
78
|
+
puts ''
|
|
79
|
+
|
|
80
|
+
# Show manifest summary
|
|
81
|
+
manifest = load_manifest
|
|
82
|
+
if manifest
|
|
83
|
+
show_manifest_summary(manifest)
|
|
84
|
+
else
|
|
85
|
+
puts '❌ Manifest not found'
|
|
86
|
+
puts " Run: dam manifest #{brand}"
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def show_storage_status(project_entry)
|
|
91
|
+
puts 'Storage:'
|
|
92
|
+
|
|
93
|
+
# Local storage
|
|
94
|
+
show_local_status(project_entry)
|
|
95
|
+
|
|
96
|
+
# S3 staging (inferred - only show if exists)
|
|
97
|
+
show_s3_status(project_entry) if project_entry[:storage][:s3][:exists]
|
|
98
|
+
|
|
99
|
+
# SSD backup (inferred - only show if configured and exists)
|
|
100
|
+
show_ssd_status(project_entry) if brand_info.locations.ssd_backup &&
|
|
101
|
+
brand_info.locations.ssd_backup != 'NOT-SET' &&
|
|
102
|
+
project_entry[:storage][:ssd][:exists]
|
|
103
|
+
|
|
104
|
+
puts ''
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def show_local_status(project_entry)
|
|
108
|
+
local = project_entry[:storage][:local]
|
|
109
|
+
|
|
110
|
+
if local[:exists]
|
|
111
|
+
puts " 📁 Local: ✓ exists (#{local[:structure]} structure)"
|
|
112
|
+
puts " Heavy files: #{local[:has_heavy_files] ? 'yes' : 'no'}"
|
|
113
|
+
puts " Light files: #{local[:has_light_files] ? 'yes' : 'no'}"
|
|
114
|
+
else
|
|
115
|
+
puts ' 📁 Local: ✗ does not exist'
|
|
116
|
+
end
|
|
117
|
+
puts ''
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def show_s3_status(_project_entry)
|
|
121
|
+
puts ' ☁️ S3 Staging: ✓ exists'
|
|
122
|
+
|
|
123
|
+
# TODO: Query S3 for detailed status (files needing sync)
|
|
124
|
+
# For now, just show that s3-staging folder exists locally
|
|
125
|
+
s3_staging_path = File.join(project_path, 's3-staging')
|
|
126
|
+
if Dir.exist?(s3_staging_path)
|
|
127
|
+
file_count = Dir.glob(File.join(s3_staging_path, '*')).count
|
|
128
|
+
puts " Local staging files: #{file_count}"
|
|
129
|
+
end
|
|
130
|
+
puts ''
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def show_ssd_status(project_entry)
|
|
134
|
+
puts ' 💾 SSD Backup: ✓ exists'
|
|
135
|
+
puts " Path: #{project_entry[:storage][:ssd][:path]}"
|
|
136
|
+
puts ''
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def show_git_status
|
|
140
|
+
puts 'Git:'
|
|
141
|
+
|
|
142
|
+
status = git_status_info
|
|
143
|
+
|
|
144
|
+
puts " 🌿 Branch: #{status[:branch]}"
|
|
145
|
+
puts " 📡 Remote: #{status[:remote]}" if status[:remote]
|
|
146
|
+
|
|
147
|
+
if status[:modified_count].positive? || status[:untracked_count].positive?
|
|
148
|
+
puts " ↕️ Status: #{status[:modified_count]} modified, #{status[:untracked_count]} untracked"
|
|
149
|
+
else
|
|
150
|
+
puts ' ↕️ Status: Clean working directory'
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
if status[:ahead].positive? || status[:behind].positive?
|
|
154
|
+
puts " 🔄 Sync: #{sync_status_text(status[:ahead], status[:behind])}"
|
|
155
|
+
else
|
|
156
|
+
puts ' 🔄 Sync: Up to date'
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
puts ''
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def show_brand_git_status
|
|
163
|
+
status = git_status_info
|
|
164
|
+
|
|
165
|
+
puts "🌿 Branch: #{status[:branch]}"
|
|
166
|
+
puts "📡 Remote: #{status[:remote]}" if status[:remote]
|
|
167
|
+
|
|
168
|
+
if status[:modified_count].positive? || status[:untracked_count].positive?
|
|
169
|
+
puts "↕️ Changes: #{status[:modified_count]} modified, #{status[:untracked_count]} untracked"
|
|
170
|
+
else
|
|
171
|
+
puts '✓ Working directory clean'
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
if status[:ahead].positive? || status[:behind].positive?
|
|
175
|
+
puts "🔄 Sync: #{sync_status_text(status[:ahead], status[:behind])}"
|
|
176
|
+
else
|
|
177
|
+
puts '✓ Up to date with remote'
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
def show_manifest_summary(manifest)
|
|
182
|
+
puts '📋 Manifest Summary:'
|
|
183
|
+
puts " Total projects: #{manifest[:projects].size}"
|
|
184
|
+
|
|
185
|
+
local_count = manifest[:projects].count { |p| p[:storage][:local][:exists] }
|
|
186
|
+
s3_count = manifest[:projects].count { |p| p[:storage][:s3][:exists] }
|
|
187
|
+
ssd_count = manifest[:projects].count { |p| p[:storage][:ssd][:exists] }
|
|
188
|
+
|
|
189
|
+
puts " Local: #{local_count}"
|
|
190
|
+
puts " S3 staging: #{s3_count}"
|
|
191
|
+
puts " SSD backup: #{ssd_count}"
|
|
192
|
+
|
|
193
|
+
# Project types
|
|
194
|
+
storyline_count = manifest[:projects].count { |p| p[:hasStorylineJson] }
|
|
195
|
+
puts ''
|
|
196
|
+
puts " Storyline projects: #{storyline_count}"
|
|
197
|
+
puts " FliVideo projects: #{manifest[:projects].size - storyline_count}"
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
def sync_status_text(ahead, behind)
|
|
201
|
+
parts = []
|
|
202
|
+
parts << "#{ahead} ahead" if ahead.positive?
|
|
203
|
+
parts << "#{behind} behind" if behind.positive?
|
|
204
|
+
parts.join(', ')
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
def load_manifest
|
|
208
|
+
manifest_path = File.join(brand_path, 'projects.json')
|
|
209
|
+
return nil unless File.exist?(manifest_path)
|
|
210
|
+
|
|
211
|
+
JSON.parse(File.read(manifest_path), symbolize_names: true)
|
|
212
|
+
rescue JSON::ParserError
|
|
213
|
+
nil
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
def find_project_in_manifest(manifest)
|
|
217
|
+
return nil unless manifest
|
|
218
|
+
|
|
219
|
+
project_name = File.basename(project_path)
|
|
220
|
+
manifest[:projects].find { |p| p[:id] == project_name }
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
def git_repo?
|
|
224
|
+
git_dir = File.join(brand_path, '.git')
|
|
225
|
+
Dir.exist?(git_dir)
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
def git_status_info
|
|
229
|
+
{
|
|
230
|
+
branch: current_branch,
|
|
231
|
+
remote: remote_url,
|
|
232
|
+
modified_count: modified_files_count,
|
|
233
|
+
untracked_count: untracked_files_count,
|
|
234
|
+
ahead: commits_ahead,
|
|
235
|
+
behind: commits_behind
|
|
236
|
+
}
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
def current_branch
|
|
240
|
+
`git -C "#{brand_path}" rev-parse --abbrev-ref HEAD 2>/dev/null`.strip
|
|
241
|
+
rescue StandardError
|
|
242
|
+
'unknown'
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
def remote_url
|
|
246
|
+
result = `git -C "#{brand_path}" remote get-url origin 2>/dev/null`.strip
|
|
247
|
+
result.empty? ? nil : result
|
|
248
|
+
rescue StandardError
|
|
249
|
+
nil
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
def modified_files_count
|
|
253
|
+
`git -C "#{brand_path}" status --porcelain 2>/dev/null | grep -E "^.M|^M" | wc -l`.strip.to_i
|
|
254
|
+
rescue StandardError
|
|
255
|
+
0
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
def untracked_files_count
|
|
259
|
+
`git -C "#{brand_path}" status --porcelain 2>/dev/null | grep -E "^\\?\\?" | wc -l`.strip.to_i
|
|
260
|
+
rescue StandardError
|
|
261
|
+
0
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
def commits_ahead
|
|
265
|
+
`git -C "#{brand_path}" rev-list --count @{upstream}..HEAD 2>/dev/null`.strip.to_i
|
|
266
|
+
rescue StandardError
|
|
267
|
+
0
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
def commits_behind
|
|
271
|
+
`git -C "#{brand_path}" rev-list --count HEAD..@{upstream} 2>/dev/null`.strip.to_i
|
|
272
|
+
rescue StandardError
|
|
273
|
+
0
|
|
274
|
+
end
|
|
275
|
+
end
|
|
276
|
+
end
|
|
277
|
+
end
|
|
278
|
+
end
|
data/lib/appydave/tools.rb
CHANGED
|
@@ -59,6 +59,10 @@ require 'appydave/tools/dam/s3_operations'
|
|
|
59
59
|
require 'appydave/tools/dam/project_listing'
|
|
60
60
|
require 'appydave/tools/dam/manifest_generator'
|
|
61
61
|
require 'appydave/tools/dam/sync_from_ssd'
|
|
62
|
+
require 'appydave/tools/dam/status'
|
|
63
|
+
require 'appydave/tools/dam/repo_status'
|
|
64
|
+
require 'appydave/tools/dam/repo_sync'
|
|
65
|
+
require 'appydave/tools/dam/repo_push'
|
|
62
66
|
|
|
63
67
|
require 'appydave/tools/youtube_automation/gpt_agent'
|
|
64
68
|
|
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.
|
|
4
|
+
version: 0.20.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- David Cruwys
|
|
@@ -292,7 +292,11 @@ files:
|
|
|
292
292
|
- lib/appydave/tools/dam/manifest_generator.rb
|
|
293
293
|
- lib/appydave/tools/dam/project_listing.rb
|
|
294
294
|
- lib/appydave/tools/dam/project_resolver.rb
|
|
295
|
+
- lib/appydave/tools/dam/repo_push.rb
|
|
296
|
+
- lib/appydave/tools/dam/repo_status.rb
|
|
297
|
+
- lib/appydave/tools/dam/repo_sync.rb
|
|
295
298
|
- lib/appydave/tools/dam/s3_operations.rb
|
|
299
|
+
- lib/appydave/tools/dam/status.rb
|
|
296
300
|
- lib/appydave/tools/dam/sync_from_ssd.rb
|
|
297
301
|
- lib/appydave/tools/debuggable.rb
|
|
298
302
|
- lib/appydave/tools/gpt_context/_doc.md
|