#!/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 ssmythe@docent.com Initial Version
#
# 1.1 2002.09.23 ssmythe@docent.com Thanks to Robert O'Brien for adding
# the DumpGroups code.
# 1.2 2003.03.14 ssmythe@docent.com Fawad Khan for suggesting adding
# the DumpLabelSyncs code.
# 1.3 2003.03.26 ssmythe@docent.com 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 |