// 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? class func pluginDidLoad(bundle: NSBundle) { let appName = NSBundle.mainBundle().infoDictionary?["CFBundleName"] as? NSString if appName == "Xcode" { sharedPlugin = XcodePerforcePlugin(bundle: bundle) } } 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!) } createMenuItems() } deinit { NSNotificationCenter.defaultCenter().removeObserver(self) } func createMenuItems() { var item = NSApp.mainMenu!!.itemWithTitle("Source Control") if item != nil { p4SettingsSetUpMenu(item) p4InfoSetUpMenu(item) p4EditSetUpMenu(item) p4AddSetUpMenu(item) p4RevertSetUpMenu(item) p4vcRevGraphSetUpMenu(item) p4vcTimeLapseSetUpMenu(item) //p4MergeDiffSetUpMenu(item) } } func p4SettingsSetUpMenu(let item : NSMenuItem?) { var 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: - func p4EditSetUpMenu(let item : NSMenuItem?) { var 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 = getCurrentXcodeDocument() if(currentDoc.result == false) { return } if (p4Functionatlity.p4ClientSet() == true) { let filePath = currentDoc.document?.fileURL?.path let resultMessage = p4Functionatlity.issueP4EditForFile(filePath) displayCustomAlertBox("p4 edit", informativeText: resultMessage) } else { displayDefaultP4NotSetError() } } func p4AddSetUpMenu(let item : NSMenuItem?) { var menuItem = NSMenuItem(title:"p4 - add", action:"p4Add", keyEquivalent:"") menuItem.target = self item!.submenu!.addItem(menuItem) } func p4Add() { let currentDoc = getCurrentXcodeDocument() if(currentDoc.result == false) { return } if (p4Functionatlity.p4ClientSet() == true) { let filePath = currentDoc.document?.fileURL?.path let resultMessage = p4Functionatlity.issueP4AddForFile(filePath) displayCustomAlertBox("p4 add", informativeText: resultMessage) } else { displayDefaultP4NotSetError() } } func p4RevertSetUpMenu(let item : NSMenuItem?) { var menuItem = NSMenuItem(title:"p4 - revert", action:"p4Revert", keyEquivalent:"") menuItem.target = self item!.submenu!.addItem(menuItem) } func p4Revert() { let currentDoc = getCurrentXcodeDocument() if(currentDoc.result == false) { return } if (p4Functionatlity.p4ClientSet() == true) { let filePath = currentDoc.document?.fileURL?.path let resultMessage = p4Functionatlity.issueP4RevertForFile(filePath) displayCustomAlertBox("p4 revert", informativeText: resultMessage) } else { displayDefaultP4NotSetError() } } func p4InfoSetUpMenu(let item : NSMenuItem?) { var 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 = getCurrentXcodeDocument() if(currentDoc.result == false) { return } if (p4Functionatlity.p4ClientSet() == true) { let filePath = currentDoc.document?.fileURL?.path 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: - func p4vcRevGraphSetUpMenu(let item : NSMenuItem?) { var menuItem = NSMenuItem(title:"p4vc - revgraph", action:"p4vcRevGraph", keyEquivalent:"") menuItem.target = self item!.submenu!.addItem(menuItem) } func p4vcRevGraph() { let currentDoc = getCurrentXcodeDocument() if(currentDoc.result == false) { return } if (p4Functionatlity.p4ClientSet() == true && p4Functionatlity.p4vcInstalled == true) { let filePath = currentDoc.document?.fileURL?.path 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) } if (resultMessage.isEmpty == false) { displayCustomAlertBox("p4vc revgraph", informativeText: resultMessage) } } else { displayDefaultP4NotSetError() } } func p4vcTimeLapseSetUpMenu(let item : NSMenuItem?) { var menuItem = NSMenuItem(title:"p4vc - timelapse", action:"p4vcTimeLapse", keyEquivalent:"") menuItem.target = self item!.submenu!.addItem(menuItem) } func p4vcTimeLapse() { let currentDoc = getCurrentXcodeDocument() if(currentDoc.result == false) { return } if (p4Functionatlity.p4ClientSet() == true && p4Functionatlity.p4vcInstalled == true) { let filePath = currentDoc.document?.fileURL?.path 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) } if(resultMessage.isEmpty == false) { displayCustomAlertBox("p4vc revgraph", informativeText: resultMessage) } } else { displayDefaultP4NotSetError() } } // MARK: - func p4MergeDiffSetUpMenu(let item : NSMenuItem?) { var menuItem = NSMenuItem(title:"p4merge - diff", action:"p4MergeDiff", keyEquivalent:"") menuItem.target = self item!.submenu!.addItem(menuItem) } func p4MergeDiff() { } // MARK: - func getCurrentXcodeDocument() -> (result:Bool, document:IDESourceCodeDocument?) { var result = false let currentXcodeDoc = P4XcodeHelper.currentSourceCodeDocument() if (currentXcodeDoc != nil) { result = true } else { var 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, currentXcodeDoc) } 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?) { var alertBox = NSAlert() alertBox.messageText = messageText alertBox.informativeText = informativeText if(p4Icon != nil) { alertBox.icon = p4Icon } alertBox.runModal() } }