#!/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 |