#!/usr/local/bin/perl -w
#
# Copyright (C) 2005, 2007, 2012, 2016 Internet Systems Consortium, Inc. ("ISC")
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
# $Id$
#
# Track which branches are still open or not in the bind9 cvs repository.
# This is done so that work that is "in progress" (active) doesn't get
# so easily forgotten about.
#
# This script updates doc/private/branches by adding new branches and moving
# closed branches to the end of the file. New branches are found by walking
# the cvs repository and extracting the new branches from the header fields
# of the files there.
#
# doc/private/branches has one line per branch in the following field order:
# name, status, to whom the branch belongs and comments. Comments are
# in '(',')'. The first three field are single words.
#
# Note: this is intended to be run on the machine hosting the CVS repository.
#
%branches = ();
%whom = ();
%comments = ();
%history = ();
%dates = ();
$repository = "/proj/cvs/prod";
$module = "bind9";
#
# Make sure we have a up to date copy. If the previous ran failed for
# any reason remove it (-C).
#
!system("cvs", "-d", $repository, "update", "-C", "doc/private/branches") || die "cannot update doc/private/branches: $!";
#
# load existing content
#
open(BRANCHES, "<doc/private/branches") || die "can't open util/branches: $!";
while (<BRANCHES>) {
my $branch;
my $status;
my $who;
chomp;
next if (/^-/);
next if (/^Branch/);
next if (/^\s/);
$c = "";
if (m://.*:) {
$c = $_;
$c =~ s:.*?//\s*(.*)$:$1:;
s:(.*?)//.*:$1:;
} else {
#
# look for old style comment
#
if (m/\(.*\)/) {
$c = $_;
$c =~ s/.*\((.*)\).*$/$1/;
s/\(.*\)//;
}
}
s/\s*$//;
next if (/^\s*$/);
($branch, $status, $who) = split;
$status = "new" if (!defined($status));
$branches{$branch} = $status;
$who = "" if (!defined($who));
$whom{$branch} = $who;
$comments{$branch} = $c;
}
close (BRANCHES);
# T 1999-03-15 21:15 +0000 vixie bind [ietf44:A]
open(HISTORY, "cvs history -T -a 2> /dev/null |") || die("can't get history");
while (<HISTORY>) {
my $tag;
my $date;
my $time;
my $tz;
my $who;
my $mod;
my $branch;
chomp;
s/[][]//g;
s/:[^ \t]+$//;
s/\s+/ /g;
($tag, $date, $time, $tz, $who, $mod, $branch) = split;
next if ($mod ne $module );
next if ($tag ne "T" );
next if (exists($history{$branch}));
$history{$branch} = $who;
$dates{$branch} = "$date $time $tz";
# print "$_\n";
}
close (HISTORY);
#
# Search repository for new branches.
#
# New branches have the following format "name:<revision>.0.#"
# where # is the number of potential branches from this the revision.
#
open(FILES, "find $repository/$module -type f -name *,v -print |") || die "can't start find: $!";
while (<FILES>) {
chomp;
# print "file: $_\n"; # debug
# $file = $_; # save for branch debug below.
s:^$repository/::;
s:/Attic/([^/]*)$:/$1:;
s:,v$::;
#
# use cvs so that the file is locked.
#
#print "cvs -d $repository rlog -h $_\n";
open(FILE, "cvs -d $repository rlog -h $_|") || die "can't start cvs rlog -h $_: $!";
while (<FILE>) {
chomp;
next unless m/^symbolic names:$/; # skip until we find the tags
while (<FILE>) {
chomp;
last if (m/^locks;/); # we are past the tags
last if (m/^keyword/); # we are past the tags
next unless m/\.0\.\d+$/; # skip if not a branch
s/\s(.*):.*/$1/; # extract label
if (!$branches{$_}) {
$branches{$_} = "new";
if (exists($history{$_})) {
$whom{$_} = $history{$_};
$comments{$_} = $dates{$_};
} else {
$whom{$_} = "";
$comments{$_} = "";
}
# print "branch: $_ $file\n"; # debug
}
}
chomp while (<FILE>); # let cvs rlog exit normally.
}
close(FILE);
}
close(FILES);
#
# Write out updated version.
#
open(BRANCHES, ">doc/private/newbranches") || die "can't open doc/private/branches: $!";
print BRANCHES "\nBranch\t\t\t\tStatus\tWhom\t// Comments\n";
print BRANCHES "-----------------------------------------------------------\n\n";
print BRANCHES "\t\t\t\tnew\t\tnot yet classified\n";
print BRANCHES "\t\t\t\topen\t\tdevelopement branch\n";
print BRANCHES "\t\t\t\tactive\t\tnot a development branch\n";
print BRANCHES "\t\t\t\treview\t\tready for review\n";
print BRANCHES "\t\t\t\tprivate\t\tprivate branch\n";
print BRANCHES "\t\t\t\tclosed\t\tfinished with\n";
print BRANCHES "\n";
foreach $key (sort keys %branches) {
next if ($branches{$key} eq "closed");
print BRANCHES "$key";
$len = length($key);
if ($len >= 32) {
$tabs = 1;
} else {
$needed = int (32 - $len);
$tabs = int ($needed / 8);
if ($needed % 8 != 0) {
$tabs++;
}
}
for ($i = 0; $i < $tabs; $i++) {
printf BRANCHES "\t";
}
print BRANCHES "$branches{$key}\t";
print BRANCHES "$whom{$key}";
print BRANCHES "\t// $comments{$key}" if ($comments{$key} ne "");
print BRANCHES "\n";
}
print BRANCHES "\n\n";
foreach $key (sort keys %branches) {
next if ($branches{$key} ne "closed");
print BRANCHES "$key";
$len = length($key);
if ($len >= 32) {
$tabs = 1;
} else {
$needed = int (32 - $len);
$tabs = int ($needed / 8);
if ($needed % 8 != 0) {
$tabs++;
}
}
for ($i = 0; $i < $tabs; $i++) {
printf BRANCHES "\t";
}
print BRANCHES "$branches{$key}";
print BRANCHES "\t\t// $comments{$key}" if ($comments{$key} ne "");
print BRANCHES "\n";
}
close(BRANCHES);
#
# Update if changed.
#
if (system("cmp", "-s", "doc/private/newbranches", "doc/private/branches")) {
rename("doc/private/newbranches", "doc/private/branches") || die "Cannot rename: doc/private/newbranches -> doc/private/branches: $!";
!system("cvs", "-d", $repository, "commit", "-m", "auto update", "doc/private/branches") || die "cvs commit failed: $!";
} else {
unlink("doc/private/newbranches");
}