# p4unknown.rbw
# Task: determine which files need to be "p4 add'ed." and offer options to do add.
#
# Expects parameters:
# -p $p -c $c -u $u -a "%D"
# Note that %D is depot syntax for current selected file or directory.
#
# num of calls to 'p4': 3 or 4 (for add)
# status: tested on Darwin Mac OS X using P4Ruby API
# R Cowham - converted to work fine on Windows
#
# Based on the original by Jeff Bowles which was:
# Copyright 2004 Perforce Corporation, Inc. All rights reserved.
# Changes Copyright 2005 Robert Cowham, MIT License
require "P4"
require 'getoptlong'
require "find"
require 'fox14'
include Fox
def convert_paths(arr)
if RUBY_PLATFORM.match("win32")
arr.collect! {|e| e.tr('/', '\\')}
else
arr.collect! {|e| e.tr('\\', '/')}
end
end
verbose = false
defaultPort = nil
defaultUser = nil
defaultClient = nil
options = GetoptLong.new(
[ '--verbose', '-v', GetoptLong::NO_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"
verbose = 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
file_args = ARGV
p4 = P4.new
p4.port = defaultPort if defaultPort != nil
p4.user = defaultUser if defaultUser != nil
p4.client = defaultClient if defaultClient != nil
p4.tagged
p4.parse_forms
p4.exception_level = 1
p4.connect
class FileMainWindow < FXMainWindow
def initialize(anApp, p4, search_root, files)
# Initialize base class first
super(anApp, "Files Present in Client Workspace directories", nil, nil, DECOR_ALL, 0, 0, 400, 300)
buttons = FXHorizontalFrame.new(self, LAYOUT_SIDE_BOTTOM|LAYOUT_FILL_X|PACK_UNIFORM_WIDTH)
# Place the list in a sunken frame
sunkenFrame = FXVerticalFrame.new(self, LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_SUNKEN|FRAME_THICK,
0, 0, 0, 0, 0, 0, 0, 0)
fileList = FXList.new(sunkenFrame, nil, 0, LIST_EXTENDEDSELECT|LAYOUT_FILL_X|LAYOUT_FILL_Y)
addBtn = FXButton.new(buttons, "&Add to Perforce")
cancelBtn = FXButton.new(buttons, "&Close")
addBtn.connect(SEL_COMMAND) do |sender, selector, data|
files = Array.new
fileList.each { |item|
files << item.getText() if item.isSelected()
}
#-----------------------------------------------------------
# call to P4: 'p4 where'
#-----------------------------------------------------------
p4.run_add(files)
exit
end
cancelBtn.connect(SEL_COMMAND) {exit}
fileList.appendItem("Search root: #{search_root}")
fileList.appendItem("List of files present in workspace, but unknown to Perforce:")
files.each do |file|
fileList.appendItem(file)
end
fileList.appendItem("Total files: #{files.size}")
end
def create
super
show(PLACEMENT_SCREEN)
end
end
begin
#-----------------------------------------------------------
# call to P4: 'p4 client -o'
#-----------------------------------------------------------
cl_spec = p4.fetch_client
cl_name = cl_spec['Client']
cl_root = cl_spec['Root']
search_root = cl_root
if file_args
print "File args: '#{file_args}'\n" if verbose
# We need to translate Depot syntax into local syntax.
#-----------------------------------------------------------
# call to P4: 'p4 where //depot/search/path/...'
#-----------------------------------------------------------
where = p4.run_where(file_args)[0]
print "Where #{where}\n" if verbose
search_root = where['path'].strip
print "Search root: '#{search_root}'\n" if verbose
# Remove trailing directory slash and ellipsis
if search_root =~ /[\\\/]\.\.\.$/
search_root = search_root[0..search_root.size - 5]
end
print "Search root: '#{search_root}'\n" if verbose
end
#-----------------------------------------------------------
# call to P4: 'p4 fstat //myclient/...'
#-----------------------------------------------------------
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.
#
allFilesPerforce = ret.collect { |r| r['clientFile'] }
allFilesPresent = []
Find.find(search_root) do |f|
Find.prune if f == "." || f == ".."
allFilesPresent << f if File.stat(f).file?
end
convert_paths(allFilesPresent)
convert_paths(allFilesPerforce)
newFiles = (allFilesPresent - allFilesPerforce)
FXApp.new("P4Unknown", "FXRuby") do |theApp|
FileMainWindow.new(theApp, p4, search_root, newFiles)
theApp.create
theApp.run
end
rescue P4Exception
p4.errors.each { |e| $stderr.puts( e ) }
raise
rescue
p4.errors.each { |e| $stderr.puts( e ) }
raise
end
p4.disconnect