From 0172381ef557b5083db4fbb1b64a0daec5570f98 Mon Sep 17 00:00:00 2001 From: Sean Whitton Date: Sun, 2 Feb 2020 13:18:59 -0700 Subject: start importing annex-review-unused Signed-off-by: Sean Whitton --- bin/annex-review-unused | 170 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 170 insertions(+) create mode 100755 bin/annex-review-unused 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 +# +# 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 . + +=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; -- cgit v1.2.3