(tmpfile *os.File, tmpfileName string, opts editOpts, tree *sops.Tree, dataKey []byte)
| 162 | } |
| 163 | |
| 164 | func editTreeImpl(tmpfile *os.File, tmpfileName string, opts editOpts, tree *sops.Tree, dataKey []byte) editTreeResult { |
| 165 | // Write to temporary file |
| 166 | var out []byte |
| 167 | var err error |
| 168 | if opts.ShowMasterKeys { |
| 169 | out, err = opts.OutputStore.EmitEncryptedFile(*tree) |
| 170 | } else { |
| 171 | out, err = opts.OutputStore.EmitPlainFile(tree.Branches) |
| 172 | } |
| 173 | if err != nil { |
| 174 | return createError(common.NewExitError(fmt.Sprintf("Could not marshal tree: %s", err), codes.ErrorDumpingTree)) |
| 175 | } |
| 176 | _, err = tmpfile.Write(out) |
| 177 | if err != nil { |
| 178 | return createError(common.NewExitError(fmt.Sprintf("Could not write output file: %s", err), codes.CouldNotWriteOutputFile)) |
| 179 | } |
| 180 | |
| 181 | // Compute file hash to detect if the file has been edited |
| 182 | origHash, err := hashFile(tmpfileName) |
| 183 | if err != nil { |
| 184 | return createError(common.NewExitError(fmt.Sprintf("Could not hash file: %s", err), codes.CouldNotReadInputFile)) |
| 185 | } |
| 186 | |
| 187 | // Close the temporary file, so that an editor can open it. |
| 188 | // We need to do this because some editors (e.g. VSCode) will refuse to |
| 189 | // open a file on Windows due to the Go standard library not opening |
| 190 | // files with shared delete access. |
| 191 | if err := tmpfile.Close(); err != nil { |
| 192 | return createError(err) |
| 193 | } |
| 194 | |
| 195 | // Let the user edit the file |
| 196 | err = runEditorUntilOk(runEditorUntilOkOpts{ |
| 197 | InputStore: opts.InputStore, |
| 198 | OutputStore: opts.OutputStore, |
| 199 | OriginalHash: origHash, |
| 200 | TmpFileName: tmpfileName, |
| 201 | ShowMasterKeys: opts.ShowMasterKeys, |
| 202 | Tree: tree}) |
| 203 | if err != nil { |
| 204 | return createError(err) |
| 205 | } |
| 206 | |
| 207 | // Encrypt the file |
| 208 | err = common.EncryptTree(common.EncryptTreeOpts{ |
| 209 | DataKey: dataKey, Tree: tree, Cipher: opts.Cipher, |
| 210 | }) |
| 211 | if err != nil { |
| 212 | return createError(err) |
| 213 | } |
| 214 | |
| 215 | // Output the file |
| 216 | encryptedFile, err := opts.OutputStore.EmitEncryptedFile(*tree) |
| 217 | if err != nil { |
| 218 | return createError(common.NewExitError(fmt.Sprintf("Could not marshal tree: %s", err), codes.ErrorDumpingTree)) |
| 219 | } |
| 220 | return editTreeResult{ |
| 221 | value: encryptedFile, |
no test coverage detected