# Copyright (c) 1997-2004, Perforce Software, Inc. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL PERFORCE SOFTWARE, INC. BE LIABLE FOR ANY # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package P4::UI; use Config; use strict; use vars qw( @ISA @EXPORT @EXPORT_OK ); require Exporter; @ISA = qw(Exporter ); @EXPORT_OK = qw( ); @EXPORT = qw( ); sub new { my $class = shift; my $self = { "binmode" => 0 }; bless( $self, $class ); return $self; } # Edit the specified file ( normally a change spec or client spec etc ). sub Edit($) { my $self = shift; my $filename = shift; my $editor = defined( $ENV{"P4EDITOR"} ) ? $ENV{"P4EDITOR"} : defined( $ENV{"EDITOR"} ) ? $ENV{"EDITOR"} : $^O eq "MSWin32" ? "notepad" : "vi"; system( "$editor $filename" ); } # Get the user to read a message and hit return to continue sub ErrorPause($) { my ($self, $message) = @_; $self->OutputError( $message ); $self->Prompt( "Hit return to continue ..." ); } # Read data from the user. Inefficiently at the moment. sub InputData { my $input = ""; my $line; while( $line = <> ) { $input .= $line; } } # Write out textual information from the server. $level indicates indentation. sub OutputInfo($$) { my ($self, $level, $data) = @_; for( ; $level; $level-- ) { print(".... "); } print( $data, "\n" ); } # # Write an error message to stdout. All error messages are delivered to the # Perl API ready formatted rather than in their structured form because it's # (a) too complicated and (b) not worth it to do anything more sophisticated. # sub OutputError($) { my ($self, $err) = @_; print( STDERR $err ); } # Tagged output format sub OutputStat { my ($self, $hash ) = @_; foreach my $key ( sort keys %$hash ) { if ( ref( $hash->{ $key } ) ) { # Nested element print( "... $key\n" ); foreach my $item ( @{ $hash->{ $key } } ) { print( "... ... $item\n" ); } } else { print("... $key ", $hash->{ $key }, "\n" ); } } print("\n"); } # Write a text buffer to stdout sub OutputText($$) { my ($self, $text, $len ) = @_; printf( "%*s", $len, $text ); } # Write a binary buffer to stdout. See clientuser.cc in the Perforce # API for the roots of this implementation. sub OutputBinary($$) { my ($self, $data, $len ) = @_; if ( $Config{ "osname" } == "MSWin32" ) { if ( $self->{ "binmode" } == !$len ) { $self->{ "binmode" } = !(!$len); binmode( STDOUT, $self->{ "binmode" } ? ":raw" : ":crlf" ); } } syswrite( STDOUT, $data, $len ); } # Prompt the user for input sub Prompt($) { my $self = shift; my $prompt = shift; print("$prompt" ); return <>; } # # Function to diff two files. This default implementation does nothing of # great use and is intended to be overridden in derived classes. It's only # called if you have previously called P4::Client::DoPerlDiffs() as by # default the diff output will go through the OutputText() interface. # sub Diff($$$$) { my $self = shift; my $f1 = shift; my $f2 = shift; my $diffFlags = shift; my $differ = shift; if ( $differ ) { print( "$f1 and $f2 differ\n" ); } else { print( "$f1 and $f2 are the same\n" ); } } 1; __END__ =head1 NAME P4::UI - User interface object for Perforce API =head1 SYNOPSIS use P4::Client; use P4::UI; my $client = new P4::Client; my $ui = new P4::UI; $client->SetClient( $clientname ); $client->SetPort ( $p4port ); $client->SetPassword( $p4password ); $client->Init() or die( "Failed to connect to Perforce Server" ); $client->Run( $ui, "info" ); $client->Run( $ui, "edit", "file.txt" ); $client->Final(); =head1 DESCRIPTION This module provides a skeleton user interface for Perforce commands. The output from the Perforce server is simply written to stdout, and input comes from stdin. In order to do anything clever, you will need to derive a subclass from P4::UI and override the appropriate methods. =head2 EXPORTS UI::new() - Create a new user interface object =head1 METHODS =over 4 =item C Constructor. The only method of this class you call directly. =item C Method called when the Perforce server wants the client to edit a specform ( changespec, jobspec, clientspec etc.). The default implementation simply invokes your chosen editor by checking the environment variables P4EDITOR and EDITOR before falling back on vi/notepad and hoping they're there. =item C Called to alert the user to an error message which they must acknowledge before continuing. Default implementation prints the message on stdout and prompts the user to "Hit Return to continue". =item C Used to read information directly from the user. Called in response to the "-i" flag to many Perforce commands. i.e. "p4 submit -i". =item C Writes data to stdout prefixed by $level occurances of "..." =item C Blurt an error to stderr. The error message arrives as preformatted text. =item C Print the output of a command in tagged format. The tagged data is passed as a hash reference for ease of use. Multi line fields (such as mappings) are presented as array references within the hash. i.e. in a clientspec, the View field in the form is normally transmitted by Perforce as a sequence of fields: "View0", "View1", etc. P4::UI gets these as a single "View" member of the hash which is itself an array reference containing the view records in order. =item C Prints $length bytes of $text on STDOUT =item C Prints the prompt string $prompt and then reads a line of input from the user returning the input line. =item C Diff two files manually. The default implementation of this method does nothing of any great use. It's intended to be overridden in subclasses for users who want to do the diffs themselves. This method will not be invoked unless you have previously called the P4::Client::DoPerlDiffs() method to specify your prediliction for doing things the hard way. Otherwise diff output goes out through OutputText(). =back =head1 LICENCE Copyright (c) 1997-2004, Perforce Software, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL PERFORCE SOFTWARE, INC. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =head1 AUTHOR Tony Smith, Perforce Software ( tony@perforce.com ) =head1 SEE ALSO perl(1), P4::Client(3), Perforce API documentation. =cut