From 0db12ef8b87b37a9b7d55be5f8d4c2545b1dd0e4 Mon Sep 17 00:00:00 2001 From: Guilhem Moulin Date: Fri, 27 Mar 2015 03:10:05 +0100 Subject: Add a 'git' command. --- cli/icevault | 51 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 3 deletions(-) (limited to 'cli/icevault') diff --git a/cli/icevault b/cli/icevault index c93a608..67e06ec 100755 --- a/cli/icevault +++ b/cli/icevault @@ -35,7 +35,7 @@ delete @ENV{qw/IFS CDPATH ENV BASH_ENV/}; my $LANGINFO = I18N::Langinfo::langinfo(I18N::Langinfo::CODESET()); my $LOCALE = Encode::find_encoding $LANGINFO; -my (%CONFIG, @GPG); +my (%CONFIG, @GIT, @GPG); my $SOCKET; @@ -146,6 +146,12 @@ sub loadConfig() { error "C<%s> must contain %%s, %%h and %%i placeholders", 'template' unless $CONFIG{template} =~ /%s/ and $CONFIG{template} =~ /%h/ and $CONFIG{template} =~ /%i/; + $CONFIG{'git-dir'} //= '.git'; + $CONFIG{'git-dir'} =~ s#\A~/#$ENV{HOME}#; + $CONFIG{'git-dir'} = "$CONFIG{store}/$CONFIG{'git-dir'}" unless $CONFIG{'git-dir'} =~ /\A\//; + $CONFIG{'git-dir'} =~ /\A(\/\p{Print}+)\z/ or error "Insecure C<%s>", $CONFIG{'git-dir'}; + $CONFIG{'git-dir'} = $1; # untaint $CONFIG{'git-dir'} + $CONFIG{socket} //= 'socket'; $CONFIG{socket} =~ s#\A~/#$ENV{HOME}#; @@ -169,6 +175,7 @@ sub loadConfig() { error "Insecure C<%s>", $CONFIG{gpg} unless $CONFIG{gpg} =~ /\A([-_\@a-zA-Z0-9\.%\/= ]+)\z/; $CONFIG{gpg} = $1; + @GIT = ('git', '--work-tree='.$CONFIG{store}, '--git-dir='.$CONFIG{'git-dir'}); @GPG = split / /, $CONFIG{gpg}; } @@ -453,8 +460,6 @@ sub saveIdentityFile($$) { unlink $outfh->filename or error "Can't unlink C<%s>: %s", $outfh->filename, $!; error "Can't move C<%s> to C<%s>: %s", $outfh->filename, $filename, $r; } - - # TODO: git add $filename; git commit } # Get the visible form list from the server, and croak if it's empty. @@ -580,6 +585,25 @@ sub sha256_file($) { return $sha256->digest; } +# Add the given @filenames to the index and if there are any staged +# changes for these files, commit them with the given message. +sub commit($@) { + my $msg = shift; + my @filenames = @_; + + return unless -d $CONFIG{'git-dir'} and @filenames; + mysystem @GIT, 'add', @filenames; + + # check if there are any staged changes on @filenames + system {$GIT[0]} @GIT, 'diff', '--quiet', '--staged', '--', @filenames; + return unless $?; # exit value 0: nothing staged + error "C<%s> exited with value %d", $GIT[0], ($? >> 8) if $? and $? != -1 and $? != 256; + + $msg =~ /\A(\p{Print}*)\z/ or error "Insecure C<%s>", $msg; + $msg = $1; # untaint $msg + mysystem @GIT, 'commit', '-m', $msg, '--', @filenames; +} + ####################################################################### @@ -594,6 +618,7 @@ my @USAGE = ( clip => "scheme://hostname/identity", dump => "[-p, --show-passwords] scheme://hostname/identity", edit => "scheme://hostname/identity", + git => "GIT-COMMAND [GIT-ARG ...]", insert => "[-f, --force] [-s, --socket=PATH] [identity]", ls => "[-0, --zero] [scheme://[hostname/[identity]]]", ); @@ -771,6 +796,7 @@ elsif ($COMMAND eq 'insert') { undef @{$form->{fields}}[@dontsave] if @dontsave; # remove the field we don't want to save myprintf "Saving identity C<%s>", "$uri/$id"; saveIdentityFile $form, $filename; + commit "Add new identity $uri/$id", $filename; } elsif ($COMMAND eq 'fill') { @@ -921,6 +947,7 @@ elsif ($COMMAND eq 'fill') { if ($changed) { my $r = promptYN "Save changes?", 0; saveIdentityFile ($myform, $filename) if $r; + commit "Save imported changes for $id", $filename; } } @@ -982,6 +1009,7 @@ elsif ($COMMAND eq 'edit') { } elsif (defined $fh2) { myprintf "Saving user changes for identity C<%s>", $id; saveIdentityFile($fh2, $filename); # use the FH we opened before unlinking + commit "Save manual (using $EDITOR) changes for $id", $filename; } else { print "Aborting\n"; exit 1; @@ -1039,6 +1067,23 @@ elsif ($COMMAND eq 'ls') { print $LOCALE->encode($_), $delim foreach sort keys %matches; } +elsif ($COMMAND eq 'git') { + getopts(); + usage() unless @ARGV; + + unless (-d $CONFIG{store}) { + require 'File/Path.pm'; + File::Path::make_path($CONFIG{store}); + myprintf "Created directory C<%s>", $CONFIG{store}; + } + + for (my $i = 0; $i <= $#ARGV; $i++) { + $ARGV[$i] =~ /\A(\p{print}*)\z/ or die; + $ARGV[$i] = $1; + } + exec {$GIT[0]} @GIT, @ARGV; +} + else { print STDERR "Usage: $NAME [COMMAND] [OPTION ...] [ARG ...]\n"; error "Unknown command C<%s>. Try C<%s> for more information.", $COMMAND, "$NAME --help"; -- cgit v1.2.3