git-crypt
git-crypt copied to clipboard
please add subcommand to determine lock state
I find that I'm wondering, "is my git-crypt repository locked, or unlocked?" Sometimes, I cannot remember. Then have to go poking in files to see... unless there is some easier way I missed?
Suggest a command, perhaps git-crypt lockstate
that tells the user
whether it's locked. Give this a 'quiet' flag to have no output (maybe
in this case, name it git-crypt islocked
and have zero be 'yes').
A [maybe better] alternative would be adding this information to
status
output (although status
is more parsable as-is, one file per line)
or giving it an option (maybe -l
or -k
) to determine the locked state
(which could then be combined with quiet flag from #68 for no output).
+1, i 'regularly' have the sane problem, and I can't remember which state it is in. So havung a quick and easy cmd to check this woudl be great. (also if preventing a 'second' or 'third' 'init' on an exisitng repo coudl be prevented, or at least warned about, that wouydl be great too, so one doesn't get into the messed up state I got myself into.)
Doesn't git-crypt status
do this?
That only says whether the files will be encrypted when locked. It's just an attribute lookup and says nothing of the current encryption state. I think you're right that "status" is possibly the wrong word for what that command does.
I usually have to resort to paging the file and looking for garbled characters to check if it's encrypted, which is silly but works.
I may be mistaken, but git-crypt status
is what I always use to see if there's a file that's supposed to be encrypted but is actually stored plaintext in the repo (you get an error in the output). Is that not so for you?
@skorokithakis This issue seems to be about the current lock/unlock state of the workng copy, not the encrypted/plain state of the repository object store. Different problem and git crypt status
works for what you says it does, but that's not actually the information being sought here.
This would be really helpful, I have a couple of make targets that require the repo to be in unlocked state, I still don't want to unlock it in the target since I want unlock and lock to be user triggered. But it's currently tricky to sanity check the state and warn the user about it.
If you are curious about my current workaround:
grep -rq "\x0GITCRYPT" path && echo "Locked" || echo "Unlocked"
I have a function to do this:
$ grep -qsPa "\x00GITCRYPT" $(git ls-tree -r master --name-only)
It returns 0
if locked or 1
if unlocked.
The subshell returns the list of tracked files and these are checked for the magic string. If any files are found to contain this then the repo is assumed to be locked.
Note assumed - this isn't guaranteed!
An improvement is to only check the encrypted files:
$ grep -qsPa "\x00GITCRYPT" $(git crypt status | grep -v '^not' | awk '{print $2}')
(thanks to @tiwilliam for the initial suggestion that led to this method).
Is there a reason why you grep all the crypted files? Checking just the first/last one should be sufficient, no?
And I think the '-e' option could be used (instead of grep -v ^not
).
My proposition:
$ grep -qsPa "\x00GITCRYPT" $(git crypt status -e | head -n1 | awk '{print $2}')
I just did a quick test and I found that it is much faster to just grep everything because git crypt status -e
is too slow:
$ time grep -qsPa "\x00GITCRYPT" $(git ls-tree -r master --name-only)
real 0m0.020s
user 0m0.019s
sys 0m0.001s
$ time grep -qsPa "\x00GITCRYPT" $(git crypt status -e | head -n1 | awk '{print $2}')
real 0m7.077s
user 0m5.564s
sys 0m1.817s
Ok, I see. Problem is that on a big git repository both method are too slow (tested with 5261 files)...
I would suggest the following on big repos:
$ git ls-tree -r master --name-only | sed 's/.*/"&"/' | xargs grep -qsPa "\x00GITCRYPT"
note: sed is needed if you have files with space in their names (surround with double quotes).
Small improvement on @fauust' suggestion
git ls-tree -r --name-only -z HEAD some/path/ | xargs -0 grep -qsPa "\x00GITCRYPT"
-
HEAD
is the git ref-ish to look at (can use branch names, commit IDs, etc too) -
some/path/
is a path to look under — can omit to search the entire directory tree, or repeat to search multiple paths. If you run it from a subdirectory in the repository working tree it'll only search that, andsome/path/
is relative to there. - handles files with spaces/etc by using nulls between paths
- return is 0 if locked and non-zero if unlocked.
xargs -0
is much better and elegant than my ugly sed
indeed!
Tested and adopted, thanks @rcoup!
BTW, if you need an even faster alternative, I recently discovered ripgrep. Here is a comparison on the webkit repo:
❯ git ls-tree -r --name-only -z HEAD | time xargs -0 grep -qsPa "\x00GITCRYPT"
xargs -0 grep -qsPa "\x00GITCRYPT" 20.38s user 2.56s system 77% cpu 29.440 total
❯ git ls-tree -r --name-only -z HEAD | time xargs -0 rg -qsPa "\x00GITCRYPT"
xargs -0 rg -qsPa "\x00GITCRYPT" 27.58s user 3.83s system 379% cpu 8.271 total
I recently ran into wanting this feature and ended up using the following to tell if the repo is locked or not:
$ git config --local --get filter.git-crypt.smudge
if the output is blank it's locked, if it returns the smudge command then it's unlocked. I integrated this into my prompt by just searching the .git/config
file for the filter section instead as it didn't involve shelling out to a subprocess.
That's obviously even better/cleaner, thanks @Cadair !
Having a status option would make scripting around checking easier.
Thank you @Cadair for a direct plumbing way to check. It should be noted, that git command will throw an exit code of 1, if the value isn't found.