From: Junio C Hamano Date: Mon, 12 Apr 2010 21:29:50 +0000 (-0700) Subject: Meta/cook: What's cooking script (third generation) X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2f557677f429c2bff9c7b57a5e6a37d00534b520;p=thirdparty%2Fgit.git Meta/cook: What's cooking script (third generation) --- diff --git a/cook b/cook new file mode 100755 index 0000000000..b3af892840 --- /dev/null +++ b/cook @@ -0,0 +1,548 @@ +#!/usr/bin/perl -w +# Maintain "what's cooking" messages + +use strict; + +sub phrase_these { + my (@u) = @_; + my @d = (); + for (my $i = 0; $i < @u; $i++) { + push @d, $u[$i]; + if ($i == @u - 2) { + push @d, " and "; + } elsif ($i < @u - 2) { + push @d, ", "; + } + } + return join('', @d); +} + +sub describe_relation { + my ($topic_info) = @_; + my @desc; + + if (exists $topic_info->{'used'}) { + push @desc, ("is used by " . + phrase_these(@{$topic_info->{'used'}})); + } + + if (exists $topic_info->{'uses'}) { + push @desc, ("uses " . + phrase_these(@{$topic_info->{'uses'}})); + } + + if (exists $topic_info->{'shares'}) { + push @desc, ("shares commits with " . + phrase_these(@{$topic_info->{'shares'}})); + } + + if (!@desc) { + return ""; + } + + return "(this branch " . join("; ", @desc) . ".)"; +} + +sub forks_from { + my ($topic, $fork, $forkee, @overlap) = @_; + my %ovl = map { $_ => 1 } (@overlap, @{$topic->{$forkee}{'log'}}); + + push @{$topic->{$fork}{'uses'}}, $forkee; + push @{$topic->{$forkee}{'used'}}, $fork; + @{$topic->{$fork}{'log'}} = (grep { !exists $ovl{$_} } + @{$topic->{$fork}{'log'}}); +} + +sub topic_relation { + my ($topic, $one, $two) = @_; + + my $fh; + open($fh, '-|', + qw(git log --abbrev=7), "--format=%m %h", + "$one...$two", "^master") + or die "$!: open log --left-right"; + my (@left, @right); + while (<$fh>) { + my ($sign, $sha1) = /^(.) (.*)/; + if ($sign eq '<') { + push @left, $sha1; + } elsif ($sign eq '>') { + push @right, $sha1; + } + } + close($fh) or die "$!: close log --left-right"; + + if (!@left) { + if (@right) { + forks_from($topic, $two, $one); + } + } elsif (!@right) { + forks_from($topic, $one, $two); + } else { + if (@left < @right) { + forks_from($topic, $two, $one, @left); + } elsif (@right < @left) { + forks_from($topic, $one, $two, @right); + } else { + push @{$topic->{$one}{'shares'}}, $two; + push @{$topic->{$two}{'shares'}}, $one; + } + } +} + +sub get_commit { + my (@base) = qw(master next pu); + my $fh; + open($fh, '-|', + qw(git for-each-ref), + "--format=%(refname:short) %(authordate:iso8601)", + "refs/heads/??/*") + or die "$!: open for-each-ref"; + my @topic; + my %topic; + + while (<$fh>) { + chomp; + my ($branch, $date) = /^(\S+) (.*)$/; + push @topic, $branch; + $date =~ s/ .*//; + $topic{$branch} = +{ + log => [], + tipdate => $date, + }; + } + close($fh) or die "$!: close for-each-ref"; + + my %base = map { $_ => undef } @base; + my %commit; + my $show_branch_batch = 20; + + while (@topic) { + my @t = (@base, splice(@topic, 0, $show_branch_batch)); + my $header_delim = '-' x scalar(@t); + my $contain_pat = '.' x scalar(@t); + open($fh, '-|', qw(git show-branch --sparse --sha1-name), + map { "refs/heads/$_" } @t) + or die "$!: open show-branch"; + while (<$fh>) { + chomp; + if ($header_delim) { + if (/^$header_delim$/) { + $header_delim = undef; + } + next; + } + my ($contain, $sha1, $log) = + ($_ =~ /^($contain_pat) \[([0-9a-f]+)\] (.*)$/); + + for (my $i = 0; $i < @t; $i++) { + my $branch = $t[$i]; + my $sign = substr($contain, $i, 1); + next if ($sign eq ' '); + next if (substr($contain, 0, 1) ne ' '); + + if (!exists $commit{$sha1}) { + $commit{$sha1} = +{ + branch => {}, + log => $log, + }; + } + my $co = $commit{$sha1}; + $co->{'branch'}{$branch} = 1; + next if (exists $base{$branch}); + push @{$topic{$branch}{'log'}}, $sha1; + } + } + close($fh) or die "$!: close show-branch"; + } + + my %shared; + for my $sha1 (keys %commit) { + my $sign; + my $co = $commit{$sha1}; + if (exists $co->{'branch'}{'next'}) { + $sign = '+'; + } elsif (exists $co->{'branch'}{'pu'}) { + $sign = '-'; + } else { + $sign = '.'; + } + $co->{'log'} = $sign . ' ' . $co->{'log'}; + my @t = (sort grep { !exists $base{$_} } + keys %{$co->{'branch'}}); + next if (@t < 2); + my $t = "@t"; + $shared{$t} = 1; + } + + for my $combo (keys %shared) { + my @combo = split(' ', $combo); + for (my $i = 0; $i < @combo - 1; $i++) { + for (my $j = $i + 1; $j < @combo; $j++) { + topic_relation(\%topic, $combo[$i], $combo[$j]); + } + } + } + + open($fh, '-|', + qw(git log --first-parent --abbrev=7), + "--format=%ci %h %p :%s", "master..next") + or die "$!: open log master..next"; + while (<$fh>) { + my ($date, $commit, $parent, $tips); + unless (($date, $commit, $parent, $tips) = + /^([-0-9]+) ..:..:.. .\d{4} (\S+) (\S+) ([^:]*):/) { + die "Oops: $_"; + } + for my $tip (split(' ', $tips)) { + my $co = $commit{$tip}; + $co->{'merged'} = " (merged to 'next' on $date at $commit)"; + } + } + close($fh) or die "$!: close log master..next"; + + for my $branch (keys %topic) { + my @log = (); + my $n = scalar(@{$topic{$branch}{'log'}}); + if (!$n) { + delete $topic{$branch}; + next; + } elsif ($n == 1) { + $n = "1 commit"; + } else { + $n = "$n commits"; + } + my $d = $topic{$branch}{'tipdate'}; + my $head = "* $branch ($d) $n\n"; + my @desc; + for (@{$topic{$branch}{'log'}}) { + my $co = $commit{$_}; + if (exists $co->{'merged'}) { + push @desc, $co->{'merged'}; + } + push @desc, $commit{$_}->{'log'}; + } + my $list = join("\n", map { " " . $_ } @desc); + my $relation = describe_relation($topic{$branch}); + $topic{$branch}{'desc'} = $head . $list; + if ($relation) { + $topic{$branch}{'desc'} .= "\n $relation"; + } + } + + return \%topic; +} + +sub blurb_text { + my ($mon, $year, $issue, $dow, $date, + $master_at, $next_at, $text) = @_; + + my $now_string = localtime; + my ($current_dow, $current_mon, $current_date, $current_year) = + ($now_string =~ /^(\w+) (\w+) (\d+) [\d:]+ (\d+)$/); + + $mon ||= $current_mon; + $year ||= $current_year; + $issue ||= "01"; + $dow ||= $current_dow; + $date ||= $current_date; + $master_at ||= '0' x 40; + $next_at ||= '0' x 40; + $text ||= <<'EOF'; +Here are the topics that have been cooking. Commits prefixed with '-' are +only in 'pu' while commits prefixed with '+' are in 'next'. The ones +marked with '.' do not appear in any of the integration branches, but I am +still holding onto them. +EOF + + $text = < [], + 'section_data' => {}, + 'topic_description' => { + $blurb => { + desc => undef, + text => blurb_text(), + }, + }, + }; + } + + open ($fh, '<', $fn) or die "$!: open $fn"; + while (<$fh>) { + chomp; + if ($in_unedited_olde) { + if (/^>>$/) { + $in_unedited_olde = 0; + $_ = " | $_"; + } + } elsif (/^<<$/) { + $in_unedited_olde = 1; + } + + if ($in_unedited_olde) { + $_ = " | $_"; + } + + if (defined $section && /^-{20,}$/) { + $_ = ""; + } + if (/^$/) { + $last_empty = 1; + next; + } + if (/^\[(.*)\]\s*$/) { + $section = $1; + $branch = undef; + if (!exists $section{$section}) { + push @section, $section; + $section{$section} = []; + } + next; + } + if (defined $section && /^\* (\S+) /) { + $branch = $1; + $last_empty = 0; + if (!exists $branch{$branch}) { + push @branch, [$branch, $section]; + $branch{$branch} = 1; + } + push @{$section{$section}}, $branch; + } + if (defined $branch) { + my $was_last_empty = $last_empty; + $last_empty = 0; + if (!exists $description{$branch}) { + $description{$branch} = []; + } + if ($was_last_empty) { + push @{$description{$branch}}, ""; + } + push @{$description{$branch}}, $_; + } + } + close($fh); + + for my $branch (keys %description) { + my $ary = $description{$branch}; + if ($branch eq $blurb) { + while (@{$ary} && $ary->[-1] =~ /^-{30,}$/) { + pop @{$ary}; + } + $description{$branch} = +{ + desc => undef, + text => join("\n", @{$ary}), + }; + } else { + my @desc = (); + while (@{$ary}) { + my $elem = shift @{$ary}; + last if ($elem eq ''); + push @desc, $elem; + } + $description{$branch} = +{ + desc => join("\n", @desc), + text => join("\n", @{$ary}), + }; + } + } + + return +{ + section_list => \@section, + section_data => \%section, + topic_description => \%description, + }; +} + +sub write_cooking { + my ($fn, $cooking) = @_; + my $fh; + + open($fh, '>', $fn) or die "$!: open $fn"; + print $fh $cooking->{'topic_description'}{$blurb}{'text'}; + + for my $section_name (@{$cooking->{'section_list'}}) { + my $topic_list = $cooking->{'section_data'}{$section_name}; + next if (!@{$topic_list}); + + print $fh "\n"; + print $fh '-' x 50, "\n"; + print $fh "[$section_name]\n"; + for my $topic (@{$topic_list}) { + my $d = $cooking->{'topic_description'}{$topic}; + + print $fh "\n", $d->{'desc'}, "\n"; + if ($d->{'text'}) { + print $fh "\n", $d->{'text'}, "\n"; + } + } + } + close($fh); +} + +my $graduated = 'Graduated to "master"'; +my $new_topics = 'New Topics'; +my $old_new_topics = 'Old New Topics'; + +sub update_issue { + my ($cooking) = @_; + my ($fh, $master_at, $next_at, $incremental); + + open($fh, '-|', + qw(git for-each-ref), + "--format=%(refname:short) %(objectname)", + "refs/heads/master", + "refs/heads/next") or die "$!: open for-each-ref"; + while (<$fh>) { + my ($branch, $at) = /^(\S+) (\S+)$/; + if ($branch eq 'master') { $master_at = $at; } + if ($branch eq 'next') { $next_at = $at; } + } + close($fh) or die "$!: close for-each-ref"; + + $incremental = ((-r "Meta/whats-cooking.txt") && + system("cd Meta && " . + "git diff --quiet --no-ext-diff HEAD -- " . + "whats-cooking.txt")); + + my $now_string = localtime; + my ($current_dow, $current_mon, $current_date, $current_year) = + ($now_string =~ /^(\w+) (\w+) (\d+) [\d:]+ (\d+)$/); + + my $btext = $cooking->{'topic_description'}{$blurb}{'text'}; + if ($btext !~ s/\A$blurb_match//) { + die "match pattern broken?"; + } + my ($mon, $year, $issue, $dow, $date) = ($1, $2, $3, $4, $5); + + if ($current_mon ne $mon || $current_year ne $year) { + $issue = "01"; + } elsif (!$incremental) { + $issue =~ s/^0*//; + $issue = sprintf "%02d", ($issue + 1); + } + $mon = $current_mon; + $year = $current_year; + $dow = $current_dow; + $date = $current_date; + + $cooking->{'topic_description'}{$blurb}{'text'} = + blurb_text($mon, $year, $issue, $dow, $date, + $master_at, $next_at, $btext); + + if (!$incremental) { + my $sd = $cooking->{'section_data'}; + my $sl = $cooking->{'section_list'}; + for (my $i = 0; $i < @{$sl}; $i++) { + if ($sl->[$i] eq $new_topics) { + $sl->[$i] = $old_new_topics; + unshift @{$sl}, $new_topics; + last; + } + } + $sd->{$old_new_topics} = $sd->{$new_topics}; + $sd->{$new_topics} = []; + } +} + +sub merge_cooking { + my ($cooking, $current) = @_; + my $td = $cooking->{'topic_description'}; + my $sd = $cooking->{'section_data'}; + my $sl = $cooking->{'section_list'}; + my (@new_topic, @gone_topic); + + if (!exists $sd->{$new_topics}) { + $sd->{$new_topics} = []; + unshift @{$sl}, $new_topics; + } + + if (!exists $sd->{$graduated}) { + $sd->{$graduated} = []; + unshift @{$sl}, $graduated; + } + + update_issue($cooking); + + for my $topic (sort keys %{$current}) { + if (!exists $td->{$topic}) { + push @new_topic, $topic; + next; + } + my $n = $current->{$topic}{'desc'}; + my $o = $td->{$topic}{'desc'}; + if ($n ne $o) { + $td->{$topic}{'desc'} = $n . "\n<<\n" . $o ."\n>>"; + } + } + + for my $topic (sort keys %{$td}) { + next if ($topic eq $blurb); + if (!exists $current->{$topic}) { + push @gone_topic, $topic; + } + } + + for (@new_topic) { + push @{$sd->{$new_topics}}, $_; + $td->{$_}{'desc'} = $current->{$_}{'desc'}; + } + + if (@gone_topic) { + for my $topic (@gone_topic) { + for my $section (@{$sl}) { + @{$sd->{$section}} = (grep { $_ ne $topic } + @{$sd->{$section}}); + } + } + for (@gone_topic) { + push @{$sd->{$graduated}}, $_; + } + } + +} + +################################################################ +# Main + +my $topic = get_commit(); +my $cooking = read_previous('Meta/whats-cooking.txt'); +merge_cooking($cooking, $topic); +write_cooking('Meta/whats-cooking.txt', $cooking); diff --git a/cook.sh b/cook.sh deleted file mode 100755 index 3156c063de..0000000000 --- a/cook.sh +++ /dev/null @@ -1,449 +0,0 @@ -#!/bin/sh - -LANG=C LC_ALL=C GIT_PAGER=cat -export LANG LC_ALL GIT_PAGER - -tmpdir=/var/tmp/cook.$$ -mkdir "$tmpdir" || exit -tmp="$tmpdir/t" -trap 'rm -fr "$tmpdir"' 0 - -git branch --merged "master" | sed -n -e 's/^..//' -e '/\//p' >"$tmp.in.master" -git branch --merged "pu" | sed -n -e 's/^..//' -e '/\//p' >"$tmp.in.pu" -{ - comm -13 "$tmp.in.master" "$tmp.in.pu" - git branch --no-merged pu | - sed -n -e 's/^..//' -e '/\//p' -} >"$tmp.branches" - -git log --first-parent --format="%H %ci" master..next | -sed -e 's/ [0-2][0-9]:[0-6][0-9]:[0-6][0-9] [-+][0-2][0-9][0-6][0-9]$//' >"$tmp.next" -git rev-list master..pu >"$tmp.commits.in.pu" - -format_branch () { - # branch=$1 others=$2 - git rev-list --no-merges --topo-order "master..$1" --not $2 >"$tmp.list" - count=$(wc -l <"$tmp.list" | tr -d ' ') - label="* $1 ($(git show -s --format="%ai" $1 | sed -e 's/ .*//')) $count commit" - test "$count" = 1 || label="${label}s" - - echo "$label" - lasttimelabel= - lastfoundmerge= - while read commit - do - merged= merged_with= - while read merge at - do - if test -n "$lastfoundmerge" - then - if test "$lastfoundmerge" = "$merge" - then - lastfoundmerge= - else - continue - fi - fi - mb=$(git merge-base $merge $commit) - if test "$mb" = "$commit" - then - merged=$at merged_with=$merge - else - break - fi - done <"$tmp.next" - - lastfoundmerge=$merged_with - thistimelabel= - if test -n "$merged" - then - thistimelabel=$merged - commitlabel="+" - elif grep "$commit" "$tmp.commits.in.pu" >/dev/null - then - commitlabel="-" - else - commitlabel="." - fi - if test "$lasttimelabel" != "$thistimelabel" - then - with=$(git rev-parse --short $merged_with) - echo " (merged to 'next' on $thistimelabel at $with)" - lasttimelabel=$thistimelabel - fi - git show -s --format=" $commitlabel %s" $commit - done <"$tmp.list" -} - -add_desc () { - kind=$1 - shift - test -z "$description" || description="$description;" - others= - while : - do - other=$1 - case "$other" in - "#EPO-"*) other="early parts of ${other#"#EPO-"}" - esac - shift - case "$#,$others" in - 0,) - others="$other" - break ;; - 0,?*) - others="$others and $other" - break ;; - *,) - others="$other" - ;; - *,?*) - others="$others, $other" - ;; - esac - done - description="$description $kind $others" -} - -show_topic () { - old=$1 new=$2 - - sed -n -e '/^ ..*/p' -e '/^\* /p' "$old" >"$tmp.old.nc" - sed -n -e '/^ ..*/p' -e '/^\* /p' "$new" >"$tmp.new.nc" - if cmp "$tmp.old.nc" "$tmp.new.nc" >/dev/null - then - cat "$old" - else - cat "$new" - echo "<<" - cat "$old" - echo ">>" - fi -} - -compare_topic () { - b=$1 r=$2 - based=$(git rev-list --no-merges $b..$r | wc -l | tr -d ' ') - bases=$(git rev-list --no-merges $r..$b | wc -l | tr -d ' ') - case "$based,$bases" in - 0,0) echo same; exit ;; - 0,*) echo left; exit ;; - *,0) echo right; exit ;; - esac - - if test $based -lt $bases - then - echo left-p - else - echo fork - fi -} - -# List commits that are shared between more than one topic branches -while read b -do - git rev-list --no-merges "master..$b" -done <"$tmp.branches" | sort | uniq -d >"$tmp.shared" - -# Set of branches related to each other due to sharing the same commit -while read shared -do - b=$(git branch --contains "$shared" | sed -n -e 's/^..//' -e '/\//p') - echo "" $b "" -done <"$tmp.shared" | sort -u >"$tmp.related" - -serial=1 -while read b -do - related=$(grep " $b " "$tmp.related" | tr ' ' '\012' | sort -u | sed -e '/^$/d') - - based_on= based_on_msg= - used_by= - forks= - same_as= - if test -n "$related" - then - for r in $related - do - test "$b" = "$r" && continue - case "$(compare_topic "$b" "$r")" in - same) - same_as="$same_as$r " - ;; - left) - based_on="$based_on$r " - based_on_msg="$based_on_msg$r " - ;; - left-p) - based_on="$based_on$r " - based_on_msg="${based_on_msg}#EPO-$r " - ;; - right) - used_by="$used_by$r " - ;; - fork) - forks="$forks$r " - ;; - esac - done - fi - - { - format_branch "$b" "$based_on" - - description= - test -z "$same_as" || add_desc 'is same as' $same_as - test -z "$based_on" || add_desc 'uses' $based_on_msg - test -z "$used_by" || add_desc 'is used by' $used_by - test -z "$forks" || add_desc 'shares commits with' $forks - - test -z "$description" || - echo " (this branch$description.)" - } >"$tmp.output.$serial" - echo "$b $serial" - serial=$(( $serial + 1 )) -done <"$tmp.branches" >"$tmp.output.toc" - -eval $(date +"monthname=%b month=%m year=%Y date=%d dow=%a") - -incremental=$( - cd Meta && - if git diff --quiet --no-ext-diff HEAD -- whats-cooking.txt >/dev/null - then - echo no - else - echo yes - fi -) - -# Find the current issue -eval $(sed -ne '/^Subject: /{ - s/^Subject: What.s cooking in git.git (\([A-Z][a-z][a-z]\) \([0-9][0-9][0-9][0-9]\), #\([0-9][0-9]*\); [A-Z][a-z][a-z], [0-9][0-9])$/lastmon=\1 lastyear=\2 lastissue=\3/p - q -}' Meta/whats-cooking.txt) -if test "$monthname $year" = "$lastmon $lastyear" -then - while case "$lastissue" in 0?*) ;; *) break ;; esac - do - lastissue=${lastissue#0} - done - if test "$incremental" = no - then - issue=$(( $lastissue + 1 )) - else - issue=$(( $lastissue + 0 )) - fi -else - issue=1 -fi - -issue=$( printf "%02d" $issue ) -last=whats-cooking.txt - -master_at=$(git rev-parse --verify refs/heads/master) -next_at=$(git rev-parse --verify refs/heads/next) -cat >"$tmp.output.blurb" <) { - if ($in_unedited_olde) { - if (/^>>$/) { - $in_unedited_olde = 0; - $_ = " | $_"; - } - } elsif (/^<<$/) { - $in_unedited_olde = 1; - } - - if ($in_unedited_olde) { - $_ = " | $_"; - } - - if (defined $section && /^-{20,}$/) { - $_ = "\n"; - } - if (/^$/) { - $last_empty = 1; - next; - } - if (/^\[(.*)\]\s*$/) { - $section = $1; - $branch = undef; - if ($section eq "New Topics" && !$incremental) { - $section = "Old New Topics"; - } - if (!exists $section{$section}) { - push @section, $section; - $section{$section} = []; - } - next; - } - if (defined $section && /^\* (\S+) /) { - $branch = $1; - $last_empty = 0; - if (!exists $branch{$branch}) { - push @branch, [$branch, $section]; - $branch{$branch} = 1; - } - push @{$section{$section}}, $branch; - } - if (defined $branch) { - my $was_last_empty = $last_empty; - $last_empty = 0; - if (!exists $description{$branch}) { - $description{$branch} = []; - } - if ($was_last_empty) { - push @{$description{$branch}}, "\n"; - } - push @{$description{$branch}}, $_; - } - } - - if (open I, "<$tmp.output.toc") { - $section = "New Topics"; - while () { - my ($branch, $oldserial) = /^(\S*) (\d+)$/; - next if (exists $branch{$branch}); - if (!exists $section{$section}) { - # Have it at the beginning - unshift @section, $section; - $section{$section} = []; - } - push @{$section{$section}}, $branch; - push @branch, [$branch, $section]; - $branch{$branch} = 1; - if (!exists $description{$branch}) { - $description{$branch} = []; - } - open II, "<$tmp.output.$oldserial"; - while () { - push @{$description{$branch}}, $_; - } - close II; - } - close I; - } - - while (0 <= @{$description{$blurb}}) { - my $last = pop @{$description{$blurb}}; - if ($last =~ /^$/ || $last =~ /^-{20,}$/) { - next; - } else { - push @{$description{$blurb}}, $last; - last; - } - } - - open O, ">$tmp.template.blurb"; - for (@{$description{$blurb}}) { - print O $_; - } - close O; - - open TOC, ">$tmp.template.toc"; - $serial = 1; - for my $section (@section) { - for my $branch (@{$section{$section}}) { - print TOC "$branch $serial $section\n"; - open O, ">$tmp.template.$serial"; - for (@{$description{$branch}}) { - print O $_; - } - close O; - $serial++; - } - } -' <"$template" "$tmp" "$incremental" - -tmpserial=$( - tail -n 1 "$tmp.template.toc" | - read branch serial section && - echo $serial -) - -# Assemble them all - -if test -z "$TO_STDOUT" -then - exec >"Meta/whats-cooking.txt" -fi - -if test -s "$tmp.template.blurb" -then - sed -e '/^---------------*$/q' <"$tmp.output.blurb" - sed -e '1,/^---------------*$/d' <"$tmp.template.blurb" -else - cat "$tmp.output.blurb" -fi - -current=' --------------------------------------------------- -[Graduated to "master"] -' -while read branch oldserial section -do - test "$section" = 'Graduated to "master"' && - test "$incremental" = no && continue - - tip=$(git rev-parse --quiet --verify "refs/heads/$branch") || continue - mb=$(git merge-base master $tip) - test "$mb" = "$tip" || continue - if test -n "$current" - then - echo "$current" - current= - else - echo - fi - cat "$tmp.template.$oldserial" -done <"$tmp.template.toc" - -current= -while read branch oldserial section -do - found=$(grep "^$branch " "$tmp.output.toc") || continue - newserial=$(expr "$found" : '[^ ]* \(.*\)') - if test "$current" != "$section" - then - current=$section - echo " --------------------------------------------------- -[$section] -" - else - echo - fi - - show_topic "$tmp.template.$oldserial" "$tmp.output.$newserial" -done <"$tmp.template.toc"