From 05167b4f504b2eb9a64783be0f1b26efad5a8b0e Mon Sep 17 00:00:00 2001 From: Sean Whitton Date: Sun, 28 Feb 2021 13:19:48 -0700 Subject: Rename annex-review-unused to git-annex-reviewunused Signed-off-by: Sean Whitton --- Changes | 2 + README | 4 +- bin/annex-review-unused | 61 ----------- bin/git-annex-reviewunused | 61 +++++++++++ lib/App/annex_review_unused.pm | 211 -------------------------------------- lib/App/git_annex_reviewunused.pm | 211 ++++++++++++++++++++++++++++++++++++++ t/24_annex-review-unused.t | 37 ------- t/24_git-annex-reviewunused.t | 37 +++++++ 8 files changed, 313 insertions(+), 311 deletions(-) delete mode 100755 bin/annex-review-unused create mode 100755 bin/git-annex-reviewunused delete mode 100644 lib/App/annex_review_unused.pm create mode 100644 lib/App/git_annex_reviewunused.pm delete mode 100755 t/24_annex-review-unused.t create mode 100755 t/24_git-annex-reviewunused.t diff --git a/Changes b/Changes index a7995b0..30f4ec4 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,8 @@ Revision history for Git::Annex {{$NEXT}} + - Rename annex-review-unused to git-annex-reviewunused now that git-annex + supports third party subcommands. 0.006 2020-03-23 17:02:28-07:00 America/Phoenix - annex-review-unused: Check whether unused files still exist earlier. diff --git a/README b/README index d550c62..b32b1c2 100644 --- a/README +++ b/README @@ -8,7 +8,7 @@ Git::Annex -- class representing a git-annex repository annex-to-annex -- use hardlinks to migrate files between git annex repos -annex-review-unused -- interactively process `git annex unused` output +git-annex-reviewunused -- interactively process `git annex unused` output INSTALLATION @@ -28,7 +28,7 @@ After installing, you can find documentation for this module and its scripts with the perldoc & man commands. % perldoc Git::Annex - % man annex-review-unused + % man git-annex-reviewunused You can also look for information at: diff --git a/bin/annex-review-unused b/bin/annex-review-unused deleted file mode 100755 index 99d8798..0000000 --- a/bin/annex-review-unused +++ /dev/null @@ -1,61 +0,0 @@ -#!/usr/bin/perl -# PODNAME: annex-review-unused -# ABSTRACT: 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 SYNOPSIS - -B [B<--just-print>] [B<--from=>I] [B<--used-refspec=>I] - -=head1 DESCRIPTION - -This program lets you interactively review unused files in a git annex -repository, choosing which you'd like to drop. By running git-log(1), -it provides more information about unused files than does B. - -=head1 OPTIONS - -=over 4 - -=item B<--just-print> - -Run non-interactively: gather and print information about unused -files, and then exit. - -=item B<--from=>I - -Passed on to B. - -=item B<--used-refspec=>I - -Passed on to B. - -=back - -=head1 EXIT STATUS - -0 if there are no unused files left at time of program exit, 1 if there are. - -=head1 SEE ALSO - -git-annex-unused(1), git-annex-dropunused(1) - -=cut - -use App::annex_review_unused; -exit App::annex_review_unused->main; diff --git a/bin/git-annex-reviewunused b/bin/git-annex-reviewunused new file mode 100755 index 0000000..b4fa7e3 --- /dev/null +++ b/bin/git-annex-reviewunused @@ -0,0 +1,61 @@ +#!/usr/bin/perl +# PODNAME: git-annex-reviewunused +# ABSTRACT: 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 SYNOPSIS + +B [B<--just-print>] [B<--from=>I] [B<--used-refspec=>I] + +=head1 DESCRIPTION + +This program lets you interactively review unused files in a git annex +repository, choosing which you'd like to drop. By running git-log(1), +it provides more information about unused files than does B. + +=head1 OPTIONS + +=over 4 + +=item B<--just-print> + +Run non-interactively: gather and print information about unused +files, and then exit. + +=item B<--from=>I + +Passed on to B. + +=item B<--used-refspec=>I + +Passed on to B. + +=back + +=head1 EXIT STATUS + +0 if there are no unused files left at time of program exit, 1 if there are. + +=head1 SEE ALSO + +git-annex-unused(1), git-annex-dropunused(1) + +=cut + +use App::git_annex_reviewunused; +exit App::git_annex_reviewunused->main; diff --git a/lib/App/annex_review_unused.pm b/lib/App/annex_review_unused.pm deleted file mode 100644 index dd2ed23..0000000 --- a/lib/App/annex_review_unused.pm +++ /dev/null @@ -1,211 +0,0 @@ -package App::annex_review_unused; -# ABSTRACT: 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 . - -use 5.028; -use strict; -use warnings; - -use subs qw(main exit); -use Getopt::Long; -use Git::Annex; -use Try::Tiny; -use Term::ReadKey; -use Term::ANSIColor; - -my $exit_main = 0; - -CORE::exit main unless caller; - -=func main - -Implementation of annex-review-unused(1). Please see documentation -for that command. - -Normally takes no arguments and responds to C<@ARGV>. If you want to -override that you can pass an arrayref of arguments, and those will be -used instead of the contents of C<@ARGV>. - -=cut - -sub main { - shift if $_[0] and ref $_[0] eq ""; # in case main called as a class method - local @ARGV = @{ $_[0] } if $_[0] and ref $_[0] ne ""; - - 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; - #<<< - try { - ($uuid) = $annex->git->config("remote." . $from_arg . ".annex-uuid"); - } catch { - die "couldn't determine an annex UUID for $from_arg remote"; - }; - #>>> - } - $unused_opts{used_refspec} = $used_refspec_arg if $used_refspec_arg; - - my @to_drop; - my @unused_files = grep { - # 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 $ret = $_->{contentlocation} - = $annex->abs_contentlocation($_->{key}); - - if ($from_arg) { - #<<< - try { - $annex->annex->readpresentkey($_->{key}, $uuid); - } catch { - $ret = 0; - }; - #>>> - } - - $ret; - } $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]; - my $contentlocation = $unused_file->{contentlocation}; - - 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 = map { s/^/ /r } @{ $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 5 + @log_lines > $height; - } - 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--; - 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 with --force:"); - say "@to_drop\n"; - $annex->annex->dropunused(\%dropunused_args, "--force", @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); - - EXIT_MAIN: - return $exit_main; -} - -sub _say_bold { print colored(['bold'], @_), "\n" } - -sub _say_bullet { _say_bold(" • ", @_) } - -sub _say_spaced_bullet { _say_bold("\n", " • ", @_, "\n") } - -sub _prompt_yn { - my $prompt = shift; - local $| = 1; - my $response; - while (1) { - print colored(['bold'], "$prompt "); - chomp(my $response = ); - return 1 if lc($response) eq "y"; - return 0 if lc($response) eq "n"; - say "invalid response"; - } -} - -sub exit { $exit_main = shift // 0; goto EXIT_MAIN } - -1; diff --git a/lib/App/git_annex_reviewunused.pm b/lib/App/git_annex_reviewunused.pm new file mode 100644 index 0000000..175d7a0 --- /dev/null +++ b/lib/App/git_annex_reviewunused.pm @@ -0,0 +1,211 @@ +package App::git_annex_reviewunused; +# ABSTRACT: 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 . + +use 5.028; +use strict; +use warnings; + +use subs qw(main exit); +use Getopt::Long; +use Git::Annex; +use Try::Tiny; +use Term::ReadKey; +use Term::ANSIColor; + +my $exit_main = 0; + +CORE::exit main unless caller; + +=func main + +Implementation of git-annex-reviewunused(1). Please see documentation +for that command. + +Normally takes no arguments and responds to C<@ARGV>. If you want to +override that you can pass an arrayref of arguments, and those will be +used instead of the contents of C<@ARGV>. + +=cut + +sub main { + shift if $_[0] and ref $_[0] eq ""; # in case main called as a class method + local @ARGV = @{ $_[0] } if $_[0] and ref $_[0] ne ""; + + 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; + #<<< + try { + ($uuid) = $annex->git->config("remote." . $from_arg . ".annex-uuid"); + } catch { + die "couldn't determine an annex UUID for $from_arg remote"; + }; + #>>> + } + $unused_opts{used_refspec} = $used_refspec_arg if $used_refspec_arg; + + my @to_drop; + my @unused_files = grep { + # 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 $ret = $_->{contentlocation} + = $annex->abs_contentlocation($_->{key}); + + if ($from_arg) { + #<<< + try { + $annex->annex->readpresentkey($_->{key}, $uuid); + } catch { + $ret = 0; + }; + #>>> + } + + $ret; + } $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]; + my $contentlocation = $unused_file->{contentlocation}; + + 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 = map { s/^/ /r } @{ $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 5 + @log_lines > $height; + } + 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--; + 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 with --force:"); + say "@to_drop\n"; + $annex->annex->dropunused(\%dropunused_args, "--force", @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); + + EXIT_MAIN: + return $exit_main; +} + +sub _say_bold { print colored(['bold'], @_), "\n" } + +sub _say_bullet { _say_bold(" • ", @_) } + +sub _say_spaced_bullet { _say_bold("\n", " • ", @_, "\n") } + +sub _prompt_yn { + my $prompt = shift; + local $| = 1; + my $response; + while (1) { + print colored(['bold'], "$prompt "); + chomp(my $response = ); + return 1 if lc($response) eq "y"; + return 0 if lc($response) eq "n"; + say "invalid response"; + } +} + +sub exit { $exit_main = shift // 0; goto EXIT_MAIN } + +1; diff --git a/t/24_annex-review-unused.t b/t/24_annex-review-unused.t deleted file mode 100755 index 4947455..0000000 --- a/t/24_annex-review-unused.t +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/perl - -use 5.028; -use strict; -use warnings; -use lib 't/lib'; - -use App::annex_review_unused; -use Test::More; -use t::Setup; -use t::Util; -use File::chdir; -use File::Spec::Functions qw(rel2abs); -use Capture::Tiny qw(capture_stdout); - -plan skip_all => "git-annex not available" unless git_annex_available; - -with_temp_annexes { - my (undef, $source1) = @_; - my ($output, $exit); - - { - local $CWD = "source1"; - (undef, undef, $exit) = run_bin "annex-review-unused"; - ok !$exit, "it exits zero when no unused files"; - sleep 1; - $source1->rm("foo/foo2/baz"); - $source1->commit({ message => "rm" }); - - ($output, undef, $exit) = run_bin qw(annex-review-unused --just-print); - ok $exit, "it exits nonzero when unused files"; - ok 20 < @$output && @$output < 30, "it prints ~two log entries"; - like $output->[5], qr/unused file #1/, "it prints an expected line"; - } -}; - -done_testing; diff --git a/t/24_git-annex-reviewunused.t b/t/24_git-annex-reviewunused.t new file mode 100755 index 0000000..b84b608 --- /dev/null +++ b/t/24_git-annex-reviewunused.t @@ -0,0 +1,37 @@ +#!/usr/bin/perl + +use 5.028; +use strict; +use warnings; +use lib 't/lib'; + +use App::git_annex_reviewunused; +use Test::More; +use t::Setup; +use t::Util; +use File::chdir; +use File::Spec::Functions qw(rel2abs); +use Capture::Tiny qw(capture_stdout); + +plan skip_all => "git-annex not available" unless git_annex_available; + +with_temp_annexes { + my (undef, $source1) = @_; + my ($output, $exit); + + { + local $CWD = "source1"; + (undef, undef, $exit) = run_bin "git-annex-reviewunused"; + ok !$exit, "it exits zero when no unused files"; + sleep 1; + $source1->rm("foo/foo2/baz"); + $source1->commit({ message => "rm" }); + + ($output, undef, $exit) = run_bin qw(git-annex-reviewunused --just-print); + ok $exit, "it exits nonzero when unused files"; + ok 20 < @$output && @$output < 30, "it prints ~two log entries"; + like $output->[5], qr/unused file #1/, "it prints an expected line"; + } +}; + +done_testing; -- cgit v1.2.3