nix

configuration files that power my machines
Log | Files | Refs | README | LICENSE

git-id (3948B)


      1 #!/usr/bin/perl
      2 # vim: sts=4 sw=4 ts=4 expandtab:
      3 =pod
      4 
      5 =head1 NAME
      6 
      7 git-id
      8 
      9 =head1 SYNOPSIS
     10 
     11     git-id
     12 
     13 =head1 DESCRIPTION
     14 
     15 Runs git-status and prepends numeric ids to filenames.
     16 
     17 =head1 OPTIONS
     18 
     19 =over 4
     20 
     21 =item -h
     22 
     23 Show this help message
     24 
     25 =item -s
     26 
     27 =item --column
     28 
     29 =item -u(no|normal|all)
     30 
     31 =item --color=(always|auto|never)
     32 
     33 These options are similar to git-status'.
     34 
     35 =back
     36 
     37 =head1 SEE ALSO
     38 
     39     git-number(1), git-list(1)
     40 
     41 =cut
     42 
     43 use strict;
     44 use warnings;
     45 use Cwd;
     46 
     47 my $red = "\e[31m";
     48 my $normal = "\e[0m";
     49 my $git_dir = `git rev-parse --git-dir`;
     50 chomp $git_dir;
     51 
     52 my $gitids = "$git_dir/gitids.txt";
     53 
     54 my $color = 'always';
     55 my $STATUS_DEFAULT = 0;
     56 my $STATUS_SHORT = 1;
     57 my $status_style = $STATUS_DEFAULT;
     58 my $status_opt = '';
     59 
     60 my $untracked_in_columns = 0;
     61 while (scalar @ARGV && $ARGV[0] =~ /^-/) {
     62     my $option = shift @ARGV;
     63     last if $option eq '--';
     64     if ($option =~ /--color=(always|auto|never)/) {
     65         $color = $1;
     66         if ($color =~ /never/) {
     67             $red = $normal = '';
     68         }
     69     } elsif ($option eq '--short') {
     70         $status_style = $STATUS_SHORT;
     71     } elsif ($option =~ m{^-u(no|normal|all)$}) {
     72         $status_opt .= " $option";
     73     } elsif ($option =~ /^--column/) {
     74         if ($option eq '--column=never' || ($option =~ /--column(=auto)?$/ && ! -t STDOUT)) {
     75             $untracked_in_columns = 0;
     76         } else {
     77             $untracked_in_columns = 1;
     78         }
     79         $status_opt .= " $option";
     80     } else {
     81         print "Unknown option: $option\n";
     82         exit 1;
     83     }
     84 }
     85 
     86 if (! $untracked_in_columns) {
     87     $status_opt .= " --column=never";
     88 }
     89 
     90 my @status_option_for = ( '', '--short' );
     91 my $status_format = $status_option_for[$status_style];
     92 my $git_cmd = "git -c color.status=$color status $status_opt $status_format "
     93               . join(' ', @ARGV);
     94 open my $git_status, "$git_cmd|"
     95     or die "Error: $!";
     96 
     97 open my $cache, ">$gitids"
     98     or die "Error: $!";
     99 
    100 # Headers
    101 print $cache "cwd: " . getcwd . "\n";
    102 print $cache "status-format: $status_format\n";
    103 print $cache "\n";
    104 
    105 my $seen_untracked = 0;
    106 my @untracked;
    107 my $c = 1;
    108 while (my $line = <$git_status>) {
    109     if ($line =~ /Untracked files:/) {
    110         $seen_untracked = 1;
    111     }
    112 
    113     if ($status_style == $STATUS_DEFAULT) {
    114         if ($seen_untracked && $line =~ /\t/ && $untracked_in_columns) {
    115             push @untracked, $line;
    116             last;
    117         }
    118 
    119         if ($line =~ /#\t/) {
    120             $line =~ s/#\t/#$c\t/;
    121             $c += 1;
    122         } elsif ($line =~ /\t/) {
    123             $line =~ s/\t/$c\t/;
    124             $c += 1;
    125         }
    126     } elsif ($status_style == $STATUS_SHORT) {
    127         if ($line !~ /^#/) {
    128             $line =~ s/^/$c /;
    129             $c += 1;
    130         }
    131     }
    132     show_and_cache($line);
    133 }
    134 
    135 if ($untracked_in_columns) {
    136     my $seen_files = 0;
    137     my @the_rest;
    138     while (my $line = <$git_status>) {
    139         if ($line =~ /\t/) {
    140             $seen_files = 1;
    141             push @untracked, $line;
    142         } else {
    143             push @the_rest, $line;
    144         }
    145     }
    146 
    147     my $rows = @untracked;
    148     foreach my $line (@untracked) {
    149         my $id = $c;
    150         $line =~ s/([\t ])(\S)/add_number(\$id, $1, $2, $rows)/ge;
    151         $line =~ s/^ +//;
    152         show_and_cache($line);
    153         $c += 1;
    154     }
    155     print join "", @the_rest;
    156 }
    157 
    158 close $git_status;
    159 close $cache;
    160 exit 0;
    161 
    162 sub show_and_cache {
    163     my ($line) = @_;
    164     my $tocache = $line;
    165     $tocache =~ s/{(\d+)}[\t ]{1,2}/\n$1\t/g;
    166     $line =~ s/{(\d+)}/$1/g;
    167     print $line;
    168     $tocache =~ s/\e\[(\d*(;\d*)*)m//g;
    169     if ($untracked_in_columns) {
    170         $tocache =~ s/\s*\n/\n/gms; # Trailing spaces from columnar formatting
    171     }
    172     print $cache $tocache;
    173 }
    174 
    175 sub add_number {
    176     my ($nref, $space, $first_char, $incr) = @_;
    177 
    178     my $num = $$nref;
    179     if ($num < 10 && $space eq ' ') {
    180         $num = "{$num} ";
    181     } else {
    182         $num = "{$num}";
    183     }
    184     my $str = "$normal$num$space$red$first_char";
    185     $$nref += $incr;
    186     return $str;
    187 }