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