#!/usr/bin/perl
# Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
#
# @APPLE_LICENSE_HEADER_START@
# 
# This file contains Original Code and/or Modifications of Original Code
# as defined in and that are subject to the Apple Public Source License
# Version 2.0 (the 'License'). You may not use this file except in
# compliance with the License. Please obtain a copy of the License at
# http://www.opensource.apple.com/apsl/ and read it before using this
# file.
# 
# The Original Code and all software distributed under the License are
# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
# Please see the License for the specific language governing rights and
# limitations under the License.
# 
# @APPLE_LICENSE_HEADER_END@

use strict;
use File::Basename ();
use File::Find ();
use Getopt::Std ();

my $MyName = File::Basename::basename($0);
my $N = 100;
my $MinSize = 64;
my %inodes;
my @symlinks;
our $opt_d = '';

sub wanted {
    return unless /\.[\dn][a-z]*$/;
    if(-l $_) {
	push(@symlinks, $_);
    } elsif(-f _) {
	return if -s _ < $MinSize;
	my($dev, $ino) = stat(_);
	my $list = $inodes{$ino};
	$list = $inodes{$ino} = [] unless defined($list);
	push(@$list, $_);
    }
}

sub usage {
    die "Usage: $MyName [-d prefix] dir ...\n";
}

Getopt::Std::getopts('d:');
usage() unless scalar(@ARGV) > 0;

for my $dir (@ARGV) {
    $dir = $opt_d . $dir if $opt_d ne '';
    next unless -e $dir;
    die "$dir: no such directory\n" unless -d _;

    %inodes = ();
    @symlinks = ();
    File::Find::find({
	wanted => \&wanted,
	no_chdir => 1,
    }, $dir);

    my(@compress, @links);
    for(values(%inodes)) {
	push(@compress, $_->[0]);
	push(@links, $_) if scalar(@$_) > 1;
    }

    my $count;
    while(($count = scalar(@compress)) > 0) {
	$_ = $count > $N ? $N : $count;
	my @args = splice(@compress, 0, $_);
	print "gzip -f @args\n";
	system('gzip', '-f', @args) == 0 or die "gzip failed\n";;
    }
    foreach my $list (@links) {
	my $main = shift(@$list);
	for(@$list) {
	    printf "rm $_; ln $main.gz $_.gz\n";
	    unlink $_ or die "Can't unlink: $!\n";
	    link("$main.gz", "$_.gz") or die "Can't link: $!\n";;
	}
    }
    for(@symlinks) {
	my $link = readlink($_);
	printf "rm $_; ln -s $link.gz $_.gz\n";
	unlink $_ or die "Can't unlink: $!\n";
	symlink("$link.gz", "$_.gz") or die "Can't symlink: $!\n";
    }
}
