module Commands
Public Class Methods
download(options=nil)
click to toggle source
TODO the p4ruby extconf.rb file mechanism has some logic to search the ftp site for things. We might also want to use HTTP
# File lib/commands/download.rb, line 10 def Commands.download(options=nil) version = 'r14.2' binary = 'p4d' if options and options.params and !options.params.empty? op = OptionParser.new do |op| op.on('-v VERSION', '--version VERSION', 'ftp.perforce.com version') do |v| version = v end end op.parse!(options.params) if !options.params.empty? binary = options.params.first end end case binary when 'p4' download_p4_via_ftp(version) when 'p4d' download_p4d_via_ftp(version) when 'p4api' download_p4api_via_ftp(version) else raise "Don't know how to download #{binary}, check 'p4util help download'" end end
help(options)
click to toggle source
# File lib/commands/help.rb, line 4 def Commands.help(options) if !options.params.empty? && Commands.respond_to?(options.params.first.to_sym) method_name = "print_#{options.params.first}_help".to_sym Commands.method(method_name).call() else print_general_help end end
init(options=nil)
click to toggle source
# File lib/commands/init.rb, line 14 def Commands.init(options=nil) init_dir = 'p4init' p4port = '127.0.0.1:1666' version = nil auto = false if options and !options.params.empty? op = OptionParser.new do |op| op.on('-p PORT', '--port PORT', 'P4PORT setting') { |x| p4port = x } op.on('-a', '--auto', 'Force charset to be auto') { |x| auto = true } op.on('-v VERSION', '--version VERSION', 'ftp.perforce.com version') do |v| version = v end end op.parse!(options.params) if !options.params.empty? init_dir = options.params.first end end if options and !options.params.empty? init_dir = options.params.shift end initialize_p4d(init_dir, p4port, auto) end
kill(options=nil)
click to toggle source
# File lib/commands/kill.rb, line 5 def Commands.kill(options=nil) list_process_names.select{|p| p =~ /p4d/}.each do |p| pid = pid_for_process(p) next if pid.nil? begin puts "killing p4d #{p} at #{pid}" Process.kill('TERM', pid) rescue Exception => e puts "Problem killing #{p}: #{e.message}" puts e.backtrace.join('\n') end end is_running = true while is_running is_running = p4d_running? if is_running sleep 0.2 end end end
list_process_names()
click to toggle source
# File lib/commands/util.rb, line 9 def self.list_process_names if OsUtil.osx? or OsUtil.linux? return `ps aux | awk '{print $11}'`.split(/\n/).drop(1) else # TODO investigate using tasklist just for this raise 'No support for windows just yet' end end
p4d_available?(port=':1666')
click to toggle source
# File lib/commands/util.rb, line 31 def Commands.p4d_available?(port=':1666') begin p4 = P4.new p4.port = port p4.connect p4.disconnect true rescue false end end
p4d_running?()
click to toggle source
# File lib/commands/util.rb, line 5 def Commands.p4d_running? list_process_names.select { |p| p =~ /p4d/ }.empty? == false end
pid_for_process(process)
click to toggle source
# File lib/commands/util.rb, line 18 def self.pid_for_process(process) if OsUtil.osx? or OsUtil.linux? line = `ps aux | awk '{print $2,$11}'`.split(/\n/).drop(1).find { |p| p =~ /#{process}/ } unless line.nil? return line.split('\n').first.to_i else return nil end else raise 'NO support for windows yet' end end
print_download_help()
click to toggle source
# File lib/commands/download.rb, line 41 def Commands.print_download_help puts <<-END.gsub(/^ {6}/, '') p4util download [p4|p4d|p4api] Downloads one of the following utilities (in lieu of an installer) into a local /tmp/p4util/ directory. * p4 * p4d * p4api Will default to the r14.2 release. Options: --version X where X looks like the version in the ftp.perforce.com site, e.g., 'r14.2' instead of '2014.2' END end
print_init_help()
click to toggle source
# File lib/commands/init.rb, line 45 def Commands.print_init_help puts <<-END.gsub(/^ {6}/, '') p4util init [-p P4PORT] [-a] [p4_init_dir] Reads definitions in the directory p4_init_dir - by default, just 'p4init' - and then calls methods on a p4d instance assumed to be running locally. This assumes we are basically starting from scratch. If you have an existing p4d instance, it's highly likely your initialization run will fail. Delete your settings and working area and reset. Options: -p P4PORT : Specify p4 port setting, defaults to ':1666' (uses localhost) -a : Force our 'charset' to be 'auto' ## Definition Files ## Files are Ruby scripts, each basically extending a model class defined by this application. Each model type is defined separately later, however, you should have at least one User model that's marked as a super user. If you don't do this, you will always have a super user created with the login 'p4super' and the password 'superuser1A!'. ## Execution Order ## Each model you define has a 'rank'. Models classes generate instances, and each instance is sorted based on this rank. If you specify no rank, or any rank is equivalent, well, you submit your will to the gods of random. The only special model type that does not obey these rules is the SystemSettings model, which is always handled in a very particular order. ## SystemSettingsModel ## Example: class MySystemSettings < SystemSettingsModel # These are default settings @unicode = true @security_level = 0 # By default this is empty, but here's an example of usage @configure_settings = { 'dm.keys.hide' => '2' } end When `unicode` is enabled, this assumes that the `p4util init` command is run in the *same directory* as `p4util start`. ## UserModel ## Example of a super user (you need one): class SuperUser < UserModel @super = true # if you don't set, we'll just use this for the full_name and email @login = 'super' @password = 'superuser1A' end Example of a normal user: class JohnDoeUser < UserModel def rank; 100; end @login = 'jdoe' @full_name = 'John Doe' @email = 'jdoe@example.com' @password = 'johndoe1A!' end Note that with the super user, you don't really need a rank, but with your other models, it's a good idea. (You can mix when users come and go with other changes.) ## ChangelistModel ## Example of a changelist with an add and edit: class Changelist2 < ChangelistModel def rank; 1001 end @description = 'An example add and edit' @user = 'jdoe' @edits = [ FileDefinition.new(:path => 'depot/README.txt', :content => <<-STOP.gsub(/^ {8}/, '') This is an example readme. Added a second line STOP ) ] @adds = [ FileDefinition.new(:path => 'depot/main/project2/example.txt', :local_path => 'p4init/some_text.txt') ] end Note that adds an edits are specified with 'FileDefinition' objects. Each file definition instance can define text content inline, or via a 'local_path' to a file relative to the current working directory. The `@user` is not necessary, but you probably don't want to add everything as your super user, so set this to a UserModel instance that should exist at this point. ## DepotModel ## Example creating a new standard depot: class ProjectDepot < DepotModel def rank 1001 end @depot = 'my_project' @description = 'The My Project depot' end Other attributes that can be set that update the depot spec being written: :type, :address, :suffix, :map, :spec_map ## GroupModel ## Example: class SystemGroup < GroupModel def rank; 2000 end @group = 'system' @timeout = 'unset' @password_timeout = 'unset' @users = ['app'] end Attributes: :group, :max_results, :max_scan_rows, :max_lock_time, :password_timeout, :timeout, :users, :subgroups, :owners ## TriggerModel ## Example: class ExampleTriggers < TriggerModel def rank; 50; end @triggers = [ 'trig1 change-submit //depot/dir/... "/usr/bin/s1.pl %changelist%"', 'trig2 change-submit -//depot/z/... "/usr/bin/s1.pl %user%"' ] end END end
print_kill_help()
click to toggle source
# File lib/commands/kill.rb, line 27 def Commands.print_kill_help puts <<-END.gsub(/^ {6}/,'') p4util kill Finds local p4d processes and kills them. On unix machines, will probably use `ps -x` and 'p4d', then will send SIGTERM signals to each process. END end
print_start_help()
click to toggle source
# File lib/commands/start.rb, line 26 def Commands.print_start_help puts <<-END.gsub(/^ {6}/,'') p4util start Spawns a Perforce process in your local /tmp/p4util/p4droot directory. If the Perforce executable does not exist, will download the binary first. Will try to set up a server log at /tmp/p4util/server.log. It'll be fairly verbose by default; this is *not* intended for any kind of performance testing. END end
rake(options)
click to toggle source
# File lib/commands/rake.rb, line 4 def Commands.rake(options) print_rake_help end
spawn_p4d()
click to toggle source
# File lib/commands/start.rb, line 12 def Commands.spawn_p4d pid = Process.spawn("#{OsUtil.p4d_path} -r #{Conventions.p4droot_dir} "+ "-v server=1 -L #{Conventions.p4d_log_path}") Process.detach(pid) while !p4d_running? sleep 0.2 end while !p4d_available? sleep 0.1 end end
start(options=nil)
click to toggle source
# File lib/commands/start.rb, line 4 def Commands.start(options=nil) if !File.exists?(OsUtil.p4d_path) Commands.download(options) end Conventions.init_p4droot_dir spawn_p4d end
unicode_upgrade()
click to toggle source
# File lib/commands/util.rb, line 43 def Commands.unicode_upgrade system("#{OsUtil.p4d_path} -r #{Conventions.p4droot_dir} "+ "-v server=1 -L #{Conventions.p4d_log_path} " + "-xi") end
version(options)
click to toggle source
# File lib/commands/version.rb, line 6 def Commands.version(options) print_version_help end
Private Class Methods
download_p4_via_ftp(version)
click to toggle source
# File lib/commands/download.rb, line 63 def Commands.download_p4_via_ftp(version) download_via_ftp(version, OsUtil.p4_executable, OsUtil.p4_path) if !File.executable?(OsUtil.p4_path) File.chmod(0755, OsUtil.p4_path) end end
download_p4api_via_ftp(version)
click to toggle source
# File lib/commands/download.rb, line 79 def Commands.download_p4api_via_ftp(version) download_via_ftp(version, OsUtil.p4api_file, OsUtil.p4api_path) # um, probably should expand this guy out end
download_p4d_via_ftp(version)
click to toggle source
# File lib/commands/download.rb, line 71 def Commands.download_p4d_via_ftp(version) download_via_ftp(version, OsUtil.p4d_executable, OsUtil.p4d_path) if !File.executable?(OsUtil.p4d_path) File.chmod(0755, OsUtil.p4d_path) end end
download_via_ftp(version, filename, output_path)
click to toggle source
# File lib/commands/download.rb, line 87 def Commands.download_via_ftp(version, filename, output_path) ftp = Net::FTP.new('ftp.perforce.com') ftp.login dir = OsUtil.ftp_download_dir(version) ftp.chdir(dir) ftp.passive=true Conventions.init_working_dir ftp.getbinaryfile(filename, output_path) ensure ftp.close if ftp and !ftp.closed? end
initialize_p4d(init_dir, p4port, auto)
click to toggle source
# File lib/commands/init.rb, line 208 def Commands.initialize_p4d(init_dir, p4port, auto) # Go through our init_dir, and evaluate each script as if it were defined # in the Commands::Init module. if File.directory?(init_dir) Dir.glob("#{init_dir}/**/*.rb") do |file| contents = IO.read(file) Commands::Init.class_eval(contents, file) end elsif File.file?(init_dir) contents = IO.read(init_dir) Commands::Init.class_eval(contents, init_dir) end # Note that nothing is actually done until this line. This allows classes # to re-define methods and do fancy shit, like, 'oh in security_settings 0 # this guy actually doesn't have a password'. Commands::Init::InitModel.run(p4port, auto) end
print_general_help()
click to toggle source
# File lib/commands/help.rb, line 15 def Commands.print_general_help puts <<-END.gsub(/^ {6}/, '') p4util [command] [params] Executes various commands useful when writing Perforce applications. Use `p4util help [command]` for more information on each command. List of available commands: download - Download Perforce binaries for your platform init - Seed the local p4d instance using local configuration files kill - Shutdown p4d processes using SIGTERM start - Spawn the p4d process in your working directory Additional 'commands' you can use for more information: version - Print the version string rake - Some notes on how to use the Rake tasks END end
print_rake_help()
click to toggle source
# File lib/commands/rake.rb, line 10 def Commands.print_rake_help puts <<-END.gsub(/^ {6}/, '') Use rake to drive p4util commands Example usage in your Rakefile: require 'p4util/tasks' P4Util::Tasks.new do |p4util| p4util.version = 'r14.2' p4util.p4_init_dir = 'spec/init.base' end This defines three tasks for you: * `p4init` - See 'p4util help init' * `p4kill` - See 'p4util help kill' * `p4reset` - Calls p4kill then removes the /tmp/p4util/p4droot folder (This assumes you have installed p4util or setup the p4util gem dependency.) The `version` property specifies the version of p4d to download and run. It mirrors the version directory names of ftp.perforce.com at the moment. The `p4_init_dir` property indicates a directory of ruby scripts that define the script files for the p4util init command. END end
print_version_help()
click to toggle source
# File lib/commands/version.rb, line 12 def Commands.print_version_help puts <<-END.gsub(/^ {6}/, '') p4util #{P4Util::VERSION} END end