#!/usr/bin/perl -w
# $Id: touch-dirs,v 1.4 2011/08/07 17:32:38 tom Exp $
# Traverse the given directory tree(s), and set the modification time on each
# directory to match the newest file in the directory (or its subdirectories).
# Ignore symbolic links.
#
# This is used to make "identical" tarballs from a given directory at different
# times, using "archive -t".

use strict;

use Getopt::Std;
use File::stat;

use vars qw($opt_n $opt_v);

sub touch_dirs($) {
    my $pathname = $_[0];
    my $newest   = 0;
    my $modtime;
    my @list;
    my $sb;
    my $n;
    my $dh;

    printf "** %s\n", $pathname if $opt_v;

    opendir( DIR, $pathname ) || die "can't opendir $pathname: $!";
    @list = sort readdir(DIR);
    closedir DIR;

    for $n ( 0 .. $#list ) {
        next if ( $list[$n] eq "." );
        next if ( $list[$n] eq ".." );

        my $item = $pathname . "/" . $list[$n];

        $sb = lstat $item;
        next if ( $sb->mode & 020000 );    # symbolic link

        printf "%d:%s\n", $n, $item if $opt_v;
        $modtime = $sb->mtime;
        if ( $sb->mode & 040000 ) {
            $modtime = &touch_dirs($item);
        }
        if ( $modtime > $newest ) {
            printf "...newer %s\n", scalar localtime $modtime if $opt_v;
            $newest = $modtime;
        }
    }

    if ( $newest ne 0 ) {
        if ($opt_n) {
            $sb = lstat $pathname;
            if ( $sb->mtime ne $newest ) {
                printf "...touch %s %s\n", scalar localtime $newest, $pathname;
            }
        }
        else {
            utime $newest, $newest, $pathname;
        }
    }
    return $newest;
}

&getopts('nv');

if ( $#ARGV >= 0 ) {
    while ( $#ARGV >= 0 ) {
        &touch_dirs( shift @ARGV );
    }
}
else {
    &touch_dirs(".");
}
