p4unknown.rb #2

  • //
  • guest/
  • robert_cowham/
  • perforce/
  • utils/
  • p4gui/
  • p4unknown.rb
  • View
  • Commits
  • Open Download .zip Download (6 KB)
# 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

# Change User Description Committed
#2 5187 Robert Cowham Tidy up.
#1 5182 Robert Cowham Added new tool and links.