Pairs.pl #6

  • //
  • guest/
  • jeff_bowles/
  • perforce-triggers/
  • triggers/
  • Pairs.pl
  • View
  • Commits
  • Open Download .zip Download (5 KB)
#
# Example trigger to enforce a rule "files of suffix .x/.y need to be checked
# in as pairs".
#
# This script will do the following:
#	1. Return "success" (exit code 0) if the change has no applicable files
#	   in the changelist;
#	2. Otherwise, it checks that the files you've given are
#	   being submitted with the other component in that pair, and
#	   if not, reports an error.
#
# Unix usage:
#	perl /whatever/Pairs.pl %changelist% %serverport%
# NT usage:
#       c:/perl/bin/perl  c:/whatever/Pairs.pl %changelist% %serverport%
# (Note that the name of this script might need to be an "8.3" filename,
# depending on the version of Perl you're running.)
#
#
# Example 'triggers' section:
# (Note: since this is applicable to only filenames with certain
# suffixes, you might want to restrict the trigger to run when those files
# are submitted.  So, if this is looking at .cpp/.h/.txt/.html lines, you
# might want to have it run only on those files.)

#    Triggers:
#	exampleP  //.../*.cpp    "perl whatever/Pairs.pl %changelist% %serverport%"
#	exampleP  //.../*.h      "perl whatever/Pairs.pl %changelist% %serverport%"
#	exampleP  //.../*.html   "perl whatever/Pairs.pl %changelist% %serverport%"
#	exampleP  //.../*.txt    "perl whatever/Pairs.pl %changelist% %serverport%"
#
# Tested on Platforms:   FreeBSD, NT (as program, not service).
#
# Most recent version tested against: 2002.2
#
# You might need to...
# 1. You might need to run change the "$p4 = ......." line,
#    below, to add a username and password
#         ('p4 -u hardcodedusername  -P hardcodeduserpasswd -p $ServerPort')
#    if the default user it's connecting as isn't appropriate.

$ChangeNum = $ARGV[0];
$ServerPort = $ARGV[1];
$p4 = "p4 -p $ServerPort ";

$MaxErrs = 10;
$OptimizeErrorOutput = "yes";

#-------- enter the suffixes for the pairs, here -----------------------------------
$listpairs{"cpp"} = "h";	# x.cpp must have x.h checked in, and also vice versa.
$listpairs{"txt"} = "html";	# x.txt must have x.html checked in, and also vice versa.
#-----------------------------------------------------------------------------------

Fatal("Changelist $ChangeNum (1st arg) needs to be numeric!\n") unless ($ChangeNum =~ /^\d+$/);
Fatal("\%serverport\% (2nd arg) wasn't specified.\n") if ($ServerPort eq "");

# cannot use 'p4 describe -s changenum', so we get a list of open files
# this way...
@OpenedList = `$p4 opened -a -c $ChangeNum`;

#
# Algorithm used:
#	for each file in that's being submitted...
#		1. Figure out if it's "interesting" to this trigger, which is to say,
#		   that it ends with one of the suffixes listed in "listpairs".
#		2. If so, add it to the associative array "FilesToChange". The
#		   value of the array element is the name of the OTHER item in the
#		   pair. (So if "x.h" is being submitted, $FilesToChange{"x.h"} will
#		   map to "x.cpp".)
#	After creating this array, then step through it making sure that each
#	item mentioned as a value ("x.cpp") is also a valid index. That means
#	that ``$FilesToChange{"x.cpp"} should exist''). If not, it's an error.
#
chomp(@OpenedList);
foreach (@OpenedList) {
	my($tmp);
	next unless /^(\/\/.*)#\d+ - .*\s$ChangeNum\s.*/;
	if (($tmp = IsInterestingFile($1, %listpairs)) ne "") {
		$FilesToChange{"$1"} = $tmp;
		$nfiles++;
	}
}

if ($nfiles == -1) {
	Inform("No changes modify files that belong in a pair. (Exiting.)\n");
	exit(0);
}

$nerrs = 0;
foreach $f (sort keys %FilesToChange) {
	my($expected_pair) = $FilesToChange{"$f"};
	if (!defined($FilesToChange{"$expected_pair"})) {
		# errors are reported to STDOUT, since NT triggers don't copy STDERR to user.
		print "$f was submitted, but $expected_pair wasn't - both should be submitted.\n";
		$nerrs++;
	}
	if ($nerrs >= $MaxErrs) {   
		Warn("*** Only first $MaxErrs errors shown\n");
		last;
	}
}

if ($nerrs > 0) {
	Fatal("Errors found, submission refused\n");	# Note, this prints to STDOUT. See above.
}
exit(0);

sub IsInterestingFile {
	my($fname, %listpairs) = @_;

	foreach $l (keys %listpairs) {
		my($suffix1, $suffix2) = ($l, $listpairs{$l});
		return "$1.$suffix2"
			if ($fname =~ /^(.*)\.$suffix1/);
		return "$1.$suffix1"
			if ($fname =~ /^(.*)\.$suffix2/);
	}
	return "";
}

###############################################################################
# Note that all messages (warning/fatal/info) go to STDOUT, not STDERR. Trigger
# output to standard output is sent to the user; standard error isn't.
###############################################################################
sub TellUser {
	my($str, $msgtype) = @_;
	print "$str";
	print "\n" unless ($str =~ /\n$/);
	exit(1) if ($msgtype eq fatal);
}

sub Warn {
	TellUser(@_, warning);
}
sub Fatal {
	TellUser(@_, fatal);
}

sub Inform {
	TellUser(@_, inform);
}
# Change User Description Committed
#6 4568 Jeff Bowles Updating comment format.
#5 3566 Jeff Bowles adding comments about 'you might need to...'
#4 3563 Jeff Bowles Doesn't need client specified now, uses whatever default
user/client provided. Might need to hard-code the user/password,
will add comment eventually saying so.
#3 518 Jeff Bowles Adding a bit of comment to deal with "Host:" fields that
might appear in client specs. Deliberately not adding the
code, since some earlier versions of p4d don't honor Host:
in the first place.
#2 375 Jeff Bowles Making a slight bit more selective by running "p4 opened -c NUM".
(Also, corrected slight error in which Pairs.pl would only bother
with the FIRST revision submitted for a file.)
#1 106 Jeff Bowles Branching these suckers to mimic the utils area.