#!/usr/local/bin/perl -w ############################################################################## # p4specs - Save Perforce client, user, 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 ############################################################################## 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() { 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() { 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() { 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() { 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() { 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() { 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: $!"; } } ############################################################################## # 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() { 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() { 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() { 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() { 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: $!"; } } ############################################################################## # 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() { 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(); DumpBranches(); DumpLabels(); 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() { 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() { 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() { 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() { 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() { 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() { chomp; if (/^\t/) { $_="\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();