Brain Phrye

code cooking diy fiction personal photos politics reviews tools 


Initial pass at git-ls

[ Listen to article ]

In Google there was (and possibly still is) a tool called “sourcerer” that let you browse through a repo. One nice feature it had was that deleted files and directories were shown struch through in red - and you could even follow down deleted dirs.

I’ve long wanted that view of a git repo. And today while digging through a rather old, imported work project it turned out that was useful to have. So I wrote a first pass at it. I also wrote a git-recover but that’s a bit more of a mess so maybe later.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#!/usr/bin/env perl

use Git;
use List::Util qw[min max];
use Term::ReadKey;

sub uniq {
  my %seen;
  return grep { !$seen{$_}++ } @_;
}

my $r = Git->repository() || die("Not in a git workdir.\n");
my $pwd = $r->wc_subdir();

my @deleted = uniq(sort(grep {/^[^\/]/} map {s|^$pwd||;s|/.*||;$_}
  grep {/^$pwd/} ($r->command("log", "--all", "--pretty=format:",
                              "--name-only", "--diff-filter=D"))));

opendir my $dir, "." || die("Failed to open '.'.\n");
my @files = readdir $dir;
closedir $dir;

my($wchar, $hchar, $wpixels, $hpixels) = GetTerminalSize();
my $maxlen = 0;
my %files;
foreach my $f (@deleted) {
  $maxlen = max($maxlen, length($f)+3);
  $files{$f} = "-$f-";
}
foreach my $f (@files) {
  $maxlen = max($maxlen, length($f)+1);
  $files{$f} = "$f" unless $f eq "." || $f eq "..";
}

my $curchars = $maxlen;
foreach $f (sort(keys(%files))) {
  printf("%-${maxlen}s", $files{$f});
  $curchars += $maxlen;
  if ($curchars > $wchar) {
    $curchars = $maxlen;
    printf("\n");
  }
}
printf("\n") unless $curchars == $maxlen;

Be nice if it could accept args, work outside of the current dir, took some common ls flags and a number of other bits. Also, using git log instead of a plumbing command it likely a no-no.