summaryrefslogtreecommitdiff
path: root/scripts/git/empty-annexes-from
blob: d4eba1670b26d08bef5f3c2a81842b5db20bf024 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#!/usr/bin/env perl
use 5.036;

# This is for emptying a machine that's about to be reinstalled, scrapped etc.
# Assume HOME is the same there as here, and that it uses my ~/.mrconfig.
# We then process only annexes checked out both here and there.
# Before running this, mount a backup drive, s.t. git-annex is more likely to
# be happy about the number of copies that will remain after moving to here.

use Git::Annex;
use experimental "try";

our @leave_used = qw(lib/priv);

@ARGV == 1 or die "Exactly one argument required\n";
my $remote = $ARGV[0];
$remote =~ /\A[a-z]+\z/ or die "Remote name $remote not a short hostname?\n";
chdir;
my @annexes;
for (`mr ls`) {
    chomp;
    /^mr list: (?=\/)/ and -d $' or next;
    `git -C $' annex status 2>/dev/null`;
    $? and next;
    `ssh $remote git -C $' annex status 2>/dev/null`;
    $? or push @annexes, Git::Annex->new($');
}

my @not_done;

foreach my $annex (@annexes) {
    my $tl = $annex->toplevel;
    say "Processing $tl";
    (my $rel = $tl) =~ s#\A\Q$ENV{HOME}\E/##;
    try {
	my ($url) = $annex->git->remote("get-url", $remote);
	$url =~ /\A$remote:\Q$rel\E\z/
	  or die "$tl $remote remote URL form not recognised\n";
    } catch ($e) {
	$e =~ /No such remote/
	  ? $annex->git->remote("add", $remote, "$remote:$rel")
	  : die $e
    }

    $annex->annex->sync(qw(--no-content origin), $remote);
    $annex->annex->untrust($remote);

    chdir $tl;
    if (grep $_ eq $rel, @leave_used) {
	$annex->annex->unused({
	    used_refspec =>
"+refs/remotes/$remote/master:+refs/remotes/$remote/synced/master",
	    from => $remote
	});
	system(qw(git annex move --unused --numcopies=1), "--from=$remote")
	  == 0
	  or die "'git annex move --unused' for $rel exited non-zero\n";
	push @not_done, $rel;
	$annex->annex->sync(qw(--no-content origin), $remote);
    } else {
	$annex->annex->wanted($remote, "standard");
	$annex->annex->required($remote, "standard");
	$annex->annex->ungroup($remote, $_)
	  for split " ", ($annex->annex->group($remote))[0];
	$annex->annex->group($remote, "unwanted");
	system qw(git annex move --all), "--from=$remote";

	my @objects = `ssh $remote find $tl/.git/annex/objects`;
	if (    @objects == 1
	    and $? == 0
	    and system("ssh $remote git -C $tl annex uninit") == 0) {
	    $annex->annex->dead($remote);
	    $annex->annex->sync("origin");
	} else {
	    push @not_done, $rel;
	    $annex->annex->sync("origin", $remote);
	}
    }

    $annex->git->remote("rm", $remote);
}

$" = ", ";
warn "Annexes that remain on $remote: @not_done\n" if @not_done;