#!/bin/perl
###############################################################################
#
# Parse a stream of git status --porcelain -z lines and output the file
# paths that have been modified/added/renamed in the work tree.
#
# Input is expected to be in the format defined for
#     git status --porcelain -z
#
# Usage: git status --porcelain -z | chaned-wt-files.pl
#
################################################################################

use strict;

my $verbose;

foreach my $arg (@ARGV) {
    if ($arg eq '--verbose') {
        $verbose = 1;
        next;
    }
    print STDERR "$0: unknown option/argument [$arg]\n";
    exit 1;
}

my $stdin = '';
my $buffer;
while (read (STDIN, $buffer, 100000)) {
    $stdin .= $buffer;
}
print "Read ", length ($stdin), " bytes from STDIN\n" if $verbose;

while (length ($stdin)) {
    # get the HEAD status, work tree status, and the to path
    my ($X, $Y, $pathto) = unpack ('A1A1xZ*', $stdin);
    substr ($stdin, 0, 4 + length ($pathto), '');

    # handle cases that have a second path (renames, copies)
    my $pathfrom = '';
    if ($X eq 'R' || $X eq 'C') {
        $pathfrom = unpack ('Z*', $stdin);
        substr ($stdin, 0, 1 + length ($pathfrom), '');
    }

    # don't process untracked files
    next if $X eq '?';

    # don't process files deleted from work tree
    next if $Y eq 'D';

    # don't process files not in the index
    next if $X eq ' ' || !$X;

    if ($verbose) {
        print "X[",$X,"] Y[",$Y,"] pathto  [",$pathto,"]\n";
        print "         pathfrom[",$pathfrom,"]\n" if length ($pathfrom);
        next;
    }

    print $pathto, "\n";
}

