88 "io"
99 "io/ioutil"
1010 "os"
11+ "os/exec"
1112 "os/user"
1213 "path/filepath"
1314 "strconv"
@@ -21,6 +22,7 @@ import (
2122// An AddOptions contains options for TargetState.Add.
2223type AddOptions struct {
2324 Empty bool
25+ Encrypt bool
2426 Exact bool
2527 Template bool
2628}
@@ -40,18 +42,20 @@ type TargetState struct {
4042 SourceDir string
4143 Data map [string ]interface {}
4244 TemplateFuncs template.FuncMap
45+ GPGRecipient string
4346 Entries map [string ]Entry
4447}
4548
4649// NewTargetState creates a new TargetState.
47- func NewTargetState (destDir string , umask os.FileMode , sourceDir string , data map [string ]interface {}, templateFuncs template.FuncMap ) * TargetState {
50+ func NewTargetState (destDir string , umask os.FileMode , sourceDir string , data map [string ]interface {}, templateFuncs template.FuncMap , gpgRecipient string ) * TargetState {
4851 return & TargetState {
4952 DestDir : destDir ,
5053 TargetIgnore : NewPatternSet (),
5154 Umask : umask ,
5255 SourceDir : sourceDir ,
5356 Data : data ,
5457 TemplateFuncs : templateFuncs ,
58+ GPGRecipient : gpgRecipient ,
5559 Entries : make (map [string ]Entry ),
5660 }
5761}
@@ -120,7 +124,19 @@ func (ts *TargetState) Add(fs vfs.FS, addOptions AddOptions, targetPath string,
120124 return err
121125 }
122126 }
123- return ts .addFile (targetName , entries , parentDirSourceName , info , addOptions .Template , contents , mutator )
127+ if addOptions .Encrypt {
128+ args := []string {"--armor" , "--encrypt" }
129+ if ts .GPGRecipient != "" {
130+ args = append (args , "--recipient" , ts .GPGRecipient )
131+ }
132+ cmd := exec .Command ("gpg" , args ... )
133+ cmd .Stdin = bytes .NewReader (contents )
134+ contents , err = cmd .Output ()
135+ if err != nil {
136+ return err
137+ }
138+ }
139+ return ts .addFile (targetName , entries , parentDirSourceName , info , addOptions .Encrypt , addOptions .Template , contents , mutator )
124140 case info .Mode ()& os .ModeType == os .ModeSymlink :
125141 linkname , err := fs .Readlink (targetPath )
126142 if err != nil {
@@ -283,12 +299,30 @@ func (ts *TargetState) Populate(fs vfs.FS) error {
283299 var entry Entry
284300 switch psfp .Mode & os .ModeType {
285301 case 0 :
286- evaluateContents := func () ([]byte , error ) {
302+ readFile := func () ([]byte , error ) {
287303 return fs .ReadFile (path )
288304 }
305+ evaluateContents := readFile
306+ if psfp .Encrypted {
307+ prevEvaluateContents := evaluateContents
308+ evaluateContents = func () ([]byte , error ) {
309+ encryptedData , err := prevEvaluateContents ()
310+ if err != nil {
311+ return nil , err
312+ }
313+ cmd := exec .Command ("gpg" , "--decrypt" )
314+ cmd .Stdin = bytes .NewReader (encryptedData )
315+ return cmd .Output ()
316+ }
317+ }
289318 if psfp .Template {
319+ prevEvaluateContents := evaluateContents
290320 evaluateContents = func () ([]byte , error ) {
291- return ts .executeTemplate (fs , path )
321+ data , err := prevEvaluateContents ()
322+ if err != nil {
323+ return nil , err
324+ }
325+ return ts .executeTemplateData (path , data )
292326 }
293327 }
294328 entry = & File {
@@ -359,7 +393,7 @@ func (ts *TargetState) addDir(targetName string, entries map[string]Entry, paren
359393 return nil
360394}
361395
362- func (ts * TargetState ) addFile (targetName string , entries map [string ]Entry , parentDirSourceName string , info os.FileInfo , template bool , contents []byte , mutator Mutator ) error {
396+ func (ts * TargetState ) addFile (targetName string , entries map [string ]Entry , parentDirSourceName string , info os.FileInfo , encrypted , template bool , contents []byte , mutator Mutator ) error {
363397 name := filepath .Base (targetName )
364398 var existingFile * File
365399 var existingContents []byte
@@ -377,10 +411,11 @@ func (ts *TargetState) addFile(targetName string, entries map[string]Entry, pare
377411 perm := info .Mode ().Perm ()
378412 empty := info .Size () == 0
379413 sourceName := FileAttributes {
380- Name : name ,
381- Mode : perm ,
382- Empty : empty ,
383- Template : template ,
414+ Name : name ,
415+ Mode : perm ,
416+ Empty : empty ,
417+ Encrypted : encrypted ,
418+ Template : template ,
384419 }.SourceName ()
385420 if parentDirSourceName != "" {
386421 sourceName = filepath .Join (parentDirSourceName , sourceName )
@@ -389,6 +424,7 @@ func (ts *TargetState) addFile(targetName string, entries map[string]Entry, pare
389424 sourceName : sourceName ,
390425 targetName : targetName ,
391426 Empty : empty ,
427+ Encrypted : encrypted ,
392428 Perm : perm ,
393429 Template : template ,
394430 contents : contents ,
@@ -568,7 +604,7 @@ func (ts *TargetState) importHeader(r io.Reader, importTAROptions ImportTAROptio
568604 if err != nil {
569605 return err
570606 }
571- return ts .addFile (targetName , entries , parentDirSourceName , info , false , contents , mutator )
607+ return ts .addFile (targetName , entries , parentDirSourceName , info , false , false , contents , mutator )
572608 case tar .TypeSymlink :
573609 linkname := header .Linkname
574610 return ts .addSymlink (targetName , entries , parentDirSourceName , linkname , mutator )
0 commit comments