XcodePerforcePlugin.swift #10

  • //
  • guest/
  • jaime_rios/
  • XcodePerforcePlugin/
  • XcodePerforcePlugin/
  • XcodePerforcePlugin.swift
  • View
  • Commits
  • Open Download .zip Download (12 KB)
// Created by Jaime O. Rios

import AppKit

var sharedPlugin: XcodePerforcePlugin?

class XcodePerforcePlugin: NSObject
{
    
    var bundle: NSBundle
    var p4Functionatlity: P4Functionality = P4Functionality()
    var pathForIconResource: NSString?
    var p4Icon: NSImage?

    init(bundle: NSBundle)
    {
        self.bundle = bundle

        super.init()
    
        let myPlugin = NSBundle(forClass: XcodePerforcePlugin.self)
        pathForIconResource = myPlugin.pathForResource("plugin_icons", ofType:"icns")
        
        if pathForIconResource != nil
        {
            p4Icon = NSImage(contentsOfFile: pathForIconResource! as String)
        }
        
        createMenuItems()
    }

    deinit
    {
        NSNotificationCenter.defaultCenter().removeObserver(self)
    }

    func createMenuItems()
    {
        // Under 6.3.2, mainMenu is not available at startup
        dispatch_async(dispatch_get_main_queue()) {
            let mainMenu : NSMenu? = NSApp.mainMenu

            let item = mainMenu?.itemWithTitle("Source Control")
            
            if item != nil
            {
                self.p4SettingsSetUpMenu(item)
                self.p4InfoSetUpMenu(item)
                self.p4EditSetUpMenu(item)
                self.p4AddSetUpMenu(item)
                self.p4RevertSetUpMenu(item)
                self.p4vcSubmitSetUpMenu(item)
                self.p4vcRevGraphSetUpMenu(item)
                self.p4vcTimeLapseSetUpMenu(item)
                //p4MergeDiffSetUpMenu(item)
            }
        }
    }

    func p4SettingsSetUpMenu(let item : NSMenuItem?)
    {
        let menuItem = NSMenuItem(title:"Perforce plugin settings", action:"p4Settings", keyEquivalent:"")
        menuItem.target = self
        item!.submenu!.addItem(NSMenuItem.separatorItem())
        item!.submenu!.addItem(menuItem)
    }
    
    func p4Settings()
    {
        p4Functionatlity.checkSettings()
        var attr          = p4Functionatlity.p4Installed

        let p4Installed   = String("p4 installed: \t" + (attr ? "YES": "NO") + "\n")

        var value         = p4Functionatlity.p4Path
        var valueStr      = (value != nil ? value : "Unknown")
        let p4Path        = String("p4 path: \t\t" + valueStr! + "\n")

        attr              = p4Functionatlity.p4vcInstalled
        let p4vcInstalled = String("p4vc installed: \t" + (attr ? "YES": "NO") + "\n")

        value             = p4Functionatlity.p4vcPath
        valueStr          = (value != nil ? value : "Unknown")
        let p4vcPath      = String("p4vc path: \t" + valueStr! + "\n")

        attr              = p4Functionatlity.P4CONFIG_Set
        let p4ConfigSet   = String("P4CONFIG set: " + (attr ? "YES": "NO") + "\n")

        value             = p4Functionatlity.p4ClientName
        let p4ClientName  = String("P4CLIENT name: " + value! + "\n")
        
        let combinedString = p4Installed + p4Path + p4vcInstalled + p4vcPath + p4ConfigSet + p4ClientName
        displayCustomAlertBox("Perforce plugin settings", informativeText: combinedString)
    }
    
    
    // MARK: - p4 commands
    func p4EditSetUpMenu(let item : NSMenuItem?)
    {
        let menuItem    = NSMenuItem(title:"p4 - edit", action:"p4Edit", keyEquivalent:"")
        menuItem.target = self
        item!.submenu!.addItem(menuItem)
    }
    
    /**
    Precondition(s):
    - valid filepath
    - p4 command line app installed
    - P4CONFIG environment variable set
    */
    func p4Edit()
    {
        let currentDoc = getCurrentXcodeDocumentURL()
        if currentDoc.result == false
        {
            return
        }
        
        if p4Functionatlity.p4ClientSet() == true
        {
            let filePath             = currentDoc.document!.path
            let resultMessage        = p4Functionatlity.issueP4EditForFile(filePath!)
            displayCustomAlertBox("p4 edit", informativeText: resultMessage)
        }
        else
        {
            displayDefaultP4NotSetError()
        }
    }
    
    func p4AddSetUpMenu(let item : NSMenuItem?)
    {
        let menuItem = NSMenuItem(title:"p4 - add", action:"p4Add", keyEquivalent:"")
        menuItem.target = self
        item!.submenu!.addItem(menuItem)
    }
    
    func p4Add()
    {
        let currentDoc = getCurrentXcodeDocumentURL()
        if currentDoc.result == false
        {
            return
        }
        
        if p4Functionatlity.p4ClientSet() == true
        {
            let filePath             = currentDoc.document!.path
            let resultMessage        = p4Functionatlity.issueP4AddForFile(filePath!)

            displayCustomAlertBox("p4 add", informativeText: resultMessage)
        }
        else
        {
            displayDefaultP4NotSetError()
        }
    }
    
    func p4RevertSetUpMenu(let item : NSMenuItem?)
    {
        let menuItem = NSMenuItem(title:"p4 - revert", action:"p4Revert", keyEquivalent:"")
        menuItem.target = self
        item!.submenu!.addItem(menuItem)
    }
    
    func p4Revert()
    {
        let currentDoc = getCurrentXcodeDocumentURL()
        if currentDoc.result == false
        {
            return
        }
        
        if p4Functionatlity.p4ClientSet() == true
        {
            let filePath             = currentDoc.document!.path
            let resultMessage        = p4Functionatlity.issueP4RevertForFile(filePath!)
            displayCustomAlertBox("p4 revert", informativeText: resultMessage)
        }
        else
        {
            displayDefaultP4NotSetError()
        }
    }
    
    func p4InfoSetUpMenu(let item : NSMenuItem?)
    {
        let menuItem = NSMenuItem(title:"p4 - info", action:"p4Info", keyEquivalent:"")
        menuItem.target = self
        item!.submenu!.addItem(menuItem)
    }
    
    /**
    Precondition(s):
    - Plugin is able to query the current file that is in focus within
    Xcode 
    -- The parent folder is used as part of the 'p4 info' command call
    
    Postcondition(s):
    - p4 info message for current file's parent folder
    
    */
    func p4Info()
    {
        let currentDoc = getCurrentXcodeDocumentURL()
        if currentDoc.result == false
        {
            return
        }
        
        if p4Functionatlity.p4ClientSet() == true
        {
            let filePath             = (currentDoc.document?.path as NSString?)
            let parentFolder         = filePath!.stringByDeletingLastPathComponent
            var resultMessage        = p4Functionatlity.issueP4InfoForFolder(parentFolder)
            
            if resultMessage.isEmpty
            {
                resultMessage = "Error detected while attempting to query p4 info"
            }
            
            displayCustomAlertBox("p4 info", informativeText: resultMessage)
        }
        else
        {
            displayDefaultP4NotSetError()
        }
    }
    
    // MARK: - p4vc commands
    
    func p4vcSubmitSetUpMenu(let item : NSMenuItem?)
    {
        let menuItem = NSMenuItem(title:"p4vc - submit", action:"p4vcSubmit", keyEquivalent:"")
        menuItem.target = self
        item!.submenu!.addItem(menuItem)
    }
    
    func p4vcSubmit()
    {
        // p4vc submit
    }
    
    func p4vcRevGraphSetUpMenu(let item : NSMenuItem?)
    {
        let menuItem = NSMenuItem(title:"p4vc - revgraph", action:"p4vcRevGraph", keyEquivalent:"")
        menuItem.target = self
        item!.submenu!.addItem(menuItem)
    }
    
    func p4vcRevGraph()
    {
        let currentDoc = getCurrentXcodeDocumentURL()
        if(currentDoc.result == false)
        {
            return
        }
        
        if (p4Functionatlity.p4ClientSet() == true && p4Functionatlity.p4vcInstalled == true)
        {
            let filePath : NSString! = (currentDoc.document?.path as NSString?)
            let parentFolder  = filePath!.stringByDeletingLastPathComponent

            let p4InfoErr     = p4Functionatlity.issueP4InfoForFolder(parentFolder)
            var resultMessage = "Unable to connect to perforce server"
            
            if p4InfoErr.isEmpty == false
            {
                resultMessage = p4Functionatlity.displayP4VCRevGraphForFileAtPath(filePath! as String)
            }
            
            if resultMessage.isEmpty == false
            {
                displayCustomAlertBox("p4vc revgraph", informativeText: resultMessage)
            }
        }
        else
        {
            displayDefaultP4NotSetError()
        }
    }
    
    func p4vcTimeLapseSetUpMenu(let item : NSMenuItem?)
    {
        let menuItem = NSMenuItem(title:"p4vc - timelapse", action:"p4vcTimeLapse", keyEquivalent:"")
        menuItem.target = self
        item!.submenu!.addItem(menuItem)
    }
    
    func p4vcTimeLapse()
    {
        let currentDoc = getCurrentXcodeDocumentURL()
        if currentDoc.result == false
        {
            return
        }
        
        if p4Functionatlity.p4ClientSet() == true && p4Functionatlity.p4vcInstalled == true
        {
            let filePath      = (currentDoc.document?.path as NSString?)
            let parentFolder  = filePath?.stringByDeletingLastPathComponent
            
            let p4InfoErr     = p4Functionatlity.issueP4InfoForFolder(parentFolder!)
            var resultMessage = "Unable to connect to perforce server"
            
            if(p4InfoErr.isEmpty == false)
            {
                resultMessage = p4Functionatlity.displayP4VCTimeLapseForFileAtPath(filePath! as String)
            }
            
            if(resultMessage.isEmpty == false)
            {
                displayCustomAlertBox("p4vc revgraph", informativeText: resultMessage)
            }
        }
        else
        {
            displayDefaultP4NotSetError()
        }
    }
    
    // MARK: - p4merge commands
    
    func p4MergeDiffSetUpMenu(let item : NSMenuItem?)
    {
        let menuItem = NSMenuItem(title:"p4merge - diff", action:"p4MergeDiff", keyEquivalent:"")
        menuItem.target = self
        item!.submenu!.addItem(menuItem)
    }
    
    func p4MergeDiff()
    {
        
    }
    
    // MARK: - misc
    
    func getCurrentXcodeDocumentURL() -> (result:Bool, document:NSURL?)
    {
        var result = false
        let currentXcodeDocURL = P4XcodeHelper.currentSourceCodeDocumentURL()
        
        if currentXcodeDocURL != nil
        {
            result = true
        }
        else
        {
            let alertBox             = NSAlert()
            alertBox.messageText     = "Error"
            alertBox.informativeText = "Unable to acquire a valid file path from Xcode"
            alertBox.runModal()
            
            displayCustomAlertBox("Error", informativeText: "Unable to acquire a valid file path from Xcode")
        }
        
        return (result, currentXcodeDocURL)
    }
    
    func displayDefaultP4NotSetError()
    {
        var errorMessage = ""
        if p4Functionatlity.p4Installed == false
        {
            errorMessage = "The p4 command line app is not installed"
        }
        
        if p4Functionatlity.p4vcInstalled == false
        {
            if errorMessage.isEmpty == false
            {
                errorMessage += "\n"
            }
            
            errorMessage += "The p4vc command line app is not installed"
        }
        
        if p4Functionatlity.P4CONFIG_Set == false
        {
            if errorMessage.isEmpty == false
            {
                errorMessage += "\n"
            }
            
            errorMessage += "The P4CONFIG environment variable is not set"
        }
        
        displayCustomAlertBox("Error", informativeText: errorMessage)
    }
    
    func displayCustomAlertBox(messageText:NSString?, informativeText:NSString?)
    {
        let alertBox             = NSAlert()
        alertBox.messageText     = (messageText as! String)
        alertBox.informativeText = (informativeText as! String)

        if p4Icon != nil
        {
            alertBox.icon = p4Icon
        }
        alertBox.runModal()
    }
}

# Change User Description Committed
#12 20141 Jaime Rios Merging using M_robc_apple-to_jaime_rios_XcodePerforcePlugin
#11 19863 Jaime Rios Fixed warning generated by Xcode regarding deprecated selector call usage in Swift
#10 15948 Jaime Rios Added p4vc submit functionality; violated rule 0; updated plist for xcode 7 uuid; fixed errors encountered by xcode related to optionals and interoperability with Obj-C++ code.
#9 15115 Jaime Rios Modified plist for Xcode 6.4 and Xcode 7 Beta; updated code changes in Swift; added notes about UUID for self.
#8 13723 Jaime Rios Fixed problem with menu items not being created because mainMenu is not available at startup for Xcode 6.3.2.
#7 13687 Jaime Rios Added Xcode 6.3.2 support; minor editing changes; fixes for Swift compiler errors.
#6 12123 Jaime Rios Added compatibility for Xcode 6.2; modified the menu layout; added additional screenshot; updated URL for Alcatraz Package Manager.
#5 11740 Jaime Rios Updated readme text with additional known issues; refactored p4 revert function; added perforce icon to alert message.
#4 11739 Jaime Rios Merging

//guest/matt_attaway/XcodePerforcePlugin/...

to //guest/jaime_rios/XcodePerforcePlugin/...
#3 11734 Jaime Rios Modified p4vc functions in Swift code to only show a dialog box if there is an error.
#2 11733 Jaime Rios Refactored code to have more functionality within Swift code; fixed perforce connection bugs.
#1 11694 Jaime Rios Initial add of XcodePerforcePlugin project to guest depot.