#******************************************************************************* # vim:ts=2:sw=2:et: # Copyright (c) 2001-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. #******************************************************************************* #******************************************************************************* #* Ruby interface to the Perforce SCM System #******************************************************************************* #******************************************************************************* #* P4 class #******************************************************************************* require_relative 'P4/version' # # Get the bulk of the definition of the P4 class from the API interface # require 'P4.so' # # Add the extra's written purely in ruby. # class P4 # # Named constants for the exception levels. Note they are cumulative, # so RAISE_ALL includes RAISE_ERRORS (as you'd expect). # RAISE_NONE = 0 RAISE_ERRORS = 1 RAISE_ALL = 2 # # Named values for merge actions. Values taken from clientmerge.h in # the Perforce API # MERGE_SKIP = 1 MERGE_ACCEPT_MERGED = 2 MERGE_ACCEPT_EDIT = 3 MERGE_ACCEPT_THEIRS = 4 MERGE_ACCEPT_YOURS = 5 # Named values for generic error codes returned by # P4::Message#generic EV_NONE = 0 # misc # The fault of the user EV_USAGE = 0x01 # request not consistent with dox EV_UNKNOWN = 0x02 # using unknown entity EV_CONTEXT = 0x03 # using entity in wrong context EV_ILLEGAL = 0x04 # trying to do something you can't EV_NOTYET = 0x05 # something must be corrected first EV_PROTECT = 0x06 # protections prevented operation # No fault at all EV_EMPTY = 0x11 # action returned empty results # not the fault of the user EV_FAULT = 0x21 # inexplicable program fault EV_CLIENT = 0x22 # client side program errors EV_ADMIN = 0x23 # server administrative action required EV_CONFIG = 0x24 # client configuration inadequate EV_UPGRADE = 0x25 # client or server too old to interact EV_COMM = 0x26 # communications error EV_TOOBIG = 0x27 # not even Perforce can handle this much # Named values for error severities returned by # P4::Message#severity E_EMPTY = 0 # nothing yet E_INFO = 1 # something good happened E_WARN = 2 # something not good happened E_FAILED = 3 # user did something wrong E_FATAL = 4 # system broken -- nothing can continue # OutputHandler return values constants REPORT = 0 HANDLED = 1 CANCEL = 2 # Client progress 'done' state PROG_NORMAL = 0 PROG_DONE = 1 PROG_FAILDONE = 2 PROG_FLUSH = 3 # Mappings for P4#each_<spec> # Hash of type vs. key SpecTypes = { "clients" => ["client", "client"], "labels" => ["label", "label"], "branches" => ["branch", "branch"], "changes" => ["change", "change"], "streams" => ["stream", "Stream"], "jobs" => ["job", "Job"], "users" => ["user", "User"], "groups" => ["group", "group"], "depots" => ["depot", "name"], "servers" => ["server", "Name"], } def method_missing( m, *a ) # Generic run_* methods if ( m.to_s =~ /^run_(.*)/ ) return self.run( $1, a ) # Generic fetch_* methods elsif ( m.to_s =~ /^fetch_(.*)/ ) return self.run( $1, "-o", a ).shift # Generic save_* methods elsif ( m.to_s =~ /^save_(.*)/ ) if ( a.length == 0 ) raise( P4Exception, "Method P4##{m.to_s} requires an argument", caller) end self.input = a.shift return self.run( $1, "-i", a ) # Generic delete_* methods elsif ( m.to_s =~ /^delete_(.*)/ ) if ( a.length == 0 ) raise( P4Exception, "Method P4##{m.to_s} requires an argument", caller) end return self.run( $1, "-d", a ) # Generic parse_* methods elsif ( m.to_s == "parse_forms" ) raise( NoMethodError, "undefined method 'P4#parse_forms'", caller ) elsif ( m.to_s =~ /^parse_(.*)/ ) if ( a.length != 1 ) raise( P4Exception, "Method P4##{m.to_s} requires an argument", caller) end return self.parse_spec( $1, a.shift ) # Generic format_* methods elsif ( m.to_s =~ /^format_(.*)/ ) if ( a.length != 1 ) raise( P4Exception, "Method P4##{m.to_s} requires an argument", caller) end return self.format_spec( $1, a.shift ) # # Generic each_* methods # Simple method to iterate over a particular type of spec # This is a convenient wrapper for the pattern: # clients = p4.run_clients # clients.each do # |c| # client = p4.fetch_client( c['client'] ) # <do something with client> # end # # NOTE: It's not possible to implicitly pass a block to a # delegate method, so I've implemented it here directly. Could use # Proc.new.call, but it looks like there is a serious performance # impact with that method. # elsif ( m.to_s =~ /^each_(.*)/ ) raise( P4Exception, "No such method P4##{m.to_s}", caller) unless SpecTypes.has_key?( $1 ) raise( P4Exception, "Method P4##{m.to_s} requires block", caller) unless block_given? specs = self.run( $1, a ) cmd = SpecTypes[ $1 ][0].downcase key = SpecTypes[ $1 ][1] specs.each{ |spec| spec = self.run( cmd, "-o", spec[key] ).shift yield spec } return specs # That's all folks! else raise NameError, "No such method #{m.to_s} in class P4", caller end end # # Simple interface for submitting. If any argument is a Hash, (or subclass # thereof - like P4::Spec), then it will be assumed to contain the change # form. All other arguments are passed on to the server unchanged. # def run_submit( *args ) form = nil nargs = args.flatten.collect do |a| if( a.kind_of?( Hash ) ) form = a nil else a end end.compact if( form ) self.input = form nargs.push( "-i" ) end return self.run( "submit", nargs ) end # # Simple interface for shelving. Same rules as for submit apply def run_shelve( *args ) form = nil nargs = args.flatten.collect do |a| if( a.kind_of?( Hash ) ) form = a nil else a end end.compact if( form ) self.input = form nargs.push( "-i" ) end return self.run( "shelve", nargs ) end def delete_shelve( *args ) if( ! args.include?( "-c" ) ) args.unshift( "-c") end return self.run( "shelve", "-d", args) end # # Simple interface for using "p4 login" # def run_login( *args ) self.input = self.password return self.run( "login", args ) end def run_resolve( *args ) if( block_given? ) self.run( "resolve", args ) do |default| yield( default ) end else self.run( "resolve", args ) end end # # Simple interface to 'p4 tickets' # def run_tickets path = self.ticket_file # return an empty array if the file doesn't exist # or is a directory. results = Array.new re = Regexp.new( /([^=]*)=(.*):([^:]*)$/ ) if( File.exist?( path ) and !File.directory?( path ) ) File.open( path ) do |file| file.each_line do |line| res = re.match( line ) if( res ) tickets = { 'Host' => res[1], 'User' => res[2], 'Ticket' => res[3] } results.push( tickets ) end end end end return results end # # Interface for changing the user's password. Supply the old password # and the new one. # def run_password( oldpass, newpass ) if( oldpass && oldpass.length > 0 ) self.input = [ oldpass, newpass, newpass ] else self.input = [ newpass, newpass ] end self.run( "password" ) end # # The following methods convert the standard output of some common # Perforce commands into more structured form to make using the # data easier. # # (Currently only run_filelog is defined. More to follow) # # run_filelog: convert "p4 filelog" responses into objects with useful # methods # # Requires tagged output to be of any real use. If tagged output it not # enabled then you just get the raw data back # def run_filelog( *args ) raw = self.run( 'filelog', args.flatten ) raw.collect do |h| if ( ! h.kind_of?( Hash ) ) h else df = P4::DepotFile.new( h[ "depotFile" ] ) h[ "rev" ].each_index do |n| # If rev is nil, there's nothing here for us next unless h[ "rev" ][ n ] # Create a new revision of this file ready for populating r = df.new_revision h.each do |key,value| next unless( value.kind_of?( Array ) ) next unless value[ n ] next if( value[ n ].kind_of?( Array ) ) # If the field is the revision time, convert it to a Time object value[ n ] = Time.at( value[ n ].to_i ) if key == "time" r.set_attribute( key, value[ n ] ) end # Now if there are any integration records for this revision, # add them in too next unless ( h[ "how" ] ) next unless ( h[ "how" ][ n ] ) h[ "how" ][ n ].each_index do |m| how = h[ "how" ][ n ][ m ] file = h[ "file" ][ n ][ m ] srev = h[ "srev" ][ n ][ m ] erev = h[ "erev" ][ n ][ m ] srev.gsub!( /^#/, "" ) erev.gsub!( /^#/, "" ) srev = ( srev == "none" ? 0 : srev.to_i ) erev = ( erev == "none" ? 0 : erev.to_i ) r.integration( how, file, srev, erev ) end end df end end end # # Allow the user to run commands at a temporarily altered exception level. # Pass the new exception level desired, and a block to be executed at that # level. # def at_exception_level( level ) return self unless block_given? old_level = self.exception_level self.exception_level = level begin yield( self ) ensure self.exception_level = old_level end self end # # Allow users to run commands using a specified handler. # Pass a handler and the block that will be executed using this handler # The handler will be reset to its previous value at the end of this block # def with_handler( handler ) return self unless block_given? old_handler = self.handler self.handler = handler begin yield( self ) ensure self.handler = old_handler end self end # # Show some handy information when using irb # def inspect sprintf( 'P4: [%s] %s@%s (%s)', self.port, self.user, self.client, self.connected? ? 'connected' : 'not connected' ) end #***************************************************************************** # The P4::Spec class holds the fields in a Perforce spec #***************************************************************************** class Spec < Hash def initialize( fieldmap = nil ) @fields = fieldmap end # # Override the default assignment method. This implementation # ensures that any fields defined are valid ones for this type of # spec. # def []=( key, value ) if( self.has_key?( key ) || @fields == nil ) super( key, value ) elsif( @fields.has_key?( key.downcase ) ) super( @fields[ key.downcase ], value ) else raise( P4Exception, "Invalid field: #{key}" ) end end # # Return the list of the fields that are permitted in this spec # def permitted_fields @fields.values end # # Implement accessor methods for the fields in the spec. The accessor # methods are all prefixed with '_' to avoid conflicts with the Hash # class' namespace. This is a little ugly, but we gain a lot by # subclassing Hash so it's worth it. # def method_missing( m, *a ) k = m.to_s.downcase # Check if we're being asked for 'to_ary'. If so, raise 'NoMethodError'. raise NoMethodError if( k == "to_ary" ) if( k[0..0] != "_" ) raise( RuntimeError, "undefined method `#{m.to_s}' for object of " + "class #{self.class.to_s}" ) end k = k[ 1..-1 ] if( k =~ /(.*)=$/ ) if( a.length() == 0 ) raise( P4Exception, "Method P4##{m} requires an argument" ); end k = $1 if( @fields == nil || @fields.has_key?( k ) ) return self[ @fields[ k ] ] = a.shift end elsif( self.has_key?( m.to_s ) ) return self[ m.to_s ] elsif( @fields.has_key?( k ) ) return self[ @fields[ k ] ] end raise( P4Exception, "Invalid field: #{$1}" ) end end #***************************************************************************** #* P4::MergeInfo class #***************************************************************************** class MergeInfo def initialize( base, yours, theirs, merged, hint ) @base = base @yours = yours @theirs = theirs @merged = merged @hint = hint end attr_reader :base, :yours, :theirs, :merged, :hint end #***************************************************************************** # P4::Integration class # P4::Integration objects hold details about the integrations that have # been performed on a particular revision. Used primarily with the # P4::Revision class #***************************************************************************** class Integration def initialize( how, file, srev, erev ) @how = how @file = file @srev = srev @erev = erev end attr_reader :how, :file, :srev, :erev end #***************************************************************************** # P4::Revision class # Each P4::Revision object holds details about a particular revision # of a file. It may also contain the history of any integrations # to/from the file #***************************************************************************** class Revision def initialize( depotFile ) @depot_file = depotFile @integrations = Array.new @attributes = Hash.new end attr_reader :depot_file attr_accessor :integrations def integration( how, file, srev, erev ) rec = P4::Integration.new( how, file, srev, erev ) @integrations.push( rec ) return rec end def each_integration @integrations.each { |i| yield( i ) } end def set_attribute( name, value ) name = name.downcase if( value =~ /^\d+$/ ) @attributes[ name ] = value.to_i else @attributes[ name ] = value end end # Define #type and #type= explicitly as they clash with the # deprecated Object#type. As it is deprecated, this clash should # disappear in time. def type @attributes[ 'type' ] end def type=( t ) @attributes[ 'type' ] = t end # # Generic getters and setters for revision attributes. # def method_missing( m, *a ) k = m.to_s.downcase if( k =~ /(.*)=$/ ) if( a.length() == 0 ) raise( P4Exception, "Method P4##{m} requires an argument" ); end k = $1 @attributes[ k ] = a.shift else @attributes[ k ] end end end #***************************************************************************** # P4::DepotFile class. # Each DepotFile entry contains details about one depot file. #***************************************************************************** class DepotFile def initialize( name ) @depot_file = name @revisions = Array.new @headAction = @head_type = @head_time = @head_rev = @head_change = nil end attr_reader :depot_file, :revisions attr_accessor :head_action, :head_type, :head_time, :head_rev, :head_change def new_revision r = P4::Revision.new( @depot_file ) @revisions.push( r ) return r end def each_revision @revisions.each { |r| yield( r ) } end end #***************************************************************************** # P4::OutputHandler class. # Base class for all Handler classes that can be passed to P4::handler. #***************************************************************************** class OutputHandler def outputStat(stat) REPORT end def outputInfo(info) REPORT end def outputText(text) REPORT end def outputBinary(binary) REPORT end def outputMessage(message) REPORT end end class ReportHandler < OutputHandler def outputStat(stat) p "stat:", stat HANDLED end def outputInfo(info) p "info:", info HANDLED end def outputText(text) p "text:", text HANDLED end def outputBinary(binary) p "binary:", binary HANDLED end def outputMessage(message) p "message:", message HANDLED end end end # class P4
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#31 | 14719 | tjuricek |
Mirroring the current state of the workshop. From this point, we will try to rebuild the history of p4-ruby in the workshop from this codeline. |
||
#30 | 14718 | tony |
Make P4Ruby aware that a charset of "none" means no charset at all. Previously, using a P4Ruby >= 2014.2 against a server at least as new could result in getting 'Unicode clients require a unicode-enabled server' errors in appropriately. This was because we were treating 'none' as a character set and enabling unicode mode on the client with that as the charset to use for file content. With the advent of .p4enviro files, this problem has been cropping up frequently as that is the default value supplied when talking to a non-unicode server. With this change, we now detect 'none' and use it to disable translation as the user, and .p4enviro file no doubt intended. |
||
#29 | 14716 | tjuricek |
2014.2.0.pre5 - Clearing the charset (calling ClientApi::SetTrans(0)) if the charset property is nil or none during construction. Changed README to use the correct incantation of --with-p4api-dir. Additionally, fixed an issue using that option in lieu of the ftp.perforce.com download. Also, removing any embedded distribution of the p4api. RubyGems sets a strict file size limit, which means we won't be able to distribute the C++ API embedded through their site. Imported from Git Author: Tristan Juricek <tjuricek@perforce.com> 1423518911 -0800 Committer: Tristan Juricek <tjuricek@perforce.com> 1423518911 -0800 sha1: 90ef9f83b0f53ac88223636c0ad653ab5b00e528 push-state: complete parent-changes: d10c4cae76976e7ca616cf17e116c9a16994236a=[999733] |
||
#28 | 14711 | tjuricek |
Clear the charset setting by setting it to nil in ruby-land if the charset is detected to be 'none'. If the user happens to have set the value to 'none' in a config file, or it's otherwise specified, it appears the underlying charset detection mechanism in the C++ API treats it as an encoding. So, by setting it to 'nil' directly in the ruby code, we'll make the correct call to SetCharset(0) as the user probably intends. P4RUBY-179 Imported from Git Author: Tristan Juricek <tjuricek@perforce.com> 1423002926 -0800 Committer: Tristan Juricek <tjuricek@perforce.com> 1423002926 -0800 sha1: f7591d8f78483b9872504cc77e1e193b3fae7419 push-state: incomplete parent-changes: 9ce17f3ec56131a622187697d628bbb46263a30e=[998344] |
||
#27 | 14703 | tjuricek |
Set up call to 'rake cross native gem' as the main build step now. This utilizes the 'cross compile' feature where we can build multiple versions of ruby under one gem package, though it's really going to be used for 'direct compilation'. The following variables need to be set to run the tools/build_p4ruby.sh now: * RUBY_USE_VERSION - Should be the rvm version with the gem for publishing to geminabox * RUBY_CC_VERSION - The colon (:) delimited string of ruby versions to build - each version should be installed via RVM and registered in ~/.rake_compiler/config.yml * P4RUBY_CROSS_PLATFORM - The platform ID we are building on, needs to be set, e.g., 'x86_64-linux', 'i686-linux', 'x86_64-darwin-11'. Note that OS X uses the darwin 'version'. P4RUBY-176 Imported from Git Author: Tristan Juricek <tjuricek@perforce.com> 1421184895 -0800 Committer: Tristan Juricek <tjuricek@perforce.com> 1421184895 -0800 sha1: 1e9e81f882ba0584a7bc66a48637a6576aee7cb9 push-state: complete parent-changes: 50a9ca3b8ecb1e77ba823cbde20a7c89bd731d86=[984317] |
||
#26 | 14682 | Git Fusion |
Git Fusion branch management Imported from Git ghost-of-change-num: 960958 ghost-of-sha1: 005052ae424bd69f426f7209e741ca1c8c3253c7 ghost-precedes-sha1: ad052c71a568ef12165e143a6866ad9ceffbb4a1 parent-branch: None@960958 push-state: incomplete |
||
#25 | 14679 | tony |
Fix p4ruby test run so it also includes the current directory in the library search path. This helps us pick up the P4.so we're testing. Also fixed some minor gripes and backed out a previous change that obviously didn't work under 1.8 |
||
#24 | 14676 | tony |
Rework P4Ruby unit tests so they they are actually units. Now the test order is irrelevant as all tests are standalone. Tidied up the code formatting as well and removed all the tabs from the ruby sources files. Added a modeline for vim users so consistent indentation will be used. |
||
#23 | 14652 | jmistry |
YAC to P4#run_tickets Change in format to return an array of keyed hashes. For example: { 'Ticket' => 'D6EBA4584B635E19EA579E33EB0195DA', 'User' => 'pallen', 'Host' => 'localhost:2003' } |
||
#22 | 14650 | jmistry |
Progress indicator for P4Ruby. There is a new class P4::Progress that is set up to be subclassed by a user. It has the following interface and P4Ruby expects the following class methods to be defined by the user (even if it's an empty implementation): class Progress: def init(type) end def description(description, units ) end def total( total ) end def update( position ) end def done( fail ) end end Users need to create a subclass of P4::Progress and assign an instance to P4 to enable the progress indicator: class MyProgress < P4::Progress def update(pos): # do something with the value here # other methods p4 = P4.new p4.progress = MyProgress.new New feature to be documented in the release notes. |
||
#21 | 14648 | jmistry |
Follow-on to change 500964 Forgot to submit unit test updates. Also, instead of returning nil for a directory or non-existent file, it seems more consistent to return an empty array. |
||
#20 | 14647 | jmistry |
rename to P4#run_tickets Also, instead of each line being an element in the array, the array contains a single Hash, with each ticket entry as a separate element in the hash. |
||
#19 | 14645 | jmistry |
Ensure iterator args are passed on Forgot to pass on any arguments that the user may have supplied to their call to 'each_<spec>'. Fixed this and also added a test for it. |
||
#18 | 14644 | jmistry |
Generic each_* methods Simple method to iterate over a particular type of spec This is a convenient wrapper for the pattern: clients = p4.run_clients clients.each do |c| client = p4.fetch_client( c['client'] ) <do something with spec> end NOTE: It's not possible to implicitly pass a block to a delegate method, so I've implemented it here directly. Could use Proc.new.call, but it looks like there is a serious performance impact with that method. job056520 : spec iterator implementation |
||
#17 | 14643 | jmistry |
Implement P4#tickets for P4Ruby P4#tickets checks P4#ticket_file, if it's a directory or does not exist it just returns 'nil'. Otherwise it iterates over the file and inserts each line into an array of hashes. Each hash is a single ticket entry: key: ticket key (hostname:port=user) value: ticket value Update unit test to test new functionality. |
||
#16 | 14605 | jmistry |
Fix P4.run_submit( P4::Spec ) Ruby 1.9 changed Array.flatten, so that it called 'to_ary'. This caused problems for P4Ruby (with Ruby 1.9) and would cause P4.run_submit, P4.run_shelve, etc to fail with: `method_missing': undefined method `to_ary' for object of class P4::Spec (RuntimeError) if it was passed a P4::Spec object as an argument. P4::Spec now checks (in 'method_missing') if it's trying to run 'to_ary', and it raises 'NoMethodError' if it is. |
||
#15 | 14593 | Sven Erik Knop |
P4Ruby implementation of OutputHandler. Also, debug is now treated as a normal attribute and can be read. Test cases still missing. New functionality, to be documented in release notes. |
||
#14 | 14585 | Sven Erik Knop |
Added P4#run_shelve and P4#delete_shelve as special cases - similar to P4Python. P4#run_shelve allows passing in of a hash, assumed to be a changelist (i.e shelvelist) spec, similar to P4#run_submit. P4#delete_shelve adds an extra "-c" to the arguments before the shelve list number if "-c" is not already in the argument list. User-visible changes to be documented in the release notes. |
||
#13 | 14579 | tony |
Make new class P4::Message for returning Error objects to the user. Currently handles errors and warnings, but could potentially be used for output too (might bloat people's code though). Essentially, if you're using a 2010.2 or later client, or if you've set your api_level to 68 or higher, the P4#errors and P4#warnings arrays will be populated with P4::Message objects instead of strings. Users of older API's, or those who set their api_level to 67 or lower in their scripts will get the old behaviour. P4::Message objects have the following methods: severity() - returns the severity generic() - returns the generic code to_s() - converts the message to a string inspect() - returns a string showing the message details. User-visible enhancement documented in p4rubynotes.txt |
||
#12 | 14565 | tony |
Add P4#inspect method so you get some information about the object when using irb. User-visible change, not documented anywhere (unsupported). |
||
#11 | 14541 | tony |
Copyright notice housekeeping: update all notices to 2008, and correct start date from 1997 to 2001 when P4Ruby was first released from the public depot. No functional change |
||
#10 | 14529 | tony |
Pull 2007.3 p4-ruby changes back to main. Integration only change |
||
#9 | 14521 | tony | Update copyright notices in all applicable P4Ruby files. | ||
#8 | 14515 | tony |
Make P4::Revision attributes numbers if they're entirely composed of numbers (saves the user doing it). |
||
#7 | 14514 | tony |
Rename P4Ruby's P4DepotFile, P4Revision, and P4Integration classes to be P4::DepotFile, P4::Revision and P4::Integration respectively. Also changed P4Ruby's P4::Revision class to store arbitrary attributes of revisions, which should help with server compatibility. Note that P4Perl's already did that, so this just ports those changes over. Also, changed the method name in P4Perl's class from P4::Revision::Set() to P4::Revision::SetAttribute() as that's a better name for it. P4Ruby's equivalent is called P4::Revision#set_attribute() User-visible change to be documented in Scripting Interfaces Guide |
||
#6 | 14506 | tony |
Fix old call to exception_level? that should have been changed to 'exception_level' a while back. Bug fix to previous unreleased change |
||
#5 | 14493 | tony |
Turn on tagged mode by default, and make parse_forms mode always on (it only works when tagged mode is on too). Now users can turn tagged mode off if they want to by calling: p4.tagged = false and turn it back on by calling: p4.tagged = true You can test the current state of affairs using: p4.tagged? User-visible change to be documented in Scripting Interface Guide |
||
#4 | 14492 | tony |
Rename P4#input to P4#input=, and fix all pre-existing calls. The main existing callers are p4.run_password, p4.run_submit and and p4.run_login. There was also a bug with p4.run_password() which meant that you couldn't change a user's password if they hadn't already set one. Fixed that while I was there and added a test case to check that password setting, use and clearing works. |
||
#3 | 14490 | tony |
Rename P4#submit_spec to P4#run_submit. So now run_submit can take a variety of arguments, but if any of them are Hash or P4::Spec objects then they get converted into strings and a '-i' gets added to the submit args. |
||
#2 | 14483 | tony |
Method name rationalisation, part 1. All the methods with names ending with '?' that do not return booleans now have the '?' dropped. This will be used to ensure consistency across the scripting interfaces. Added P4#prog() -> <string> to partner P4#prog=( <string> ) Removed some redundant aliases that we're dropping support for in future versions |
||
#1 | 14480 | tony |
Add P4Ruby 1.5944 to main as start-point for the first productized release of P4Ruby |