#!/usr/bin/perl

use strict;
use File::Spec;
use Getopt::Long;

my ($noexec, $rec, $ex, $ignore);
GetOptions("noexec"=>\$noexec, "recursive"=>\$rec, "exists"=>\$ex, "ignore"=>\$ignore);

if (!@ARGV) {
    die "usage: $0 [options] <path 1> ... <path n>

Converts absolute to relative links.  If a directory is specified, 
then all links in that directory are converted.

Options:

  -n*oexec       see what would be done
  -r*ecursive    recurse into all subdirectories
  -e*xists       only convert links that work
  -i*gnore       ignore errors, and keep going
"
}

my $count = 0;
for (my $arg = shift(@ARGV)) {
    $arg=File::Spec->rel2abs($arg);
    ln_abs2rel($arg);
}


warn("# $count links converted\n");

sub warn_or_die;
sub ln_abs2rel {
    my ($d) = @_;
    if (-d $d) {
#        warn("# Converting $d\n");
        my $io;
        warn_or_die "Can't open $d: $!\n" unless opendir($io, $d);
        while(my $f=readdir($io)) {
            next if $f eq '.' || $f eq '..';
            $f="$d/$f";
            if ($rec && -d $f && ! -l $f) {
                ln_abs2rel($f);
            } elsif (-f $f ) {
                ln_abs2rel($f);
            }
        }
    } else {
        my $f = $d;
        $d =~ s/\/[^\/]+$//;
        return unless -l $f;
        return unless !$ex || -e $f;
        my $l=readlink($f);
        if ($l =~ m{^/}) {
            my $t = $d;
            my $p = "";
            while ($t && ($l !~ $t)) {
                $t =~ s{/[^/]*$}{};
                $p .= "../";
            }
            if ($t =~ /\w/) {
                my $old_l = $l;
                $l =~ s{\Q$t/\E}{};
                $l = "$p$l";
                warn("$f: $old_l -> $l\n");
                if (!$noexec) {
                    if(!symlink($l, "$f.sym-tmp")) {
                        warn_or_die("Can't create symlink: $!\n");
                    } else {
                        if (!$ex || -e "$f.sym-tmp") {
                            rename("$f.sym-tmp", $f);
                        } else {
                            warn_or_die("Link failed somehow\n")
                        }
                    }
                }
                ++$count;
            }
        }
    }
}

sub warn_or_die {
    die @_ if !$ignore;
    warn @_ if $ignore;
}

