X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?p=dupemerge;a=blobdiff_plain;f=dm6;h=0dcfab5778d56e17f6be1980d73fef2dc358c3da;hp=b0ff96b84b633c717bf0516038f74e6ae2be494d;hb=f34e832fb0a9b7bd96cfc05a14edd072bf4b32e0;hpb=a888bfab4a7685b300dbf8da06069dd3d2d75bf0 diff --git a/dm6 b/dm6 index b0ff96b..0dcfab5 100755 --- a/dm6 +++ b/dm6 @@ -63,11 +63,11 @@ 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; -(-d $link_dir) or usage; +usage unless $link_dir; my $prefix_length = 3; @@ -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"; } @@ -114,7 +125,7 @@ while () { next if ($st->nlink > $link_count_max); # Check link to inode - my $inode_link = prepare_parents("$link_dir/inode", $st->ino); + my $inode_link = prepare_parents($link_dir, $st->ino . 'I'); print STDERR 'I'; my $inode_st = lstat($inode_link); my $update_links; @@ -145,7 +156,7 @@ while () { $digest =~ y:/:_:; # Check link to digest - my $digest_link = prepare_parents("$link_dir/digest", $digest); + my $digest_link = prepare_parents($link_dir, "${digest}D"); print STDERR 'D'; my $digest_st = lstat($digest_link); if ($digest_st) { @@ -156,6 +167,10 @@ while () { undef $digest_st; } } + print STDERR "\b"; + + # Which file are we keeping? + my $keep_ino; # If digest link exists, link it to file if ($digest_st) { @@ -165,20 +180,33 @@ while () { # Old, replace input with old file print STDERR '-'; link_files($digest_link, $file); + $keep_ino = $digest_st->ino; } else { # New, add input to digest print STDERR '+'; link_files($file, $digest_link); + $keep_ino = $st->ino; } # A link to the inode indicates we are done, so do it last - link_files($file, $inode_link); + $inode_link = prepare_parents($link_dir, "${keep_ino}I"); + 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 . -type f -links -3 -print0 | xargs -0 rm -f") and die "system: exit status $?"; +print STDERR "\nRemoving empty directories..."; +system("find . -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__