#!/usr/bin/env perl # 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 . # EXAMPLE # # % git log --format='format:%H' \ # --since='1 day ago' --grep='delete junk' --grep='delete more junk' \ # | xargs annex-drop-files-deleted-by-commit use 5.028; use strict; use warnings; use lib "$ENV{HOME}/src/dotfiles/perl5"; use File::Path qw(rmtree); use File::Temp qw(tempdir); use Git::Wrapper; use Try::Tiny; use Local::ScriptStatus; use Local::Interactive qw(prompt_yn); use File::chdir; use Cwd; my $git = Git::Wrapper->new(getcwd); #<<< try { $git->rev_parse({ git_dir => 1 }); } catch { die "pwd doesn't look like a git repository ..\n"; }; #>>> my $temp = tempdir CLEANUP => 1; chmod 0700, $temp; $git->worktree("add", { force => 1, no_checkout => 1, detach => 1 }, $temp); my $worktree = Git::Wrapper->new($temp); for (@ARGV) { local $CWD = $temp; my ($commit) = $git->rev_parse($_); my @deleted_files = $git->RUN( qw(-c core.quotePath=false diff), { name_only => 1, diff_filter => 'D' }, "$commit~1..$commit" ); $worktree->checkout("$commit~1"); # We ought to be able to just `ga drop` the files here, but the # symlinks might be broken if the repo is bare and has # .git/annex/objects organised differently. And 'lookupkey' # doesn't work in bare repos either. So, extract the key from the # symlink my @deleted_keys; for (@deleted_files) { readlink =~ /SHA256E-s[0-9]+--[0-9a-f]+\.[a-zA-Z0-9]+$/; $& or die "couldn't determine key of $_"; push @deleted_keys, $&; } # using dropkey is like passing --force to `git annex drop` say_spaced_bullet "Will drop with --force:"; # for (my $i = 0 ; $i < @deleted_files ; $i++) { # say "$deleted_files[$i] $deleted_keys[$i]"; # } say for @deleted_files; say ''; if (prompt_yn "Go ahead with this?") { say for $git->annex(qw|dropkey --force|, @deleted_keys); } } # we can't use `git worktree remove` because the way git-annex # worktree support works breaks that command: git-annex replaces the # .git worktree file with a symlink rmtree $temp; $git->worktree("prune");