Greg Hurrell [Mon, 1 Aug 2022 11:53:07 +0000 (13:53 +0200)]
feat: make some improvements to logging
- Interleave output (topological ordering) instead of showing _all_ the
changes for one file before moving on to the next.
- When you don't pass any limiting paths, grab the history for _all_
files across the entire history of the repo (including past renames).
- Don't reprint commit messages for every file in a commit (no longer
necessary now that output is interleaved).
I often forget the difference between "STALE" and "MODIFIED" — they
should probably be replaced with better terms but I am not sure what —
but I can at least make it easy to look up what each one means.
and potentially getting pulled into `encrypt`/`decrypt` operations.
I hadn't seen this until now, but I just caused such a file to be
created while preparing the last commit because I edited a ciphertext by
hand to modify it (of course, I should have just used `touch` and I
later did, but anyway...)
Greg Hurrell [Tue, 8 Jun 2021 07:32:40 +0000 (09:32 +0200)]
feat: teach `status` to report staleness
Previously we only had checks to report when plain-text was newer than
ciphertext. In this case, `status` would show `[MODIFIED]` for that
file. In practice, I never see these messages because I have a Vim
autocmd that re-encrypts such files whenever I edit them.
But we did not have a check for the inverse case; ie. when a ciphertext
is newer than a plain-text. This can happen when you are editing on
multiple machines and syncing via Git. So, now we report that case as
`[STALE]`. The terminology may be confusing, but without printing out a
huge blurb explaining it, I think we have to rely on the `git-cipher
status -h/--help` output.
We do this somewhat fuzzily, requiring a difference of at least 5
seconds, because we already rely on plain-text being "older" than
ciphertext to avoid unnecessary churn. That is, when we decrypt a file,
we force the plain-text timestamp to be 1 second older than the
ciphertext. I am a bit fuzzy on why we did this and I am too lazy to
look it up in the Git history, but I am assuming it is because setting
the timestamps to be _equal_ was not enough (ie. `FileUtils.uptodate?`
probably didn't do the right thing in that case, possibly due to
timestamp resolution issues).
[Ok, I lied about being too lazy. I looked in the source repo where this
originally came from and it says nothing about `uptodate?`, so my guess
above is the best I can do.]
Greg Hurrell [Sat, 5 Jun 2021 12:38:26 +0000 (14:38 +0200)]
feat: support encryption with multiple keys
The motivation, as explained here[0], is to have these keys and subkeys:
1. Personal (signing) key: alice@home.example.net, not used by
git-cipher
- Subkey for encryption (added by GPG): used for encryption
- Any other subkeys (optionally) added by user: not used by
git-cipher
2. Work (signing) key: alice@work.example.com, not used by git-cipher
- Subkey for encryption (added by GPG): used for encryption
- Any other subkeys (optionally) added by user: not used by
git-cipher
The primary keys can have expiry dates or not (I recommend that they
have them, but that you extend them periodically, for reasons that are
too long to go into here).
The subkeys should have expiry dates. When they expire, rotate to new
keys (ie. re-encrypt the files). To make life easy, the expiry dates
should be synchronized.
Having personal and work keys makes it possible to revoke keys,
rotate them independently if desired, or stop using a key upon leaving a
job.
Set executable bit on common scripting language files
If you encrypt (or decrypt) a file with a common scripting extension
(eg. `.js`, `.sh`) then `git-cipher` will set its executable bit
automatically. We didn't used to do this, but that meant that if you
went back and manually set the permissions then you would bump the
modification time of the file, causing it to be needlessly reencrypted
on the next run of `git-cipher encrypt`.
Other approaches that were considered and discarded were:
1. Make the behavior optional, via a switch or configuration option
(discarded due to needless complexity).
2. Encode the need to set the bit in the encrypted file's own
permissions (discarded because that means setting the bit on a file
that is not executable, which is misleading).
3. Encode the need to set the bit in the encrypted file's internal
structure: effectively, instead of storing the GPG output, we'd store
a YAML file containing metadata and the output (discarded because of
compatibility concerns and complexity; would make many subcommands in
the app more complicated).
4. Encode the need to set the bit in the encrypted file's name
(discarded because it's ugly and would still add a fair bit of
complexity).
So in the end have taken what I think is the pragmatic approach.
Greg Hurrell [Mon, 8 Feb 2016 09:09:31 +0000 (01:09 -0800)]
Add `log` subcommand
This is a rough cut, but it works. Incredibly fork-heavy and generates a
lot of temporary files. Could probably benefit from some better (or
any?) error handling. I might follow up with that later and tidy it up.
Greg Hurrell [Tue, 31 Mar 2015 15:21:22 +0000 (08:21 -0700)]
Add more configurability for GPG user and preset command
You can now provide `GPG_USER` and `GPG_PRESET_COMMAND` environment
variables to override the defaults, or more permanently, you can (ab)use
`git config` via the keys `cipher.gpguser` and `cipher.presetcommand`.
Otherwise, the existing default values with be used.
Greg Hurrell [Sat, 28 Mar 2015 00:08:18 +0000 (17:08 -0700)]
Mostly alphabetize methods
I want this to be a single file, so decomposing it into
classes/modules/files isn't going to happen. In order to keep thing
manageable, let's just alphabetize everything except for the
`#initialize` method which stays at the top by convention.
Greg Hurrell [Fri, 27 Mar 2015 23:50:12 +0000 (16:50 -0700)]
Make external process calls more robust
Try to insulate us against crazy environments by shell-escaping
everything, and print a helpful message when a dependency isn't
available on the system.
Greg Hurrell [Fri, 27 Mar 2015 16:34:49 +0000 (09:34 -0700)]
Teach command_name to be context aware
Identify self as `git cipher` when run as a Git subcommand, or
`git-cipher` otherwise. Maybe a bit flakey and platform-dependent, based
on the use of `ps`, which is why I'm using `rescue` here.
Greg Hurrell [Fri, 27 Mar 2015 15:59:59 +0000 (08:59 -0700)]
Rename `encrypt` to `git-cipher`
This is the first step in the process of merging `encrypt` and `decrypt`
into a single command with subcommands. The docs and pretty much
everything else will need to be updated, but I'm going to do this in
small steps to make the changes legible in the commit history