defaultclient.rb #4

  • //
  • guest/
  • tony_smith/
  • perforce/
  • P4Rubylib/
  • triggers/
  • defaultclient.rb
  • View
  • Commits
  • Open Download .zip Download (6 KB)
#!/usr/bin/ruby
#--
#-------------------------------------------------------------------------------
#++
#
# == Introduction
#
#	This script ensures that the default client view offered to users
#	for new client workspaces is based on a template client specified
#	in the trigger definition.
#
# == Synopsis
#
#	defaultclient.rb <templatename> <clientname> <formfile>
#
# == Sample Trigger Definition
#
#	Using a trigger spec like this:
#
#  defaultclient out client "defaultclient.rb baseclient %formname% %formfile%"
#
#	would make the default client view offered to any user based on 
#	the view defined in the client called 'baseclient'. Changing that
#	client spec would change the default view.
#
# == License
#
#  Copyright (c) 1997-2008, 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.
#  
# == Version
#
#	$Id: //guest/tony_smith/perforce/P4Rubylib/triggers/defaultclient.rb#4 $
#
#--
#-------------------------------------------------------------------------------
#++
$:.unshift( File.dirname( __FILE__ ) )
require "P4"
require "P4Triggers"

#--
#-------------------------------------------------------------------------------
#			LOCAL CLASSES
#-------------------------------------------------------------------------------
#++

#
# Our P4Trigger subclass. Using P4Trigger allows us to use the pre-existing
# methods for error reporting and exit status handling.
#

class ClientTrigger < P4Trigger

    def initialize( client, template, filename )
	super()
	@client		= client
	@template	= template
	@formfile 	= P4Trigger::FormFile.new( filename )
	p4.exception_level = P4::RAISE_ERRORS
    end

    #
    # Check whether or not a client already exists. We do this using 'p4 info'
    # rather than 'p4 clients' since running 'p4 clients' on a large system
    # can be very expensive. 
    #
    def client_exists?( name )
	tp4 = P4.new
	tp4.client = name
	tp4.port = p4.port
	tp4.user = p4.user
	tp4.connect

	info = tp4.run_info.shift
	tp4.disconnect

	return true if info.has_key?( 'clientRoot' )
	return false
    end

    #
    # Main method - loads the template spec, and makes the alterations to
    # the formfile in place.
    #
    def update_client()
	begin
	    # Connect to server
	    p4.connect

	    #
	    # Sanity checks:
	    #
	    # (a) Don't do anything if the client already exists
	    # (b) Don't do anything if the template doesn't exist
	    # (c) Don't do anything if the client in question IS the template!
	    #
	    # Note that (c) is VITAL to prevent infinite recursion caused by
	    # an 'out' trigger running a 'p4 client -o'!!!
	    #
	    return 0 if( client_exists?( @client ) )
	    return 0  unless( client_exists?( @template ) )
	    return 0 if( @client == @template )

	    # First fetch the template spec. This will cause our Perforce
	    # server to execute this script again in another thread/process. 
	    # Fortunately, check (c) above stops the infinite loop
	    #
	    # Note that this also gets the specdef for clients from this server 
	    # so that P4Ruby can cache it so parse_client() and format_client()
	    # will not send any commands to the server.

	    tspec = p4.fetch_client( @template )
	    cspec = p4.parse_client( @formfile.load() )

	    # Now copy across the options and view from the template clientspec.
	    # For the view, we have to replace the template name with the client
	    # name as we copy.
	    cspec[ "View" ] = tspec[ "View" ].collect do
		|mapping|
		mapping.sub( "//#{@template}/", "//#{@client}/" )
	    end

	    cspec[ "Options" ] 	= tspec[ "Options" ]

	    # Now update the existing formfile with the new spec.
	    @formfile.save( p4.format_client( cspec ) )
	    return 0
	rescue
	    return report_error()
	end
    end
end


#--
#-------------------------------------------------------------------------------
#			LOCAL FUNCTIONS
#-------------------------------------------------------------------------------
#++


#
# Show a message explaining correct usage of this script and exit.
#
def croakusage()
    puts <<EOS

Usage: defaultclient.rb <templatename> <clientname> <formfile>

Where:
    <templatename>             - the name of an existing client workspace 
                                 on which all future client workspaces 
                                 should be based (by default).

    <clientname>               - The name of the client spec the user's 
                                 asking for

    <formfile>                 - The name of the temporary file in which the
                                 current client spec is stored

EOS
    exit( 1 )
end


#--
#-------------------------------------------------------------------------------
# START OF MAIN SCRIPT
#-------------------------------------------------------------------------------
#++

croakusage() unless ARGV.length() == 3

template 	= ARGV.shift;
client 		= ARGV.shift;
formfile 	= ARGV.shift;

#
# This next line is CRITICAL. It prevents an infinite recursion which will
# only terminate when your server runs out of resources. This is because
# this script is triggered whenever a user runs a 'p4 client -o' and this
# script itself runs a 'p4 client -o' ...
#
exit( 0 ) if( client == template)
trig = ClientTrigger.new( client, template, formfile );
exit( trig.update_client() )
# Change User Description Committed
#4 6437 Tony Smith Update P4Ruby Library scripts to support Perforce P4Ruby 2007.3
rather than my old public depot P4Ruby.
#3 5809 Tony Smith Ensure disconnection of temporary Perforce client.
Bug fix spotted
during code review.
#2 4656 Tony Smith Rework the defaultclient.rb trigger to be more robust and more
efficient. This involved a certain amount of rework to the
P4Triggers.rb module to include functionality that will be useful
to other spec triggers - there's a new class P4Trigger::FormFile
that helps scripts manage their interaction with the temporary
formfile supplied by the server.
#1 4654 Tony Smith Add an example spec trigger to show how you might restrict the
default view for all new clients to a pre-defined set of
mappings.