App-Fetchware

 view release on metacpan or  search on metacpan

bin/fetchware  view on Meta::CPAN

        # What the user specified or tmpdir() must be a directory.
        die <<EOD if not -d $fetchware_temp_dir;
fetchware: The specified directory [$fetchware_temp_dir] is not a directory or
does not exist. Please only specify directories that exist, and ones you have
read and write permission in. OS error [$!].
EOD

        # Store all of the fetchware-* temp dirs in @globbed_fetchware_temp_dirs
        # for later processing.
        for my $fetchware_file_or_dir (
            glob(catfile($fetchware_temp_dir, 'fetchware-*')),
            glob(catfile($fetchware_temp_dir, 'Fetchwarefile-*'))
        ) {
            # If it's a directory add it to the queue of directories to delete
            # below.
            if (-d $fetchware_file_or_dir) {
                push @globbed_fetchware_temp_dirs, $fetchware_file_or_dir;
            # If it's just a file just delete right away.
            } else {
                ###BUGALERT### Should I check if the current user has perms to
                #delete the file before deleting it? What about root? Should
                #root delete all files found even for other users? I'll go with
                #the Unix default of just doing the operation, and dealing with
                #the error message you receive to avoid the complexity of
                #checking perms. Furthermore, what about Unix ACLs and Windows'
                #ACL style perms? It's not worth dealing with that hassel.
                unlink $fetchware_file_or_dir or die <<EOD;
fetchware: Failed to unlink file [$fetchware_file_or_dir]. OS error [$!].
EOD
                    vmsg <<EOM;
fetchware clean found and deleted file [$fetchware_file_or_dir].
EOM
            }
        }
    }

    msg "fetchware clean found no fetchware temporary directories to clean"
        if @globbed_fetchware_temp_dirs < 1;

    # Holds the number of directories that had errors when they were
    # deleted.
    my $num_remove_tree_errors = 0;
    # Number of directories remove_tree removed successfully.
    my $num_remove_tree_successes = 0;


    # Loop over fetchware temp dirs, and delete the ones that are not locked.
    for my $temp_dir (@globbed_fetchware_temp_dirs) {
        # Try to lock the 'fetchware.sem' semaphore lock file

        # I annoying must open the file before I can see if I can lock it or
        # not.
        my $sem_lock_file = catfile($temp_dir, 'fetchware.sem');
        my $fh_sem;
        if (open $fh_sem, '>', $sem_lock_file) {
            vmsg "Successfully created [fetchware.sem] semaphore lock file.";
        } else {
            # Test if the lockfile has the same owner uid as this running perl
            # process, and if they differ skip deleting this one, because we
            # lack the perms to do it anyway.
            if ($> != (stat($sem_lock_file))[4]) {
                msg "Skipping file [$sem_lock_file], because a different user created it.";
                next;
            } else {
                die <<EOD;
App-Fetchware-Util: Failed to create [$sem_lock_file] semaphore lock file! This
should not happen, because fetchware is creating this file in a brand new
directory that only fetchware should be accessing. You simply shouldn't see this
error unless some one is messing with fetchware, or perphaps there actually is a
bug? I don't know, but this just shouldn't happen. It's so hard to trigger it to
happen, it can't easily be tested in fetchware's test suite. OS error [$!].
EOD
            }
        }
        # Now flock 'fetchware.sem.' This should
        # Use LOCK_NB so flock won't stupidly wait forever and ever until 
        # he lock becomes available.
        # If flock fails, don't die! Instead, just skip deleting this
        # fetchware temporary directory, and go on to the next one.
        unless (flock $fh_sem, LOCK_EX | LOCK_NB) {
            # Flock failed, something else has the lock, print message, and skip
            # this directory, and go on to the next one.
            msg <<EOM;
[$temp_dir] locked by another fetchware process. Skipping.
EOM
            next;
        }

        # Delete the whole $tempdir. Use error and result for File::Path's
        # experimental error handling, and set safe to true to avoid borking the
        # filesystem. This might be run as root, so it really could screw up
        # your filesystem big time! So set safe to true to avoid doing so.
        remove_tree($temp_dir, {
            error => \my $err,
            result => \my $res,
            safe => 1} );

        # Parse remove_tree()'s insane error handling system. It's expirimental,
        # but it's been experimental forever, so I can't see it changing.
        if (@$err) {
            $num_remove_tree_errors++;
            for my $diag (@$err) {
                my ($file, $message) = %$diag;
                if ($file eq '') {
                    warn "general error: $message\n";
                } else {
                    warn "problem unlinking $file: $message\n";
                }
            }
        } else {
            vmsg "No errors encountered during removal of [$temp_dir]\n";
        }

        if (@$res) {
            # Keep track of each successfully removed directory.
            $num_remove_tree_successes++;
            vmsg "unlinked [$_]" for @$res;
        }
    }

    # Summarize success or failure for user, so he doesn't have to dig



( run in 1.439 second using v1.01-cache-2.11-cpan-39bf76dae61 )