+
+#----- subroutines for setup
+
+sub create_and_switch ($$) {
+ my ($branchref, $what) = @_;
+ enable_reflog($branchref);
+ run_git(qw(update-ref -m), "tb-create $newpatch $what", $branchref, 'HEAD');
+ run_git(qw(symbolic-ref HEAD), $branchref);
+}
+
+sub stage_meta ($) {
+ my ($file) = @_;
+ run_git(qw(add), ".topbloke/$file");
+}
+
+sub meta_and_stage ($$) {
+ my ($file, $contents) = @_;
+ wf_contents(".topbloke/$file", $contents);
+ stage_meta($file);
+}
+
+sub meta_rm_stage ($) {
+ my ($file) = @_;
+ run_git(qw(rm --ignore-unmatch -q --), ".topbloke/$file");
+}
+
+#----- create the base branch
+
+if (lstat '.topbloke') {
+ -d _ or die;
+} else {
+ mkdir('.topbloke') or die "create .topbloke: $!\n";
+}
+
+my @meta_to_rm;
+
+if ($current->{Kind} eq 'foreign') {
+ check_no_metadata('HEAD');
+} else {
+ foreach_unknown_metadata('HEAD',
+ sub { push @meta_to_rm, $_ unless m/^\+/; });
+}
+
+my $baseref = "$baserefs/$newpatch";
+my $currentcommit = run_git_1line(qw(rev-parse), "HEAD");
+create_and_switch($baseref, 'base');
+
+meta_rm_stage('msg');
+meta_and_stage('patch', "$newpatch\n");
+meta_rm_stage('base');
+meta_and_stage('deps', "$current->{DepSpec}\n");
+meta_rm_stage('deleted');
+meta_rm_stage($_) foreach @meta_to_rm;
+
+if ($current->{Kind} eq 'foreign') {
+ meta_and_stage('+included', "");
+ meta_and_stage('+ends', "");
+} else {
+ # we inherit correct contents for +included
+ if ($current->{Kind} eq 'tip') {
+ metafile_process('+ends', undef, sub {
+ die if m/^\Q$current->{Fullname}\E /;
+ }, sub {
+ wf($_->[0], "$current->{Fullname} $currentcommit\n");
+ }, undef);
+ stage_meta('+ends');
+ }
+}
+
+run_git(qw(commit -q -m), "tb-create $newpatch base");
+my $basecommit = run_git_1line(qw(rev-parse), "$baseref~0");
+
+#----- create the tip branch
+
+my $tipref = "$tiprefs/$newpatch";
+create_and_switch($tipref, 'tip');
+
+my $nm = wf_start('.topbloke/msg');
+wf($nm, "From: $author\n");
+foreach my $h (qw(To CC BCC)) {
+ my $estatus;
+ run_git(\$estatus, sub { wf($nm, "$h: $_") or die $!; },
+ qw(config), "topbloke.".lc $h);
+ die "$h $estatus" unless $estatus==0 || $estatus==256;
+}
+wf($nm, <<END) or die $!;
+Subject: [${subjprefix}PATCH] $spec->{Nick}
+
+<patch description>
+
+Signed-off-by: $author
+END
+wf_done($nm);
+stage_meta('msg');
+
+meta_and_stage('base', "$basecommit\n");
+meta_rm_stage('deps');
+depsfile_add_dep('+included',$newpatch);
+stage_meta('+included');
+
+run_git(qw(commit -q -m), "tb-create $newpatch tip");