aboutsummaryrefslogtreecommitdiffstats
path: root/cli/icevault
diff options
context:
space:
mode:
Diffstat (limited to 'cli/icevault')
-rwxr-xr-xcli/icevault51
1 files changed, 48 insertions, 3 deletions
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";