git-crypt icon indicating copy to clipboard operation
git-crypt copied to clipboard

please add subcommand to determine lock state

Open smemsh opened this issue 8 years ago • 17 comments

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).

smemsh avatar Oct 15 '15 23:10 smemsh

+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.)

TheBigBear avatar Oct 17 '15 10:10 TheBigBear

Doesn't git-crypt status do this?

skorokithakis avatar Apr 25 '16 17:04 skorokithakis

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.

smemsh avatar Apr 26 '16 23:04 smemsh

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 avatar Apr 27 '16 00:04 skorokithakis

@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.

alerque avatar Apr 27 '16 05:04 alerque

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.

tiwilliam avatar Nov 29 '16 11:11 tiwilliam

If you are curious about my current workaround:

grep -rq "\x0GITCRYPT" path && echo "Locked" || echo "Unlocked"

tiwilliam avatar Nov 29 '16 11:11 tiwilliam

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).

johnlane avatar Jan 26 '17 15:01 johnlane

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}')

fauust avatar Jun 27 '17 21:06 fauust

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

johnlane avatar Jun 28 '17 10:06 johnlane

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).

fauust avatar Jun 28 '17 14:06 fauust

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, and some/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.

rcoup avatar Sep 10 '20 11:09 rcoup

xargs -0 is much better and elegant than my ugly sed indeed! Tested and adopted, thanks @rcoup!

fauust avatar Sep 10 '20 11:09 fauust

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

fauust avatar Sep 10 '20 13:09 fauust

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.

Cadair avatar May 18 '22 12:05 Cadair

That's obviously even better/cleaner, thanks @Cadair !

fauust avatar May 18 '22 13:05 fauust

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.

lordkage avatar Jul 08 '22 18:07 lordkage