- <html>
- <STYLE type="text/css">
- H1 {border-width: 1; border: solid}
- </STYLE>
- <title>Scripting Column as of $Date: 2004/08/20 $</title>
- <h1><center>Monthly Scripting Column for March</center></h1>
- <table border=0 width="100%">
- <tr><td width="70%">
- <p>Greetings!
- This continues a series of bulletins, in which we introduce
- one of the scripts that will be in a future release.
- <td>
- <table border=1 width="100%">
- <tr><td><i><font color="blue">Tip: Let someone else
- parse the data.<br>'p4 -Ztag' and 'p4 -G' are good places to
- start, and P4Ruby and P4Perl provide API access via loadable modules.
- </font></i>
- </table>
- </tr>
- </table>
- <hr>
- <h2>Today's script</h2>
- <p>Perl has its detractors, but it's handy.
- <p>We present <a href="examples/oldclients.pl">oldclients.pl</a>, a script that finds the clients whose owners aren't in list that you get from "p4 users". (These owners are
- probably just old users who've been deleted, but the owner field
- in the client spec retains the original owner's name. It's no big deal,
- but offends our sense of order.)
- <p>The challenge is to do it with as few calls to 'p4' as possible.
- <em>We know we need the list of clients and the list of users,
- which is two calls to 'p4'. Do we need any more than that?</em>
- <h3>Parsing output</h3>
- Most of the commands have an alternate way of invoking them:
- <pre>
- p4 <font color="red">-Ztag</font> clients
- </pre>
- This returns "tagged" output - this column
- gave an example of it two months back
- in some P4Perl code - and tells Perforce to let you have output
- that looks like this:
- <pre>
- ... client heart
- ... Update 1001544831
- ... Access 1081295702
- ... Owner arthur
- ... Options noallwrite noclobber nocompress unlocked nomodtime normdir
- ... Root /tmp/home/examples/heart
- ... Host
- ... MapState 1
- ... Description
- </pre>
- <p>That's the information for one entry, which means one client workspace.
- (An empty line separates each client's data.)
- <p>Look at this closely.
- <ol><li>The first thing on the line is the "tag".
- <li>the rest of the line is specific to the tag, for example
- the dates are stored as an integer (seconds since early 1970,
- if you must know).
- </ol>
- For example, this refers to client "heart", which has
- no "Host" entry. Arthur's the "Owner".
- <p>
- We've written a small routine, <a href="examples/ztag.pl">ztag.pl</a>, to parse this for the simplest
- cases ('p4 files', 'p4 users', etc). It's used in our script, thusly:
- <pre>
- <font color="green">require "ztag.pl";</font>
- $p4 = "p4 -Ztag -u zaphod";
- <font color="green">$client_tagged_cmd = "$p4 users";
- @ret = readinZtag($client_tagged_cmd);</font>
- foreach $u (@ret) {
- $userName = $u->{'User'};
- print "$userName\n";
- }
- </pre>
- <hr>
- <h3>First step: Figuring out what data you need</h3>
- <p>
- In this case:
- <ol><li>For the list of users, run "p4 -Ztag users" ;
- <li>For the list of clients, run "p4 -Ztag clients".
- </ol>
- <p>Take a moment to notice that
- "p4 -Ztag clients" has a lot of information in the
- tagged output. The options are there, so writing a script to
- report which clients have 'compress' enabled will need one call to 'p4'.
- (In fact, the Perforce example database has such a script.)
- <h3>Second step: Piece together the program</h3>
- <p>
- The program is below. The basic flow is:
- <ol><li>Get the list of users;
- <li>Get the list of clients (and respective owners, of course);
- <li>For each of the clients:
- <bl><li>See if the owner is on the user-list. Print what you find.
- </bl>
- </ol>
- Note that we are cautious about how we check that user-list.
- The Perl construct, "defined", is helpful because it doesn't
- create anything as a side-effect of looking.
- <hr>
- <center>Reminder: <font color="green">Green text</font> for Perforce hooks.</center>
- <hr>
- <pre>
- # Task: compare client specs to users, and flag the
- # client specs owned by users that don't exist anymore.
- #
- <font color="green"># num of calls to 'p4': 2</font>
- # status: tested on Win/2000 using perl 5.6
- #
- # room for optimization/improvement: add getopts call
- #
- # Copyright 2004 Perforce Corporation, Inc. All rights reserved.
- <font color="green">require "ztag.pl";</font>
- $p4 = "p4 -Ztag -u zaphod";
- #-----------------------------------------------------------
- # first call to P4: 'p4 users'
- #-----------------------------------------------------------
- <font color="green">$client_tagged_cmd = "$p4 users";
- @ret = readinZtag($client_tagged_cmd);</font>
- %userHash = {};
- foreach $u (@ret) {
- $userName = $u->{'User'};
- $userHash{$userName} = $u;
- }
- #-----------------------------------------------------------
- # second call to P4: 'p4 clients'
- #-----------------------------------------------------------
- <font color="green">$client_tagged_cmd = "$p4 clients";
- @ret = readinZtag($client_tagged_cmd);</font>
- foreach $c (@ret) {
- $clientName = $c->{'client'};
- $clientOwner = $c->{'Owner'};
- if (defined($userHash{$clientOwner})) {
- print "$clientName owned by $clientOwner OK\n";
- } else {
- print "$clientName owned by $clientOwner ** unknown user **\n";
- }
- }
- </pre>
- <hr>
- <small><p>Note: all the programs shown in these columns have been written four times: in Perl, in P4Perl, in Python, and in P4Ruby. Look into the Perforce example database for the other versions.</small>
- <i><small>$Id: //guest/jeff_bowles/scripts/0330perl.html#1 $</small>
- <br>© 2004 Perforce Corporation, Inc.</small></i>
- </html>
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#1 | 4420 | Jeff Bowles |
adding the beginnings of example "columns" for scripting examples. |
21 years ago |