windows-nt/Source/XPSP1/NT/tools/changestofiles.pl
2020-09-26 16:20:57 +08:00

248 lines
5.9 KiB
Perl

# FileName: ChangesToFiles.pl
#
#
# Usage = ChangesToFiles.pl [project] changesfile > filesfile
#
# Function: Takes build.changes and runs sd describe on each change to get the file list.
# Specifiying a project limits the output to just that project
#
# WARNING:
# WARNING: make sure pathname comparisons are case insensitive. Either convert the case or do the
# WARNING: comparisons like this:
# WARNING: if ($foo =~ /^\Q$bar\E$/i) {}
# WARNING: or if ($foo !~ /^\Q$bar\E$/i) {}
# WARNING:
$PGM='ChangesToFiles: ';
$Usage = "ChangesToFiles.pl [options] changesfile\n"
. "options:\n"
. " [-verbose]\n"
. " [-descriptions]\n"
. " [-integrates]\n"
. " [-branches]\n"
. " [-deletes]\n"
. " [-publics]\n"
. " [-all]\n"
. " [-project depotname]\n"
;
$DefaultChangesFile = "build.Changes";
#
# Debug routines for printing out variables
#
sub gvar {
for (@_) {
print "\$$_ = $$_\n";
}
}
#
# get current directory
#
sub thisdir () {
open CWD, 'cd 2>&1|';
my $here = <CWD>;
close CWD;
return $here;
}
#
# grap sdxroot from the environment
#
$sdxroot = $ENV{'SDXROOT'} or die $PGM, "SDXROOT not set in environment\n";
$sdxpath = $sdxroot;
$sdxpath =~ s/^[A-Z]://i;
#
# Process arguments
#
while ($_ = shift) {
$nextarg = $ARGV[0];
$nextarg =~ tr/A-Z/a-z/;
if (/^-verbose$/i) { $Verbose++; next; }
if (/^-v/i) { $Verbose++; next; }
if (/^-all$/i) { $DoAll++; next; }
if (/^-a$/i) { $DoAll++; next; }
if (/^-debug$/i) { $Debug++; next; }
if (/^-d$/i) { $Debug++; next; }
if (/^-descriptions$/i) { $DoDescriptions++; next; }
if (/^-integrates$/i) { $DoIntegrates++; next; }
if (/^-branches$/i) { $DoBranches++; next; }
if (/^-deletes$/i) { $DoDeletes++; next; }
if (/^-publics$/i) { $DoPublics++; next; }
if (/^-nofiles$/i) { $NoFiles++; next; }
if (/^-project$/i) { $OnlyProjects++; $ProjectList{$nextarg}++; shift; next; }
if (/^-p$/i) { $OnlyProjects++; $ProjectList{$nextarg}++; shift; next; }
if (/^-?$/i) { die $Usage; }
if (/^-help$/i) { die $Usage; }
if (/^-/) { die $Usage; }
if (not $ChangesFile) {
$ChangesFile = $_;
next;
}
die $Usage;
}
if ($DoAll) {
$DoIntegrates++;
$DoBranches++;
$DoDeletes++;
$DoPublics++;
$DoDescriptions++;
}
$ChangesFile = "$sdxroot\\$DefaultChangesFile" unless $ChangesFile;
# gvar Verbose, DoAll, Debug, DoDescriptions, DoIntegrates, DoBranches, DoDeletes, DoPublics, OnlyProjects, ChangesFile;
#
# setup SD.MAP mapping from projects to directories
#
$sdxmapfile = "$sdxroot\\sd.map";
open SDMAPFILE, $sdxmapfile or die $PGM, "Could not open $sdxmapfile <$!>\n";
while (<SDMAPFILE>) {
last if /^#\s*project\s*root\s*$/i;
}
die $PGM, "Malformed sd.map file\n" if <SDMAPFILE> !~ /^#\s*-+\s+-+\s*$/;
while (<SDMAPFILE>) {
last if /^\s*$/;
next unless /^\s*(\S+)\s*=\s*(\S+)\s*$/;
$p = $1;
$r = $2;
$p =~ tr/A-Z/a-z/;
$r =~ tr/A-Z/a-z/;
$SDProjectDir{$p} = "$sdxpath\\$r";
}
close SDMAPFILE;
#
# Check the -projects arguments against SDMAP
#
if ($Project) {
for (keys %ProjectList) {
die $PGM, $_, " not found in sd.map\n";
}
}
#
# Open and process the changes file
#
open BUILDCHANGES, $ChangesFile or die $PGM, "Could not open: ", $ChangesFile, "\n";
$CurrentProject = "";
for (<BUILDCHANGES>) {
$CurrentProject = $1 if /^---+\s*(\w+)\s*$/;
$CurrentProject =~ tr/A-Z/a-z/;
next unless /^Change\s(\d+)\s+on\s+(\S+)\s+(\S+)\s+by\s+(\S+)\\(\S+)\@(\S+)\s*'/i;
$Change = $1;
$Timestamp = "$2 $3";
$Domain = "$4";
$Alias = "$5";
$Machine = "$6";
next if $Project and not $ProjectList{$CurrentProject};
$ProjectChanges{$CurrentProject} .= "$Change ";
}
$origdir = thisdir();
for (keys %ProjectChanges) {
$Depot = $_;
#
# Change to the project and run sd describe
#
chdir $SDProjectDir{$_} or die $PGM, "Could not chdir to $SDProjectDir{$_}: $!\n";
open SDOUT, "sd describe -s $ProjectChanges{$_} |" or die "Could not run sd describe: $!\n";
chdir $origdir;
TOP: while (<SDOUT>) {
next if /^\s*$/; # skip initial blank lines
if (not /^Change\s+(\d+)\s+by\s+(\S+)\\(\S+)\@(\S+)\s+on\s+(\S+)\s+(\S+)\s*$/i) {
warn $PGM, "Could not parse sd output: $_";
last;
}
$Change = $1;
$Domain = "$2";
$Alias = "$3";
$Machine = "$4";
$Timestamp = "$5 $6";
#
# Collect the description lines
#
$Description = "";
while (<SDOUT>) {
last if /^Affected files/i;
$Description .= $_;
}
#
# Output Change summary if doing descriptions
#
printf "Description of %-10s %6d by %s:%s", $Depot, $Change, $Alias, $Description if $DoDescriptions;
#
# Collect the files
#
while (<SDOUT>) {
redo TOP if /^Change\s/i;
next if /^\s*$/;
warn $PGM, "Can't parse: $_" unless /^\.\.\.\s/;
($dots, $Filename, $FileStatus) = split ' ';
#
# Finally, the output happens...
#
$dontprint = (not $DoIntegrates and $FileStatus =~ /integrat/i
or not $DoBranches and $FileStatus =~ /branch/i
or not $DoDeletes and $FileStatus =~ /delete/i
or not $DoPublics and $Filename =~ m+root/public/+i
or $NoFiles );
printf "%-10s %6d %-8s %19s %s %s\n", $Depot, $Change, $Alias, $Timestamp, $Filename, $FileStatus unless $dontprint;
}
}
close SDOUT;
}
exit 0;