# Task: determine which files need to be "p4 add'ed." # # num of calls to 'p4': 2 # status: tested on Darwin Mac OS X using "p4 -R" # # Copyright 2004 Perforce Corporation, Inc. All rights reserved. require "readp4marshal" require 'getoptlong' require "find" verboseOption = false defaultPort = nil defaultUser = nil defaultClient = nil options = GetoptLong.new( [ '--verbose', '-v', GetoptLong::OPTIONAL_ARGUMENT], [ '--user', '-u', GetoptLong::REQUIRED_ARGUMENT], [ '--port', '-p', GetoptLong::REQUIRED_ARGUMENT], [ '--client', '-c', GetoptLong::REQUIRED_ARGUMENT], [ '--help', '-h', GetoptLong::REQUIRED_ARGUMENT], [ '--quiet', '-q', GetoptLong::REQUIRED_ARGUMENT] ) options.each do |opt, arg| case opt when "--verbose" verboseOption = true when "--user" defaultUser = arg when "--client" defaultClient = arg when "--port" defaultPort = arg when "--quiet" puts "'--quiet' not implemented yet." when "--help" puts options.Usage end end p4 = P4Marshal.new("p4port" => defaultPort, "p4user" => defaultUser, "p4client" => defaultClient) #----------------------------------------------------------- # first call to P4: 'p4 client -o' #----------------------------------------------------------- puts "Step 1: Get the client name." cl_spec = p4.run("client", "-o")[0] cl_name = cl_spec['Client'] cl_root = cl_spec['Root'] puts "Ran user-client, output was \"client=#{cl_name}\"" #----------------------------------------------------------- # second call to P4: 'p4 fstat //myclient/...' #----------------------------------------------------------- puts "Step 2: Get the list of Perforce-known files." ret = p4.run("fstat", "//#{cl_name}/...").delete_if { |r| r['headAction'] == 'delete' } # # at this point, we create two arrays to hold # the filenames: # allFilesPerforce - from "p4 fstat //myclient/..." # allFilesPresent - from "Find.find(cl_root)" # we can use set operations for the tricky stuff, and # it's a great advert for Ruby. # # (note that we map the path-separator to be '/', regardless # of platform. Ruby's polite about using '/' everywhere; the # output of "p4 fstat" uses '\' for Windows.) # allFilesPerforce = ret.collect { |r| r['clientFile'].tr('\\', '/') } puts "Step 3: Get the list of files on the local disk." allFilesPresent = [] Find.find(cl_root) do |f| Find.prune if f == "." || f == ".." allFilesPresent << f if File.stat(f).file? end puts "List of files present in workspace, but unknown to Perforce:" puts (allFilesPresent - allFilesPerforce) puts "List of files known to Perforce, but not (yet) synced to workspace:" puts (allFilesPerforce - allFilesPresent)