10 our ($VERSION, @ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS);
14 @EXPORT = qw(parse_branch_spec current_tb_branch run_git_1line);
22 $xopts = ref $_[0] ? shift @_ : { };
23 open GIT, "-|", 'git', @_ or die $!;
26 if ($xopts->{ExitStatus}) {
30 chomp $l or die "@_ ?";
34 close GIT or die "git @_ failed ($?)\n";
35 chomp $l or die "@_ ?";
41 if (!defined $git_dir) {
42 $git_dir = run_git_1line(qw(rev-parse --git-dir));
47 sub current_tb_branch () {
48 open R, git_dir().'/HEAD' or die "open HEAD $!";
49 my $ref = <R>; defined $ref or die $!;
52 if ($ref !~ s#^ref: ##) {
58 if ($ref =~ m#^refs/topbloke-(tip|base)s/([^/\@]*)\@([^/\@]*)/([^/]*)/#) {
66 DepSpec => "$2\@$3/$4/$'",
68 } elsif ($ref =~ m#^refs/heads/#) {
82 sub parse_branch_spec ($) {
85 my $spec = { }; # Email Domain DatePrefix DateNear Nick
87 my ($key,$val,$whats) = @_;
88 die "multiple $whats in branch spec\n" if exists $spec->{$key};
93 if (s#([^/\@]*)\@([^/\@]*)/##) {
94 $set->('Email', $1, "email local parts") if length $1;
95 $set->('Domain', $2, "email domains") if length $1;
96 } elsif (s#([^/]*\~[^/]*)/##) {
99 open DATE, "-|", 'date','+%s','-d',$dspec or die $!;
101 close DATE or die "date parsing failed\n";
103 $set->('DateNear', $l, 'nearby dates');
104 } elsif (s#^([0-9][^/]*)/##) {
107 m/^\d{4}(?:-\d\d(?:-\d\d(?:T(?:\d\d(?:\d\d(?:\d\d(?:Z)?)?)?)?)?)?)?$/
108 or die "bad date prefix \`$dspec'\n";
109 $set->('DatePrefix', $dspec, 'date prefixes');
112 } elsif (s#^\.\./##) {
119 if (defined $rel_levels) {
120 my $branch = current_tb_branch();
121 if (!defined $branch->{Nick}) {
122 die "relative branch spec \`$orig',".
123 " but current branch not a topbloke branch\n";
125 my ($ceaddr,$cdate,@l) = split /\//, $branch->{Nick};
127 die "relative branch spec \`$orig' has too many ../s\n";
128 $_ = (join '/', @l[0..$#l-$rel_levels]).'/'.$_;