#!/usr/bin/ruby require "P4" #******************************************************************************* # Construct your client # p4 = P4.new() #******************************************************************************* # Perforce client environment - getting the default settings # # p4.client? - Get P4CLIENT # p4.host? - Get P4HOST # p4.password? - Get P4PASSWD # p4.port? - Get P4PORT # p4.user? - Get P4USER # print <<EOS Perforce settings: P4PORT = #{p4.port?} P4USER = #{p4.user?} P4CLIENT = #{p4.client?} EOS #******************************************************************************* # Perforce client environment - setting specific values # # Uncomment the settings below as required # # p4.client( "tonys_client" ) # p4.host( "myhostname" ) # p4.password( "ruby" ) # p4.port( "localhost:1666" ) # p4.user( "tony" ) # p4.port( "localhost:1666" ) #******************************************************************************* # Protocol options. Must be called before connecting # # p4.tagged() - Tagged output # p4.parse_forms() - Tagged output + form parsing. Converts "p4 xxx -o" # output into a hash # p4.parse_forms() # #******************************************************************************* # Connect to Perforce begin p4.connect() rescue P4Exception puts( "Failed to connect to Perforce" ) raise end #******************************************************************************* # Running commands. All run* methods return an array. That can mean one line of # output per array element, or in tagged/parse_forms mode, that can mean an # array of hashes. # # By default a P4Exception is raised if any errors or warnings are encountered # during command execution. You can also opt to have exceptions raised only # for errors (and not warnings), or not at all by setting the exception level. # The available levels are: # # 0 - Exceptions disabled # 1 - Exceptions for errors # 2 - Exceptions for errors and warnings # # For example: # # p4.exception_level( 1 ) # # You can fetch the results of the command from within a rescue block # by calling P4#output; the errors with P4#errors and the warnings with # P4#warnings # #******************************************************************************* #******************************************************************************* # "p4 user -o" with "parse_forms" enabled produces an array with a single # hash entry. # begin user_spec = p4.run( "user", "-o" ).shift print <<EOS User details: User Name: #{user_spec[ "User" ]} Full Name: #{user_spec[ "FullName" ]} Email Address: #{user_spec[ "Email" ]} EOS #******************************************************************************* # Now that we have the user's details, we can update them. Since this # example is invasive, it's commented out by default. # # user_spec[ "Email" ].upcase! # p4.input( user_spec ) # p4.run( "user", "-i" ) # #******************************************************************************* # You can also run Perforce commands by invoking the method "run_<command>" # rather than passing the command name as an argument to the run method. For # example info = p4.run_info() user_spec = p4.run_user( "-o" ).shift user_list = p4.run_users() protections = p4.run_protect( "-o" ).shift #******************************************************************************* # There are also shortcut methods to make form editing easy. Any method # taking the form "fetch_<command>" is equivalent to running "p4 <command> -o" # and likewise any method taking the form "save_<command>" is equivalent to # running "p4 <command> -i". These methods do not return an array - they # return only one element, since that's all that Perforce will return to you. # # Note that all of the "save*" methods require an argument. The argument # can be either a string containing the edited form, or if you're using # parse_forms() mode, then it can be the edited hash returned from a previous # "fetch*" call. # client_spec = p4.fetch_client() client_spec[ "Owner" ] = "tony" # p4.save_client( client_spec ) rescue P4Exception => msg puts( msg ) p4.warnings.each { |w| puts( w ) } p4.errors.each { |e| puts( e ) } p4.output.each { |o| puts( o ) } end
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#6 | 1166 | Tony Smith |
Followup to previous change. Simplify the interface to getting results/errors and warnings. No need for the P4Result class anymore so that's gone (though it's still there as a C++ class because it's useful) and so is P4#result. Now you get your errors/warnings and results using P4#errors, P4#warnings and P4#output all of which return arrays. |
||
#5 | 1165 | Tony Smith |
Minor reshuffle. Added the ability to disable exceptions completely if you don't like them or to have them raised only for errors (and not for warnings). Removed P4#warnings interface and replaced it with P4#exception_level. Some minor doc tweaks to go with the above change |
||
#4 | 1164 | Tony Smith |
Reworked exception handling (hopefully for the last time) in P4/Ruby. Now exceptions are raised on completion of Perforce commands if any errors or warnings were received as part of executing the command. This change also adds documentation, and indexes the Ruby interface off my main page. Bad form to combine so many changes in one changelist, but it's getting late and I want to get them submitted! |
||
#3 | 1083 | Tony Smith |
Sweeping change to exception handling and garbage collection. Exceptions are no longer raised for errors encoutered during execution of Perforce commands as that was causing processing to abort at the first error when several success messages may have been close behind. Now exceptions are raised for events which are fatal to the execution of commands - such as failure to connect to the Perforce server for example. For other errors, the user must call "p4.errors? " to determine whether or not errors occured and "p4.errors" to get an array of error messages. You can of course then raise exceptions yourself if you want to: begin client = p4.fetch_client if p4.errors? raise P4Exception, "p4 client -o failed" end rescue P4Exception => m puts( m ) p4.errors.each { |e| puts( e ) } end version.h got renamed because it conflicts with ruby's own version.h file. We may need to look in there at some point for ruby's version so I'm getting it out of the way now. Added gc_hack.h to make sure that GC works properly on all platforms now so Ruby shouldn't nuke any objects we're holding now. |
||
#2 | 1027 | Tony Smith |
Rework structure slightly. What was P4.so is now called P4api.so and a new P4.rb module is added. P4api.so contains the raw bridge to the Perforce API whilst P4.rb contains extensions to it written purely in Ruby. Both define and extend the P4 class and P4.rb requires P4api.so so user code is unaffected. The intent is to give me a place to write Ruby code rather than having to work solely in C++. The first method added using this new structure is P4#method_missing, so now Perforce commands all appear as methods on the P4 object (prefixed by "run_" ). e.g p4 = P4.new p4.run_info() p4.run_users() p4.run_protect( "-o" ) This change also adds support for shortcut methods for form editing. fetch* and save* methods have been added as shortcuts for "p4 <cmd> -o" and "p4 <cmd> -i" respectively. For example: p4 = P4.new p4.parse_forms() client_spec = p4.fetch_client() client_spec[ "Owner" ] = tony p4.save_client( client_spec ) Note that unlike the run* methods, these accessor methods do not return an array, but return a single result - a string normally, or a hash in parse_forms mode. Ruby's arcane build/install system means that you have to install the P4.rb file yourself. "make install" doesn't take care of it. |
||
#1 | 1015 | Tony Smith |
First cut of Perforce bindings for the Ruby scripting language. Similar functionality to the Perl API stuff, but "rubyfied". Supports error reporting via exceptions, and presents tagged output and parsed forms as hash structures, with nested arrays where required. Still early days so the docs are thin on the ground. See the example.pl for a brief guide. Built with Ruby 1.6.4 on Linux. May still be some memory management issues as the Ruby Garbage Collection API has changed a little since the docs I've got and I've just dodged garbage collection for now. Not indexing this just yet. |