p4specs #4

  • //
  • guest/
  • steve_smythe/
  • admintools/
  • p4specs
  • View
  • Commits
  • Open Download .zip Download (13 KB)
#!/usr/local/bin/perl -w
##############################################################################
# p4specs - Save Perforce client, user, group, branch, label, and protection
#           specifications and check the changed information to Perforce
#
# Logic:
#
# 1. Sync workspace first
# 2. Remove all files
# 3. Dump all specs
# 4. Keep changed
# 5. Submit
#
##############################################################################
# Version  Date        Author              Description
# -------  ----------  ------------------  -----------------------------------
#
# 1.0      2002.08.29  [email protected]  Initial Version
#
# 1.1      2002.09.23  [email protected]  Thanks to Robert O'Brien for adding
#                                          the DumpGroups code.
# 1.2      2003.03.14  [email protected]  Fawad Khan for suggesting adding
#                                          the DumpLabelSyncs code.
# 1.3      2003.03.26  [email protected]  Fawad Khan for suggesting adding
#                                          the extra text regular expression
#                                          to the DumpLabelSyncs code.
##############################################################################

use File::Path;

##############################################################################
# Init
##############################################################################
sub Init {
	$p4user="SuperuserUsernameHere";
	$p4passwd="SuperuserPasswordHere";
	$p4client="ClientspecNameHere";
	$p4="/usr/local/bin/p4 -u $p4user -P$p4passwd -c $p4client";
	
	$depotroot="//DepotPathToSpecs";
	$localroot="/LocalDiskPathToSpecs";

	if (! -d "$localroot") {
		mkpath("$localroot");
	}

	%clients=();
	%user=();
	%branch=();
	%label=();
}


##############################################################################
# Sync
##############################################################################
sub Sync {
	$cmd="$p4 sync $depotroot/...";
	print "cmd=[$cmd]\n";
	open(CMD, "$cmd 2>&1 |") || die "can't open command \"$cmd\" for piped output";
	while(<CMD>) {
		chomp;
		print "$_\n";
	}
	close(CMD) || die "can't close command \"$cmd\" for piped output";
}


##############################################################################
# Remove
##############################################################################
sub Remove {
	$cmd="rm -fr $localroot";
	print "cmd=[$cmd]\n";
	open(CMD, "$cmd 2>&1 |") || die "can't open command \"$cmd\" for piped output";
	while(<CMD>) {
		chomp;
		print "$_\n";
	}
	close(CMD) || die "can't close command \"$cmd\" for piped output";

	if (! -d "$localroot") {
		mkpath("$localroot");
	}
}


##############################################################################
# DumpClients
##############################################################################
sub DumpClients {
	# client
	print "Clients...\n";
	if (! -d "$localroot/clients") {
		mkpath("$localroot/clients");
	}
	$cmd="$p4 clients";
	open(CMD, "$cmd 2>&1 |") || die "can't open command \"$cmd\" for piped output";
	while(<CMD>) {
		chomp;
		@F=split;
		$clients{$F[1]}="";
	}
	close(CMD) || die "can't close command \"$cmd\" for piped output";
	
	foreach $client (sort keys %clients) {
		print "    $client\n";
		$file="$localroot/clients/$client";
		open(FILE, ">$file") || die "cannot open file \"$file\" for output: $!";
		$cmd2="$p4 client -o $client";
		open(CMD2, "$cmd2 |") || die "can't open command \"$cmd2\" for piped output";
		while(<CMD2>) {
			chomp;
			if (!(/^Access:/)) {
				print FILE "$_\n";
			}
		}
		close(CMD2) || die "can't close command \"$cmd2\" for piped output";
		close(FILE) || die "cannot close file \"$file\" for output: $!";
	}
}


##############################################################################
# DumpUsers
##############################################################################
sub DumpUsers {
	# user
	print "Users...\n";
	if (! -d "$localroot/users") {
		mkpath("$localroot/users");
	}
	$cmd="$p4 users";
	open(CMD, "$cmd 2>&1 |") || die "can't open command \"$cmd\" for piped output";
	while(<CMD>) {
		chomp;
		@F=split;
		$users{$F[0]}="";
	}
	close(CMD) || die "can't close command \"$cmd\" for piped output";
	
	foreach $user (sort keys %users) {
		print "    $user\n";
		$file="$localroot/users/$user";
		open(FILE, ">$file") || die "cannot open file \"$file\" for output: $!";
		$cmd2="$p4 user -o $user";
		open(CMD2, "$cmd2 |") || die "can't open command \"$cmd2\" for piped output";
		while(<CMD2>) {
			chomp;
			if (!(/^Access:/)) {
				print FILE "$_\n";
			}
		}
		close(CMD2) || die "can't close command \"$cmd2\" for piped output";
		close(FILE) || die "cannot close file \"$file\" for output: $!";
	}
}


##############################################################################
# DumpGroups
##############################################################################
sub DumpGroups {
    # client
    print "Groups...\n";
    if (! -d "$localroot/groups") {
        mkpath("$localroot/groups");
    }
    $cmd="$p4 groups";
    open(CMD, "$cmd 2>&1 |") || die "can't open command \"$cmd\" for piped output";
    while(<CMD>) {
        chomp;
        @F=split;
        $groups{$F[0]}="";
    }
    close(CMD) || die "can't close command \"$cmd\" for piped output";

    foreach $group (sort keys %groups) {
        print "    $group\n";
        $file="$localroot/groups/$group";
        open(FILE, ">$file") || die "cannot open file \"$file\" for output: $!";
        $cmd2="$p4 group -o $group";
        open(CMD2, "$cmd2 |") || die "can't open command \"$cmd2\" for piped output";
        while(<CMD2>) {
            chomp;
            if (!(/^Access:/) || !(/^Update:/) ){
                print FILE "$_\n";
            }
        }
        close(CMD2) || die "can't close command \"$cmd2\" for piped output";
        close(FILE) || die "cannot close file \"$file\" for output: $!";
    }
}


##############################################################################
# DumpBranches
##############################################################################
sub DumpBranches {
	# branch
	print "Branches...\n";
	if (! -d "$localroot/branches") {
		mkpath("$localroot/branches");
	}
	$cmd="$p4 branches";
	open(CMD, "$cmd 2>&1 |") || die "can't open command \"$cmd\" for piped output";
	while(<CMD>) {
		chomp;
		@F=split;
		$branches{$F[1]}="";
	}
	close(CMD) || die "can't close command \"$cmd\" for piped output";
	
	foreach $branch (sort keys %branches) {
		print "    $branch\n";
		$file="$localroot/branches/$branch";
		open(FILE, ">$file") || die "cannot open file \"$file\" for output: $!";
		$cmd2="$p4 branch -o $branch";
		open(CMD2, "$cmd2 |") || die "can't open command \"$cmd2\" for piped output";
		while(<CMD2>) {
			chomp;
			if (!(/^Access:/)) {
				print FILE "$_\n";
			}
		}
		close(CMD2) || die "can't close command \"$cmd2\" for piped output";
		close(FILE) || die "cannot close file \"$file\" for output: $!";
	}
}


##############################################################################
# DumpLabels
##############################################################################
sub DumpLabels {
	# label
	print "Labels...\n";
	if (! -d "$localroot/labels") {
		mkpath("$localroot/labels");
	}
	$cmd="$p4 labels";
	open(CMD, "$cmd 2>&1 |") || die "can't open command \"$cmd\" for piped output";
	while(<CMD>) {
		chomp;
		@F=split;
		$labels{$F[1]}="";
	}
	close(CMD) || die "can't close command \"$cmd\" for piped output";
	
	foreach $label (sort keys %labels) {
		print "    $label\n";
		$file="$localroot/labels/$label";
		open(FILE, ">$file") || die "cannot open file \"$file\" for output: $!";
		$cmd2="$p4 label -o $label";
		open(CMD2, "$cmd2 |") || die "can't open command \"$cmd2\" for piped output";
		while(<CMD2>) {
			chomp;
			if (!(/^Access:/)) {
				print FILE "$_\n";
			}
		}
		close(CMD2) || die "can't close command \"$cmd2\" for piped output";
		close(FILE) || die "cannot close file \"$file\" for output: $!";
	}
}


##############################################################################
# DumpLabelSyncs
##############################################################################
sub DumpLabelSyncs {
	# label
	print "Label Syncs...\n";
	if (! -d "$localroot/labelsyncs") {
		mkpath("$localroot/labelsyncs");
	}
	$cmd="$p4 labels";
	open(CMD, "$cmd 2>&1 |") || die "can't open command \"$cmd\" for piped output";
	while(<CMD>) {
		chomp;
		@F=split;
		$labels{$F[1]}="";
	}
	close(CMD) || die "can't close command \"$cmd\" for piped output";
	
	foreach $label (sort keys %labels) {
		print "    $label\n";
		$file="$localroot/labelsyncs/$label";
		open(FILE, ">$file") || die "cannot open file \"$file\" for output: $!";
		$cmd2="$p4 files \@$label";
		open(CMD2, "$cmd2 |") || die "can't open command \"$cmd2\" for piped output";
		while(<CMD2>) {
			chomp;
			if (!(/^Access:/)) {
				s/^(.*#\d+)\s+.*$/$1/g;
				print FILE "$_\n";
			}
		}
		close(CMD2) || die "can't close command \"$cmd2\" for piped output";
		close(FILE) || die "cannot close file \"$file\" for output: $!";
	}
}


##############################################################################
# DumpProtections
##############################################################################
sub DumpProtections {
	# protections
	print "Protections...\n";
	if (! -d "$localroot/protections") {
		mkpath("$localroot/protections");
	}
	$file="$localroot/protections/protect";
	open(FILE, ">$file") || die "cannot open file \"$file\" for output: $!";
	$cmd="$p4 protect -o";
	open(CMD, "$cmd 2>&1 |") || die "can't open command \"$cmd\" for piped output";
	while(<CMD>) {
		chomp;
		print FILE "$_\n";
	}
	close(CMD) || die "can't close command \"$cmd\" for piped output";
	close(FILE) || die "cannot close file \"$file\" for output: $!";
}


##############################################################################
# Dump
##############################################################################
sub Dump {
	DumpClients();
	DumpUsers();
	DumpGroups();
	DumpBranches();
	DumpLabels();
	DumpLabelSyncs();
	DumpProtections();
}


##############################################################################
# Keep
##############################################################################
sub Keep {
	# First, find the new files and open them for "add"
	$cmd="find $localroot -type f -print | $p4 -x - add";
	print "cmd=[$cmd]\n";
	open(CMD, "$cmd 2>&1 |") || die "can't open command \"$cmd\" for piped output";
	while(<CMD>) {
		chomp;
		print "$_\n";
	}
	close(CMD) || die "can't close command \"$cmd\" for piped output";
	
	# Next, open for "delete" any old files no longer present
	$cmd="$p4 diff -sd //$p4client/... | $p4 -x - delete";
	print "cmd=[$cmd]\n";
	open(CMD, "$cmd 2>&1 |") || die "can't open command \"$cmd\" for piped output";
	while(<CMD>) {
		chomp;
		print "$_\n";
	}
	close(CMD) || die "can't close command \"$cmd\" for piped output";
	
	
	# Finally, open for "edit" any files that have changed
	$cmd="$p4 diff -se //$p4client/... | $p4 -x - edit";
	print "cmd=[$cmd]\n";
	open(CMD, "$cmd 2>&1 |") || die "can't open command \"$cmd\" for piped output";
	while(<CMD>) {
		chomp;
		print "$_\n";
	}
	close(CMD) || die "can't close command \"$cmd\" for piped output";
}


##############################################################################
# Revert
##############################################################################
sub Revert {
	$cmd="$p4 revert -a $depotroot/...";
	print "cmd=[$cmd]\n";
	open(CMD, "$cmd 2>&1 |") || die "can't open command \"$cmd\" for piped output";
	while(<CMD>) {
		chomp;
		print "$_\n";
	}
	close(CMD) || die "can't close command \"$cmd\" for piped output";
}


##############################################################################
# Submit
##############################################################################
sub Submit {
	$open=1;
	$cmd="$p4 opened";
	print "cmd=[$cmd]\n";
	open(CMD, "$cmd 2>&1 |") || die "can't open command \"$cmd\" for piped output";
	while(<CMD>) {
		chomp;
		if ($_ =~ /not opened on this client/) {
			$open=0;
		}
		print "$_\n";
	}
	close(CMD) || die "can't close command \"$cmd\" for piped output";

	if ($open==1) {
		$cmd="$p4 change -o";
		$cmd2="$p4 submit -i";
		open(CMD, "$cmd 2>&1 |") || die "can't open command \"$cmd\" for piped output";
		open(CMD2, "| $cmd2 2>&1") || die "can't open command \"$cmd2\" for piped input";
		while(<CMD>) {
			chomp;
			if (/^\t<enter description here>/) {
				$_="\tp4spec: Automatic save of Perforce specifications";
			}
			print "$_\n";
			print CMD2 "$_\n";
		}
		close(CMD2) || die "can't close command \"$cmd2\" for piped input";
		close(CMD) || die "can't close command \"$cmd\" for piped output";
	} else {
		print "No changes to submit\n";
	}
}


##############################################################################
# Process
##############################################################################
sub Process {
	Sync();
	Remove();
	Dump();
	Keep();
	Revert();
	Submit();
}


##############################################################################
# MAIN MAIN MAIN MAIN MAIN MAIN MAIN MAIN MAIN MAIN MAIN MAIN MAIN MAIN MAIN #
##############################################################################
Init();
Process();
# Change User Description Committed
#4 2993 Steve Smythe Thanks to Fawad Khan for suggesting adding the extra text regular
expression to the DumpLabelSyncs code.
#3 2937 Steve Smythe Add DumpLabelSyncs per the request of Fawad Khan.
#2 2143 Steve Smythe Update p4specs to v1.1 with DumpGroups code from Robert O'Brien.
#1 2060 Steve Smythe Save Perforce client, user, branch, label, and protection specifications and check the changed information to Perforce