@ISA = qw(Exporter);
@EXPORT = qw(debug
run_git run_git_1line run_git_check_nooutput
- run_git_test_anyoutput
+ run_git_test_anyoutput git_get_object
git_config git_dir chdir_toplevel
- current_branch parse_patch_spec
+ current_branch parse_patch_spec parse_patch_name
setup_config check_no_unwanted_metadata
+ patch_matches_spec
foreach_patch
flagsfile_add_flag
- wf_start wf wf_abort wf_done wf_contents);
+ wf_start wf wf_abort wf_done wf_contents
+ closeout);
%EXPORT_TAGS = ( );
@EXPORT_OK = qw();
}
$git_command, qw(cat-file --batch))
or die $!;
}
+ #debug("git_get_object $objname");
$SIG{'PIPE'} = 'IGN';
print $gro_in $objname,"\n" or die $!;
$gro_in->flush or die "$objname $!";
$SIG{'PIPE'} = 'DFL';
my $l = <$gro_out>;
chomp $l or die "$objname $l ?";
+ #debug("git_get_object $objname => $l");
if ($l =~ m/ missing$/) {
return 'missing';
} elsif (my ($type,$bytes) = $l =~ m/^\S+ (\w+) (\d+)$/) {
- my $data;
- read $gro_out, $data, $bytes == $bytes or die "$objname $!";
+ my $data = '';
+ if ($bytes) {
+ (read $gro_out, $data, $bytes) == $bytes or die "$objname $!";
+ }
+ my $nl;
+ (read $gro_out, $nl, 1) == 1 or die "$objname $!";
+ $nl eq "\n" or die "$objname ?";
return ($type, $data);
} else {
die "$objname $l";
};
}
if ($ref =~ m#^refs/topbloke-(tip|base)s/([^/\@]*)\@([^/\@]*)/([^/]*)/#) {
+ my $fullname = "$2\@$3/$4/$'";
return {
Kind => $1,
Email => $2,
Date => $4,
Nick => $', #',
Ref => $ref,
- DepSpec => "$2\@$3/$4/$'",
+ DepSpec => $fullname,
+ Fullname => $fullname,
};
} elsif ($ref =~ m#^refs/heads/#) {
return {
Domain => $domain,
Date => $date,
Nick => $nick,
+ Kind => 'tip',
+ DepSpec => $patch,
+ Fullname => $patch,
+ Ref => "refs/topbloke-tips/$patch",
};
}
wf_done($wf);
}
+sub closeout () {
+ STDOUT->error and die $!;
+ close STDOUT or die $!;
+}
+
1;
$toposort=1 if $sort eq $toposort;
}
+$relatedto = $relatedto ? parse_patch_spec($relatedto) : undef;
+
our %patches;
foreach_patch($relatedto || $leaves || !$spec ? { } : $spec,
next unless exists $patches{$dep};
$patches{$dep}{Related} = 1;
}
+ # oh, and mark ourselves as Related=1 too!
+ $v->{Related} = 1;
}
}
}
next if $deleted_only && !$v->{Info}[0]{Deleted};
next if $leaves && $v->{NotLeaf};
next if $relatedto && !$v->{Related};
+ next if $spec && !patch_matches_spec($v->{ParsedName}, $spec);
push @output, $p;
}
use Data::Dumper;
+my $current_branch = current_branch();
+my $current_patch = $current_branch->{Kind} eq 'tip'
+ ? $current_branch->{Fullname} : '';
+
foreach my $p (@output) {
my $v = $patches{$p};
- print Dumper($p, $v);
+ my $pa = $v->{ParsedName};
+ my ($msgkind, $msg) = git_get_object("$pa->{Ref}:.topbloke/msg");
+ die "$p $msgkind ?" unless $msgkind eq 'blob';
+ my $subject =
+ $msg =~ m/^Subject:\s*(?:\[[^][]*\]\s*)?(.*\S)\s*$/mi
+ ? $1 : "[no subject]";
+ printf("%1s%1s %s\@%s/%s/%-20s %s\n",
+ $p eq $current_patch ? '>' : '',
+ $v->{Info}[0]{Deleted} ? 'D' : '',
+ $pa->{Email}, $pa->{Domain}, $pa->{Date}, $pa->{Nick},
+ $subject)
+ or die $!;
}
+
+closeout();