@@ -5,7 +5,10 @@ import (
5
5
"github.com/spf13/cobra"
6
6
"github.com/wttech/aemc/pkg"
7
7
"github.com/wttech/aemc/pkg/common/pathx"
8
+ "github.com/wttech/aemc/pkg/common/timex"
8
9
"github.com/wttech/aemc/pkg/content"
10
+ "os"
11
+ "path/filepath"
9
12
"strings"
10
13
)
11
14
@@ -17,6 +20,7 @@ func (c *CLI) contentCmd() *cobra.Command {
17
20
}
18
21
cmd .AddCommand (c .contentCleanCmd ())
19
22
cmd .AddCommand (c .contentPullCmd ())
23
+ cmd .AddCommand (c .contentPushCmd ())
20
24
cmd .AddCommand (c .contentDownloadCmd ())
21
25
cmd .AddCommand (c .contentCopyCmd ())
22
26
return cmd
@@ -38,17 +42,17 @@ func (c *CLI) contentCleanCmd() *cobra.Command {
38
42
c .Error (err )
39
43
return
40
44
}
45
+ path := dir
46
+ if path == "" {
47
+ path = file
48
+ }
49
+ if err = c .aem .ContentManager ().Clean (path ); err != nil {
50
+ c .Error (err )
51
+ return
52
+ }
41
53
if dir != "" {
42
- if err = c .aem .ContentManager ().CleanDir (dir ); err != nil {
43
- c .Error (err )
44
- return
45
- }
46
54
c .SetOutput ("dir" , dir )
47
55
} else if file != "" {
48
- if err = c .aem .ContentManager ().CleanFile (file ); err != nil {
49
- c .Error (err )
50
- return
51
- }
52
56
c .SetOutput ("file" , file )
53
57
}
54
58
c .Changed ("content cleaned" )
@@ -73,10 +77,14 @@ func (c *CLI) contentDownloadCmd() *cobra.Command {
73
77
return
74
78
}
75
79
pid , _ := cmd .Flags ().GetString ("pid" )
80
+ if pid == "" {
81
+ pid = fmt .Sprintf ("aemc:content-download:%s-SNAPSHOT" , timex .FileTimestampForNow ())
82
+ }
76
83
targetFile , _ := cmd .Flags ().GetString ("target-file" )
77
- filterRoots , _ := cmd . Flags (). GetStringSlice ( "filter-roots" )
84
+ filterRoots := determineFilterRoots ( cmd )
78
85
filterFile , _ := cmd .Flags ().GetString ("filter-file" )
79
- if err = instance .ContentManager ().Download (targetFile , pkg.PackageCreateOpts {
86
+ clean , _ := cmd .Flags ().GetBool ("clean" )
87
+ if err = c .aem .ContentManager ().Download (instance , targetFile , clean , pkg.PackageCreateOpts {
80
88
PID : pid ,
81
89
FilterRoots : filterRoots ,
82
90
FilterFile : filterFile ,
@@ -94,6 +102,7 @@ func (c *CLI) contentDownloadCmd() *cobra.Command {
94
102
cmd .Flags ().StringSliceP ("filter-roots" , "r" , []string {}, "Vault filter root paths" )
95
103
cmd .Flags ().StringP ("filter-file" , "f" , "" , "Vault filter file path" )
96
104
cmd .MarkFlagsOneRequired ("filter-roots" , "filter-file" )
105
+ cmd .Flags ().Bool ("clean" , false , "Normalize content after downloading" )
97
106
return cmd
98
107
}
99
108
@@ -108,8 +117,6 @@ func (c *CLI) contentPullCmd() *cobra.Command {
108
117
c .Error (err )
109
118
return
110
119
}
111
- clean , _ := cmd .Flags ().GetBool ("clean" )
112
- replace , _ := cmd .Flags ().GetBool ("replace" )
113
120
dir , err := determineContentDir (cmd )
114
121
if err != nil {
115
122
c .Error (err )
@@ -120,21 +127,26 @@ func (c *CLI) contentPullCmd() *cobra.Command {
120
127
c .Error (err )
121
128
return
122
129
}
130
+ filterRoots := determineFilterRoots (cmd )
131
+ filterFile , _ := cmd .Flags ().GetString ("filter-file" )
132
+ filterRootExcludes := determineFilterRootExcludes (cmd )
133
+ clean , _ := cmd .Flags ().GetBool ("clean" )
134
+ replace , _ := cmd .Flags ().GetBool ("replace" )
123
135
if dir != "" {
124
- filterRoots , _ := cmd .Flags ().GetStringSlice ("filter-roots" )
125
- filterFile , _ := cmd .Flags ().GetString ("filter-file" )
126
- if err = instance .ContentManager ().PullDir (dir , clean , replace , pkg.PackageCreateOpts {
136
+ if err = c .aem .ContentManager ().PullDir (instance , dir , clean , replace , pkg.PackageCreateOpts {
137
+ PID : fmt .Sprintf ("aemc:content-pull:%s-SNAPSHOT" , timex .FileTimestampForNow ()),
127
138
FilterRoots : filterRoots ,
128
139
FilterFile : filterFile ,
129
- ContentDir : dir ,
130
140
}); err != nil {
131
141
c .Error (err )
132
142
return
133
143
}
134
144
c .SetOutput ("dir" , dir )
135
145
} else if file != "" {
136
- if err = instance .ContentManager ().PullFile (file , clean , pkg.PackageCreateOpts {
137
- ContentFile : file ,
146
+ if err = c .aem .ContentManager ().PullFile (instance , file , clean , replace , pkg.PackageCreateOpts {
147
+ PID : fmt .Sprintf ("aemc:content-pull:%s-SNAPSHOT" , timex .FileTimestampForNow ()),
148
+ FilterRoots : filterRoots ,
149
+ FilterRootExcludes : filterRootExcludes ,
138
150
}); err != nil {
139
151
c .Error (err )
140
152
return
@@ -156,6 +168,66 @@ func (c *CLI) contentPullCmd() *cobra.Command {
156
168
return cmd
157
169
}
158
170
171
+ func (c * CLI ) contentPushCmd () * cobra.Command {
172
+ cmd := & cobra.Command {
173
+ Use : "push" ,
174
+ Aliases : []string {"ps" },
175
+ Short : "Push content from JCR root directory or local file to running instance" ,
176
+ Run : func (cmd * cobra.Command , args []string ) {
177
+ instances , err := c .aem .InstanceManager ().Some ()
178
+ if err != nil {
179
+ c .Error (err )
180
+ return
181
+ }
182
+ dir , err := determineContentDir (cmd )
183
+ if err != nil {
184
+ c .Error (err )
185
+ return
186
+ }
187
+ file , err := determineContentFile (cmd )
188
+ if err != nil {
189
+ c .Error (err )
190
+ return
191
+ }
192
+ path := dir
193
+ if path == "" {
194
+ path = file
195
+ }
196
+ if ! pathx .Exists (path ) {
197
+ c .Error (fmt .Errorf ("cannot push content as it does not exist '%s'" , path ))
198
+ return
199
+ }
200
+ filterRoots := determineFilterRoots (cmd )
201
+ filterRootExcludes := determineFilterRootExcludes (cmd )
202
+ clean , _ := cmd .Flags ().GetBool ("clean" )
203
+ filterMode := determineFilterMode (cmd )
204
+ if err = c .aem .ContentManager ().Push (instances , clean , pkg.PackageCreateOpts {
205
+ PID : fmt .Sprintf ("aemc:content-push:%s-SNAPSHOT" , timex .FileTimestampForNow ()),
206
+ FilterRoots : filterRoots ,
207
+ FilterRootExcludes : filterRootExcludes ,
208
+ ContentPath : path ,
209
+ FilterMode : filterMode ,
210
+ }); err != nil {
211
+ c .Error (err )
212
+ return
213
+ }
214
+ if dir != "" {
215
+ c .SetOutput ("dir" , dir )
216
+ } else if file != "" {
217
+ c .SetOutput ("file" , file )
218
+ }
219
+ c .Changed ("content pushed" )
220
+ },
221
+ }
222
+ cmd .Flags ().StringP ("dir" , "d" , "" , "JCR root path" )
223
+ cmd .Flags ().StringP ("file" , "f" , "" , "Local file path" )
224
+ cmd .Flags ().StringP ("path" , "p" , "" , "JCR root path or local file path" )
225
+ cmd .MarkFlagsOneRequired ("dir" , "file" , "path" )
226
+ cmd .Flags ().Bool ("clean" , false , "Normalize content while uploading" )
227
+ cmd .Flags ().Bool ("update" , false , "Existing content on running instance is updated, new content is added and none is deleted" )
228
+ return cmd
229
+ }
230
+
159
231
func (c * CLI ) contentCopyCmd () * cobra.Command {
160
232
cmd := & cobra.Command {
161
233
Use : "copy" ,
@@ -167,15 +239,16 @@ func (c *CLI) contentCopyCmd() *cobra.Command {
167
239
c .Error (err )
168
240
return
169
241
}
170
- targetInstance , err := determineContentTargetInstance (cmd , c .aem .InstanceManager ())
242
+ targetInstances , err := determineContentTargetInstances (cmd , c .aem .InstanceManager ())
171
243
if err != nil {
172
244
c .Error (err )
173
245
return
174
246
}
175
- filterRoots , _ := cmd . Flags (). GetStringSlice ( "filter-roots" )
247
+ filterRoots := determineFilterRoots ( cmd )
176
248
filterFile , _ := cmd .Flags ().GetString ("filter-file" )
177
249
clean , _ := cmd .Flags ().GetBool ("clean" )
178
- if err = instance .ContentManager ().Copy (targetInstance , clean , pkg.PackageCreateOpts {
250
+ if err = c .aem .ContentManager ().Copy (instance , targetInstances , clean , pkg.PackageCreateOpts {
251
+ PID : fmt .Sprintf ("aemc:content-copy:%s-SNAPSHOT" , timex .FileTimestampForNow ()),
179
252
FilterRoots : filterRoots ,
180
253
FilterFile : filterFile ,
181
254
}); err != nil {
@@ -185,8 +258,8 @@ func (c *CLI) contentCopyCmd() *cobra.Command {
185
258
c .Changed ("content copied" )
186
259
},
187
260
}
188
- cmd .Flags ().StringP ("instance-target-url" , "u" , "" , "Destination instance URL" )
189
- cmd .Flags ().StringP ("instance-target-id" , "i" , "" , "Destination instance ID" )
261
+ cmd .Flags ().StringSliceP ("instance-target-url" , "u" , [] string {} , "Destination instance URL" )
262
+ cmd .Flags ().StringSliceP ("instance-target-id" , "i" , [] string {} , "Destination instance ID" )
190
263
cmd .MarkFlagsOneRequired ("instance-target-url" , "instance-target-id" )
191
264
cmd .Flags ().StringSliceP ("filter-roots" , "r" , []string {}, "Vault filter root paths" )
192
265
cmd .Flags ().StringP ("filter-file" , "f" , "" , "Vault filter file path" )
@@ -195,33 +268,41 @@ func (c *CLI) contentCopyCmd() *cobra.Command {
195
268
return cmd
196
269
}
197
270
198
- func determineContentTargetInstance (cmd * cobra.Command , instanceManager * pkg.InstanceManager ) (* pkg.Instance , error ) {
199
- var instance * pkg.Instance
200
- url , _ := cmd .Flags ().GetString ("instance-target-url" )
201
- if url != "" {
202
- instance , _ = instanceManager .NewByIDAndURL ("remote_adhoc_target" , url )
271
+ func determineContentTargetInstances (cmd * cobra.Command , instanceManager * pkg.InstanceManager ) ([]pkg.Instance , error ) {
272
+ var instances []pkg.Instance
273
+ urls , _ := cmd .Flags ().GetStringSlice ("instance-target-url" )
274
+ for _ , url := range urls {
275
+ instance , err := instanceManager .NewByIDAndURL ("remote_adhoc_target" , url )
276
+ if err != nil {
277
+ return nil , err
278
+ }
279
+ instances = append (instances , * instance )
203
280
}
204
- id , _ := cmd .Flags ().GetString ("instance-target-id" )
205
- if id != "" {
206
- instance = instanceManager .NewByID (id )
281
+ ids , _ := cmd .Flags ().GetStringSlice ("instance-target-id" )
282
+ for _ , id := range ids {
283
+ instance := instanceManager .NewByID (id )
284
+ instances = append (instances , * instance )
207
285
}
208
- if instance == nil {
286
+ if instances == nil {
209
287
return nil , fmt .Errorf ("missing 'instance-target-url' or 'instance-target-id'" )
210
288
}
211
- return instance , nil
289
+ return instances , nil
212
290
}
213
291
214
292
func determineContentDir (cmd * cobra.Command ) (string , error ) {
215
293
dir , _ := cmd .Flags ().GetString ("dir" )
216
294
if dir != "" && ! strings .Contains (dir , content .JCRRoot ) {
217
- return "" , fmt .Errorf ("content dir '%s' does not contain '%s'" , dir , content .JCRRoot )
295
+ return "" , fmt .Errorf ("content directory '%s' does not contain '%s'" , dir , content .JCRRoot )
296
+ }
297
+ if pathx .IsFile (dir ) {
298
+ return "" , fmt .Errorf ("content directory '%s' is not a directory; consider using 'file' parameter" , dir )
218
299
}
219
300
path , _ := cmd .Flags ().GetString ("path" )
220
301
if path != "" && ! strings .Contains (path , content .JCRRoot ) {
221
302
return "" , fmt .Errorf ("content path '%s' does not contain '%s'" , path , content .JCRRoot )
222
303
}
223
304
if path != "" && ! pathx .Exists (path ) {
224
- return "" , fmt .Errorf ("content path does not exist: %s " , path )
305
+ return "" , fmt .Errorf ("content path '%s' need to exist on file system; consider using 'dir' or 'file' parameter otherwise " , path )
225
306
}
226
307
if path != "" && pathx .IsDir (path ) {
227
308
return path , nil
@@ -234,15 +315,69 @@ func determineContentFile(cmd *cobra.Command) (string, error) {
234
315
if file != "" && ! strings .Contains (file , content .JCRRoot ) {
235
316
return "" , fmt .Errorf ("content file '%s' does not contain '%s'" , file , content .JCRRoot )
236
317
}
318
+ if pathx .IsDir (file ) {
319
+ return "" , fmt .Errorf ("content file '%s' is not a file; consider using 'dir' parameter" , file )
320
+ }
237
321
path , _ := cmd .Flags ().GetString ("path" )
238
322
if path != "" && ! strings .Contains (path , content .JCRRoot ) {
239
323
return "" , fmt .Errorf ("content path '%s' does not contain '%s'" , path , content .JCRRoot )
240
324
}
241
325
if path != "" && ! pathx .Exists (path ) {
242
- return "" , fmt .Errorf ("content path does not exist: %s " , path )
326
+ return "" , fmt .Errorf ("content path '%s' need to exist on file system; consider using 'dir' or 'file' parameter otherwise " , path )
243
327
}
244
328
if path != "" && pathx .IsFile (path ) {
245
329
return path , nil
246
330
}
247
331
return file , nil
248
332
}
333
+
334
+ func determineFilterRoots (cmd * cobra.Command ) []string {
335
+ filterRoots , _ := cmd .Flags ().GetStringSlice ("filter-roots" )
336
+ if len (filterRoots ) > 0 {
337
+ return filterRoots
338
+ }
339
+ filterFile , _ := cmd .Flags ().GetString ("filter-file" )
340
+ if filterFile != "" {
341
+ return nil
342
+ }
343
+ dir , _ := determineContentDir (cmd )
344
+ if dir != "" {
345
+ return []string {pkg .DetermineFilterRoot (dir )}
346
+ }
347
+ file , _ := determineContentFile (cmd )
348
+ if file != "" {
349
+ return []string {pkg .DetermineFilterRoot (file )}
350
+ }
351
+ return nil
352
+ }
353
+
354
+ func determineFilterRootExcludes (cmd * cobra.Command ) []string {
355
+ file , _ := determineContentFile (cmd )
356
+ if file == "" || ! strings .HasSuffix (file , content .JCRContentFile ) || content .IsPageContentFile (file ) {
357
+ return nil
358
+ }
359
+
360
+ dir := filepath .Dir (file )
361
+ entries , err := os .ReadDir (dir )
362
+ if err != nil {
363
+ return nil
364
+ }
365
+
366
+ var filterRootExcludes []string
367
+ for _ , entry := range entries {
368
+ if entry .Name () != content .JCRContentFile {
369
+ jcrPath := pkg .DetermineFilterRoot (filepath .Join (dir , entry .Name ()))
370
+ excludePattern := fmt .Sprintf ("%s(/.*)?" , jcrPath )
371
+ filterRootExcludes = append (filterRootExcludes , excludePattern )
372
+ }
373
+ }
374
+ return filterRootExcludes
375
+ }
376
+
377
+ func determineFilterMode (cmd * cobra.Command ) string {
378
+ update , _ := cmd .Flags ().GetBool ("update" )
379
+ if update {
380
+ return "update"
381
+ }
382
+ return ""
383
+ }
0 commit comments