diff --git a/Perforce.py b/Perforce.py index 25b9522..d2bc382 100644 --- a/Perforce.py +++ b/Perforce.py @@ -20,6 +20,7 @@ # global variable used when calling p4 - it stores the path of the file in the current view, used to determine with P4CONFIG to use # whenever a view is selected, the variable gets updated + global_folder = '' class PerforceP4CONFIGHandler(sublime_plugin.EventListener): @@ -331,7 +332,7 @@ def WarnUser(message): perforce_settings = sublime.load_settings('Perforce.sublime-settings') if(perforce_settings.get('perforce_warnings_enabled')): if(perforce_settings.get('perforce_log_warnings_to_status')): - sublime.status_message("Perforce [warning]: {0}".format(message)) + sublime.active_window().status_message("Perforce [warning]: {0}".format(message)) else: print("Perforce [warning]: {0}".format(message)) @@ -666,7 +667,7 @@ def on_done(self, picked): entry = applications.get('applications')[picked] f.close() - sublime.status_message(__name__ + ': Please make sure that {0} is reachable - you might need to restart Sublime Text 2.'.format(entry['exename'])) + self.window.status_message(__name__ + ': Please make sure that {0} is reachable - you might need to restart Sublime Text 2.'.format(entry['exename'])) settings = sublime.load_settings('Perforce.sublime-settings') settings.set('perforce_selectedgraphicaldiffapp', entry['name']) @@ -1068,28 +1069,75 @@ def run(self): class PerforceLogoutCommand(sublime_plugin.WindowCommand): def run(self): try: + command = ConstructCommand("p4 logout") + p = subprocess.Popen(command, stdin=subprocess.PIPE,stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=global_folder, shell=True) + p.communicate() + + # if password authenticated command = ConstructCommand("p4 set P4PASSWD=") p = subprocess.Popen(command, stdin=subprocess.PIPE,stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=global_folder, shell=True) p.communicate() + except ValueError: pass +maskChar = '*' + class PerforceLoginCommand(sublime_plugin.WindowCommand): + inputPanel = None + clearPassword = [] + def run(self): - self.window.show_input_panel("Enter Perforce Password", "", self.on_done, None, None) + # first check if logged in already + user = GetUserFromClientspec() + command = ConstructCommand("p4 login -s {0}".format(user)) + p = subprocess.Popen(command, stdin=subprocess.PIPE,stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=global_folder, shell=True) + p.communicate() + if not p.returncode: + self.window.status_message("{0} already logged in.".format(user)) + return + + self.inputPanel = self.window.show_input_panel("Enter Perforce Password", "", self.on_done, self.on_change, None) + + def isMasked(self, text): + return all(ch == maskChar for ch in text) + + def on_change(self, password): + for i, c in enumerate(password): + if c != maskChar: + self.clearPassword.insert(i, c) + + if self.inputPanel: + # check for cases when user only makes deletions from the fully masked input + if self.isMasked(password) and len(password) < len(self.clearPassword): + sel = self.inputPanel.sel() + if sel: + # get current caret position + pos = sel[0].a + self.clearPassword.pop(pos) + + if not self.isMasked(password): + self.inputPanel.run_command("mask_input") def on_done(self, password): try: - command = ConstructCommand("p4 logout") - p = subprocess.Popen(command, stdin=subprocess.PIPE,stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=global_folder, shell=True) - p.communicate() - #unset var - command = ConstructCommand("p4 set P4PASSWD={0}".format(password)) + command = ConstructCommand("p4 login") p = subprocess.Popen(command, stdin=subprocess.PIPE,stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=global_folder, shell=True) - p.communicate() + p.communicate(input="".join(self.clearPassword).encode('utf-8')) + if p.returncode: + self.window.status_message("login failed.") + else: + self.window.status_message("login successful.") + self.clearPassword.clear() except ValueError: pass +class MaskInputCommand(sublime_plugin.TextCommand): + def run(self, edit): + size = self.view.size() + toBeReplaced = sublime.Region(0, size) + self.view.replace(edit, toBeReplaced, size * maskChar) + class PerforceUnshelveClCommand(sublime_plugin.WindowCommand): def run(self): try: