summaryrefslogtreecommitdiff
path: root/bin
diff options
context:
space:
mode:
authorSean Whitton <spwhitton@spwhitton.name>2020-02-02 13:18:59 -0700
committerSean Whitton <spwhitton@spwhitton.name>2020-02-02 13:18:59 -0700
commit0172381ef557b5083db4fbb1b64a0daec5570f98 (patch)
tree1ccaf14d9531c62fdcafaf11c58cc86a45213e4b /bin
parentd6eca5d1d0b2e6bf539f25ea10948c8c396cbe8e (diff)
downloadp5-Git-Annex-0172381ef557b5083db4fbb1b64a0daec5570f98.tar.gz
start importing annex-review-unused
Signed-off-by: Sean Whitton <spwhitton@spwhitton.name>
Diffstat (limited to 'bin')
-rwxr-xr-xbin/annex-review-unused170
1 files changed, 170 insertions, 0 deletions
diff --git a/bin/annex-review-unused b/bin/annex-review-unused
new file mode 100755
index 0000000..6de9109
--- /dev/null
+++ b/bin/annex-review-unused
@@ -0,0 +1,170 @@
+#!/usr/bin/perl
+
+# annex-review-unused -- interactively process `git annex unused` output
+#
+# Copyright (C) 2019-2020 Sean Whitton <spwhitton@spwhitton.name>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or (at
+# your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+=head1 NAME
+
+annex-review-unused - interactively process `git annex unused` output
+
+=head1 SYNOPSIS
+
+
+
+=head1 DESCRIPTION
+
+
+
+=cut
+
+use 5.028;
+use strict;
+use warnings;
+
+use Getopt::Long;
+use Git::Annex;
+use Try::Tiny;
+use Term::ReadKey;
+
+my $annex = Git::Annex->new;
+
+my $just_print = 0;
+my ($uuid, $from_arg, $used_refspec_arg, %unused_opts, %dropunused_args);
+GetOptions
+ 'from=s' => \$from_arg,
+ 'used-refspec=s' => \$used_refspec_arg,
+ 'just-print' => \$just_print;
+if ($from_arg) {
+ $unused_opts{from} = $dropunused_args{from} = $from_arg;
+ ($uuid) = $annex->git->config("remote." . $from_arg . ".annex-uuid");
+}
+$unused_opts{used_refspec} = $used_refspec_arg if $used_refspec_arg;
+
+my @to_drop;
+my @unused_files = @{ $annex->unused(%unused_opts, log => 1) };
+exit unless @unused_files;
+if ($just_print) {
+ say_spaced_bullet("There are unused files you can drop with"
+ . " `git annex dropunused':");
+ say " " . $_->{number} . " " . $_->{key} for @unused_files;
+ print "\n";
+}
+my $i = 0;
+UNUSED: while ($i < @unused_files) {
+ my $unused_file = $unused_files[$i];
+
+ # check the unused file still exists i.e. has not been dropped
+ # already (in the case of reviewing unused files at a remote, just
+ # check that it's not been dropped according to the local
+ # git-annex branch by using readpresentkey rather than
+ # checkpresentkey)
+ my $contentlocation = $annex->abs_contentlocation($unused_file->{key});
+ if ($from_arg) {
+ #<<<
+ try {
+ $annex->git->annex("readpresentkey", $unused_file->{key}, $uuid);
+ } catch {
+ splice @unused_files, $i, 1;
+ next UNUSED;
+ };
+ #>>>
+ } elsif (!$contentlocation) {
+ splice @unused_files, $i, 1;
+ next UNUSED;
+ }
+
+ system qw(clear -x) unless $just_print;
+ say_bold("unused file #" . $unused_file->{number} . ":");
+
+ if ($unused_file->{bad} or $unused_file->{tmp}) {
+ say " looks like stale tmp or bad file, with key "
+ . $unused_file->{key};
+ } else {
+ my @log_lines = @{ $unused_file->{log_lines} };
+ unless ($just_print) {
+ # truncate log output if necessary to ensure user's
+ # terminal does not scroll
+ my (undef, $height) = GetTerminalSize();
+ splice @log_lines, (($height - 5) - @log_lines)
+ if @log_lines > ($height - 5);
+ }
+ print "\n";
+ say for @log_lines;
+ unless ($just_print) {
+ my $response;
+ READKEY: while (1) {
+ # before prompting, clear out stdin, to avoid
+ # registered a keypress more than once
+ ReadMode 4;
+ 1 while defined ReadKey(-1);
+
+ my @opts = ('y', 'n');
+ push @opts, 'o' if $contentlocation;
+ push @opts, ('d', 'b') if $i > 0;
+ print "Drop this unused files? (" . join('/', @opts) . ") ";
+
+ # Term::ReadKey docs recommend ReadKey(-1) but that
+ # means we need an infinite loop calling ReadKey(-1)
+ # over and over, which ramps up system load
+ my $response = ReadKey(0);
+ ReadMode 0;
+
+ # respond to C-c
+ exit 0 if ord($response) == 3;
+
+ say $response;
+ $response = lc($response);
+ if ($response eq "y") {
+ push @to_drop, $unused_file->{number};
+ last READKEY;
+ } elsif ($response eq "n") {
+ last READKEY;
+ } elsif ($response eq "o" and defined $contentlocation) {
+ system "xdg-open", $contentlocation;
+ } elsif ($response eq "b" and $i > 0) {
+ $i--;
+ $i--;
+ pop @to_drop
+ if @to_drop
+ and $to_drop[$#to_drop] eq $unused_files[$i]->{number};
+ next UNUSED;
+ } elsif ($response eq "d" and $i > 0) {
+ # user wants to drop the list we've accumulated up
+ # until now and get out of this script
+ last UNUSED;
+ } else {
+ say "invalid response";
+ }
+ }
+ }
+ }
+ print "\n";
+ $i++;
+}
+
+if (@to_drop) {
+ say_spaced_bullet("Will dropunused"
+ . (exists $dropunused_args{force} ? " with --force:" : ":"));
+ say "@to_drop\n";
+ $annex->git->annex("dropunused", \%dropunused_args, @to_drop)
+ if prompt_yn("Go ahead with this?");
+}
+
+# exit value represents whether or not there are any unused files left
+# after this run. note that in --just-print mode, @to_drop will be
+# empty, so we'll always exit non-zero if there are any unused files
+exit @to_drop == @unused_files;