diff --git a/cmd/add.go b/cmd/add.go index 7057252..92fc06d 100644 --- a/cmd/add.go +++ b/cmd/add.go @@ -4,53 +4,87 @@ package cmd import ( "fmt" + "os" "github.com/Ibotta/sopstool/fileutil" "github.com/Ibotta/sopstool/sopsyaml" "github.com/spf13/cobra" ) -// addCmd represents the add command var addCmd = &cobra.Command{ - Aliases: []string{"a", "encrypt"}, - Use: "add [files ...]", - Short: "add file to the encryption list", - Long: `Add files to the list of files managed by sopstool`, - Args: cobra.MinimumNArgs(1), + Aliases: []string{"a", "e", "add", "encrypt"}, + Use: "add [files ...], add", + Short: "add file to the encryption list and encrypt file. No argument encrypts all in sops config.", + Long: `Add files to the list of files managed by sopstool and encrypt them. If no argument is provided, encrypt everything provided in sops config`, RunE: AddCommand, } var noEncrypt bool var noClean bool +var forceOverwrite bool func init() { RootCmd.AddCommand(addCmd) addCmd.Flags().BoolVarP(&noEncrypt, "no-encrypt", "n", false, "Do not encrypt the file after adding") addCmd.Flags().BoolVar(&noClean, "no-clean", false, "Do not clean up plaintext after encrypting") + addCmd.Flags().BoolVarP(&forceOverwrite, "force", "f", false, "Force overwriting of encrypted files if they already exist") } -// AddCommand the command for the add command func AddCommand(_ *cobra.Command, args []string) error { initConfig() - for _, fileArg := range args { + if len(args) == 0 && len(sopsConfig.EncryptedFiles) == 0 { + fmt.Println("No files specified for encryption and no known encrypted files.") + return nil + } + + filesToEncrypt := args + if len(args) == 0 { + filesToEncrypt = sopsConfig.EncryptedFiles + } + + encryptedCount := 0 + for _, fileArg := range filesToEncrypt { fn := fileutil.NormalizeToPlaintextFile(fileArg) - if fileutil.ListIndexOf(sopsConfig.EncryptedFiles, fn) >= 0 { - fmt.Println("Already exists", fn) - return nil + + // Check if plaintext file exists on disk + if _, err := os.Stat(fn); os.IsNotExist(err) { + fmt.Println("Plaintext version of file does not exist:", fn) + continue } - // add file to list - sopsConfig.EncryptedFiles = append(sopsConfig.EncryptedFiles, fn) + encryptedFilePath := fileutil.NormalizeToSopsFile(fn) + + // Check if encrypted file already exists on disk + if _, err := os.Stat(encryptedFilePath); !os.IsNotExist(err) && !forceOverwrite { + fmt.Printf("Encrypted version of file %s already exists on disk. Do you want to overwrite it? [y/N]: ", encryptedFilePath) + var input string + fmt.Scanln(&input) + if input == "" || input == "y" || input == "Y" { + // Continue with the overwriting process + } else { + fmt.Println("Skipping:", encryptedFilePath) + continue + } + } + + // Check and add the file to the list if not already present + if fileutil.ListIndexOf(sopsConfig.EncryptedFiles, fn) == -1 { + sopsConfig.EncryptedFiles = append(sopsConfig.EncryptedFiles, fn) + fmt.Println("Added file to encryption list:", fn) + } else { + fmt.Println("File", fn, "is already in the encryption list.") + } - //if the file exists, encrypt it + // Encrypt the file if !noEncrypt { err := encrypter.EncryptFile(fn) if err != nil { return err } + encryptedCount++ } if !noClean { @@ -58,13 +92,13 @@ func AddCommand(_ *cobra.Command, args []string) error { if err != nil { return err } + fmt.Println("Cleaned up plaintext for:", fn) } err := sourceCodeManager.AddFileToIgnored(fn) if err != nil { return err } - fmt.Println("added file to list:", fn) } err := sopsyaml.WriteEncryptFilesToDisk(sopsConfig.Path, sopsConfig.Tree, sopsConfig.EncryptedFiles) @@ -72,7 +106,7 @@ func AddCommand(_ *cobra.Command, args []string) error { return err } - fmt.Println("Files added") + fmt.Printf("%d file(s) encrypted successfully.\n", encryptedCount) return nil } diff --git a/cmd/decrypt.go b/cmd/decrypt.go index 3a1e2b5..dc2db1e 100644 --- a/cmd/decrypt.go +++ b/cmd/decrypt.go @@ -3,6 +3,9 @@ package cmd import ( + "fmt" + "os" + "github.com/Ibotta/sopstool/fileutil" "github.com/spf13/cobra" ) @@ -32,13 +35,29 @@ func DecryptCommand(_ *cobra.Command, args []string) error { return err } - //decrypt all the files + decryptedCount := 0 // Counter for successfully decrypted files + + // Decrypt all the files for _, f := range filesToDecrypt { + cryptfile := fileutil.NormalizeToSopsFile(f) + if _, err := os.Stat(cryptfile); os.IsNotExist(err) { + fmt.Println("Encrypted version of file does not exist:", f) + // If the encrypted file doesn't exist, skip decryption for this file + continue + } + err := encrypter.DecryptFile(f) - if err != nil && !allowFail { - return err + if err != nil { + if !allowFail { + return err + } + } else { + decryptedCount++ // Increment the counter when decryption is successful } } + // Print out the total number of decrypted files + fmt.Printf("%d files decrypted successfully.\n", decryptedCount) + return nil } diff --git a/oswrap/exec.go b/oswrap/exec.go index e60755a..fe50019 100644 --- a/oswrap/exec.go +++ b/oswrap/exec.go @@ -46,6 +46,8 @@ func (ew execWrap) RunCommandStdoutToFile(outfileName string, command []string) if err != nil { return err } + defer outfile.Close() // Close the file after cmd completes + cmd.Stdout = outfile err = cmd.Start()