Fix the hardlinking hopefully once and for all
[dupemerge] / dm6
diff --git a/dm6 b/dm6
index c6f93d906e94025621b230a6baa07e83dda44a5f..2d554e3a9924cbf3810171cf924e1763d6cbda4c 100755 (executable)
--- a/dm6
+++ b/dm6
@@ -63,7 +63,7 @@ sub link_files {
                unlink($tmp_to) or warn "unlink: $tmp_to: $!";  # Try, possibly in vain, to clean up
                die "rename: $tmp_to -> $from: $saved_bang";
        }
-       print STDERR "\b \b";
+       print STDERR "\b";
 }
 
 my $link_dir = shift @ARGV;
@@ -81,14 +81,25 @@ sub slash_prefix {
        return ($prefix, $suffix);
 }
 
+sub mkdir_p {
+       my ($dir) = @_;
+       return if -d $dir;
+       $dir =~ s:/+$::os;
+       my $parent;
+       ($parent = $dir) =~ s:[^/]+$::os;
+       if ($parent ne $dir) {
+               mkdir_p($parent);
+               print STDERR 'm';
+               mkdir($dir) or die "mkdir: $dir: $!";
+       }
+       die "mkdir: $dir: $!" unless -d $dir;
+}
+
 sub prepare_parents {
        my ($link_dir, $file) = @_;
        my ($prefix, $suffix) = slash_prefix($file);
        my $parent = "$link_dir/$prefix";
-       print STDERR 'm';
-       mkpath($parent, { verbose => 0 });
-       print STDERR "\b";
-       die "mkpath: $parent: $!" unless -d $parent;
+       mkdir_p($parent);
        return "$parent/$suffix";
 }
 
@@ -159,7 +170,7 @@ while (<STDIN>) {
                        print STDERR "\b";
 
                        # Which file are we keeping?
-                       my $keep_file;
+                       my $keep_ino;
 
                        # If digest link exists, link it to file
                        if ($digest_st) {
@@ -169,23 +180,33 @@ while (<STDIN>) {
                                # Old, replace input with old file
                                print STDERR '-';
                                link_files($digest_link, $file);
-                               $keep_file = $digest_link;
+                               $keep_ino = $digest_st->ino;
                        } else {
                                # New, add input to digest
                                print STDERR '+';
                                link_files($file, $digest_link);
-                               $keep_file = $file;
+                               $keep_ino = $st->ino;
                        }
 
                        # A link to the inode indicates we are done, so do it last
-                       print STDERR '_';
-                       link_files($keep_file, $inode_link);
+                       $inode_link = prepare_parents("$link_dir/inode", $keep_ino);
+                       print STDERR ' ';
+                       link_files($digest_link, $inode_link);
 
                }
        };
        warn "$file: $@" if $@;
 }
 
+# Garbage collection
+print STDERR "\nGarbage collection in '$link_dir'...";
+chdir($link_dir) || die "chdir: $link_dir: $!";
+print STDERR "\nRemoving files with link count < 3...";
+system("find digest inode -type f -links -3 -print0 | xargs -0 rm -f") and die "system: exit status $?";
+print STDERR "\nRemoving empty directories...";
+system("find digest inode -type d -empty -print0 | xargs -0r rmdir -p --ignore-fail-on-non-empty") and die "system: exit status $?";
+print STDERR "\nDone.\n";
+
 exit(0);
 
 __END__