Konstantin Kabanov avatar Konstantin Kabanov committed 34f57b7

1. new setting "auto_checkout_enabled"
2. bugfix, non-latin file path with spaces
3. bugfix, auto-checkout of files that can not became writable
4. some variable-name refactoring (can be excluded)
5. new context menu item "TFS"

Comments (0)

Files changed (4)

Context.sublime-menu

+[
+    {
+        "caption": "TFS",
+        "mnemonic": "T",
+        "id": "tfs",
+        "children":
+        [
+            { "command": "tfs_checkout", "caption": "Checkout" },
+            { "command": "tfs_undo", "caption": "Undo" },
+            { "command": "tfs_checkin", "caption": "Checkin..." },
+            { "command": "tfs_history", "caption": "History..." },
+            { "command": "tfs_add", "caption": "Add" },
+            { "command": "tfs_get_latest", "caption": "Get latest" },
+            { "command": "tfs_difference", "caption": "Compare with latest..." },
+            { "command": "tfs_delete", "caption": "Delete" },
+            { "command": "tfs_status", "caption": "Status" },
+            { "command": "tfs_annotate", "caption": "Annotate..." }
+        ]
+    }
+]

Main.sublime-menu

         [
             { "command": "tfs_checkout", "caption": "Checkout" },
             { "command": "tfs_undo", "caption": "Undo" },
-            { "command": "tfs_checkin", "caption": "Checkin" },
-            { "command": "tfs_history", "caption": "History" },
+            { "command": "tfs_checkin", "caption": "Checkin..." },
+            { "command": "tfs_history", "caption": "History..." },
             { "command": "tfs_add", "caption": "Add" },
             { "command": "tfs_get_latest", "caption": "Get latest" },
-            { "command": "tfs_difference", "caption": "Compare with latest" },
+            { "command": "tfs_difference", "caption": "Compare with latest..." },
             { "command": "tfs_delete", "caption": "Delete" },
             { "command": "tfs_status", "caption": "Status" },
-            { "command": "tfs_annotate", "caption": "Annotate"}
+            { "command": "tfs_annotate", "caption": "Annotate..." }
         ]
     }
 ]
-import sublime, sublime_plugin, re
+import sublime, sublime_plugin, re
 import threading
+import locale
 import shlex
 import subprocess
 import os
 import stat
 
+def get_unicode_filename(view):
+    return unicode(view.file_name()).encode(locale.getpreferredencoding());
+
 class TfsManager(object):
     def __init__(self):
         self.name = 'sublime_tfs'
         settings = sublime.load_settings('sublime_tfs.sublime-settings')
         self.tf_path = settings.get("tf_path")
         self.tfpt_path = settings.get("tfpt_path")
+        self.auto_checkout_enabled = settings.get("auto_checkout_enabled", True)
         self.cwd = os.path.expandvars('%HOMEDRIVE%\\')
 
-    def is_under_tfs(self, path):
-        return self.status(path)
+    def is_under_tfs(self, p_path):
+        return self.status(p_path)
 
-    def checkout(self, path):
-        return self.run_command("checkout", path)
+    def checkout(self, p_path):
+        if self.auto_checkout_enabled or sublime.ok_cancel_dialog("Checkout " + p_path + "?"):
+            return self.run_command("checkout", p_path)
+        else:
+            return (False, "Checkout is cancelled by user!")
 
-    def checkin(self, path):
-        return self.run_command("checkin", path, True)
+    def checkin(self, p_path):
+        return self.run_command("checkin", p_path, True)
 
-    def undo(self, path):
-        return self.run_command("undo", path)
+    def undo(self, p_path):
+        return self.run_command("undo", p_path)
 
-    def history(self, path):
-        return self.run_command("history", path, True)
+    def history(self, p_path):
+        return self.run_command("history", p_path, True)
 
-    def add(self, path):
-        return self.run_command("add", path)
+    def add(self, p_path):
+        return self.run_command("add", p_path)
 
-    def get_latest(self, path):
-        return self.run_command("get", path)
+    def get_latest(self, p_path):
+        return self.run_command("get", p_path)
 
-    def difference(self, path):
-        return self.run_command("difference", path, True)
+    def difference(self, p_path):
+        return self.run_command("difference", p_path, True)
 
-    def delete(self, path):
-        return self.run_command("delete", path)
+    def delete(self, p_path):
+        return self.run_command("delete", p_path)
 
-    def status(self, path):
-        return self.run_command("status", path)
+    def status(self, p_path):
+        return self.run_command("status", p_path)
 
-    def annotate(self, path):
-        return self.run_command("annotate", path, True, True)
+    def annotate(self, p_path):
+        return self.run_command("annotate", p_path, True, True)
 
-    def auto_checkout(self, path):
-        if self.status(path)[0]:
-            self.checkout(path)
-            return (True, "")
+    def auto_checkout(self, p_path):
+        if self.status(p_path)[0]:
+            return self.checkout(p_path)
         else:
             return (False, "")
 
-    def run_command(self, command, path, is_graph = False, is_tfpt = False):
-        commands = [self.tfpt_path if is_tfpt else self.tf_path, command, path]
+    def run_command(self, command, p_path, is_graph = False, is_tfpt = False):
+        commands = [self.tfpt_path if is_tfpt else self.tf_path, command, p_path]
         if (is_graph):
             p = subprocess.Popen(commands, cwd=self.cwd)
         else:
 
 class TfsRunnerThread(threading.Thread):
     """docstring for ClearLogTread"""
-    def __init__(self, path, method):
+    def __init__(self, p_path, method):
         super(TfsRunnerThread, self).__init__()
         self.method = method
-        self.path = path
+        self.m_path = p_path
         self.success = False
         self.message = ""
 
     def run(self):
-        (self.success, self.message) = self.method(self.path)
+        (self.success, self.message) = self.method(self.m_path)
 
 class ThreadProgress():
     def __init__(self, view, thread, message, success_message = None):
         i += self.addend
         sublime.set_timeout(lambda: self.run(i), 100)
 
-
 class TfsCheckoutCommand(sublime_plugin.TextCommand):
     def run(self, edit):
-        path = self.view.file_name()
-        if not (path is None):
+        v_path = get_unicode_filename(self.view)
+        if not (v_path is None):
             manager = TfsManager()
-            thread = TfsRunnerThread(path, manager.checkout)
+            thread = TfsRunnerThread(v_path, manager.checkout)
             thread.start()
-            ThreadProgress(self.view, thread, "Checkout...", "Checkout success: %s" % path)
+            ThreadProgress(self.view, thread, "Checkout...", "Checkout success: %s" % v_path)
 
 class TfsUndoCommand(sublime_plugin.TextCommand):
     def run(self, edit):
-        path = self.view.file_name()
-        if not (path is None):
+        v_path = get_unicode_filename(self.view)
+        if not (v_path is None):
             manager = TfsManager()
-            thread = TfsRunnerThread(path, manager.undo)
+            thread = TfsRunnerThread(v_path, manager.undo)
             thread.start()
-            ThreadProgress(self.view, thread, "Undo...", "Undo success: %s" % path)
+            ThreadProgress(self.view, thread, "Undo...", "Undo success: %s" % v_path)
 
 class TfsCheckinCommand(sublime_plugin.TextCommand):
     def run(self, edit):
-        path = self.view.file_name()
-        if not (path is None):
-            if (not isReadonly(path)):
+        v_path = get_unicode_filename(self.view)
+        if not (v_path is None):
+            if (not isReadonly(v_path)):
                 self.view.run_command('save')
             manager = TfsManager()
-            thread = TfsRunnerThread(path, manager.checkin)
+            thread = TfsRunnerThread(v_path, manager.checkin)
             thread.start()
-            ThreadProgress(self.view, thread, "Checkin...", "Checkin success: %s" % path)
+            ThreadProgress(self.view, thread, "Checkin...", "Checkin success: %s" % v_path)
 
 class TfsHistoryCommand(sublime_plugin.TextCommand):
     def run(self, edit):
-        path = self.view.file_name()
-        if not (path is None):
+        v_path = get_unicode_filename(self.view)
+        if not (v_path is None):
             manager = TfsManager()
-            thread = TfsRunnerThread(path, manager.history)
+            thread = TfsRunnerThread(v_path, manager.history)
             thread.start()
-            ThreadProgress(self.view, thread, "History...", "History success: %s" % path)
+            ThreadProgress(self.view, thread, "History...", "History success: %s" % v_path)
 
 class TfsAddCommand(sublime_plugin.TextCommand):
     def run(self, edit):
-        path = self.view.file_name()
-        if not (path is None):
+        v_path = get_unicode_filename(self.view)
+        if not (v_path is None):
             manager = TfsManager()
-            thread = TfsRunnerThread(path, manager.add)
+            thread = TfsRunnerThread(v_path, manager.add)
             thread.start()
-            ThreadProgress(self.view, thread, "Adding...", "Added success: %s" % path)
+            ThreadProgress(self.view, thread, "Adding...", "Added success: %s" % v_path)
 
 class TfsGetLatestCommand(sublime_plugin.TextCommand):
     def run(self, edit):
-        path = self.view.file_name()
-        if not (path is None):
-            if (not isReadonly(path)):
+        v_path = get_unicode_filename(self.view)
+        if not (v_path is None):
+            if (not isReadonly(v_path)):
                 self.view.run_command('save')
             manager = TfsManager()
-            thread = TfsRunnerThread(path, manager.get_latest)
+            thread = TfsRunnerThread(v_path, manager.get_latest)
             thread.start()
-            ThreadProgress(self.view, thread, "Getting...", "Get latest success: %s" % path)
+            ThreadProgress(self.view, thread, "Getting...", "Get latest success: %s" % v_path)
 
 class TfsDifferenceCommand(sublime_plugin.TextCommand):
     def run(self, edit):
-        path = self.view.file_name()
-        if not (path is None):
-            if (not isReadonly(path)):
+        v_path = get_unicode_filename(self.view)
+        if not (v_path is None):
+            if (not isReadonly(v_path)):
                 self.view.run_command('save')
             manager = TfsManager()
-            thread = TfsRunnerThread(path, manager.difference)
+            thread = TfsRunnerThread(v_path, manager.difference)
             thread.start()
-            ThreadProgress(self.view, thread, "Comparing...", "Comparing success: %s" % path)
+            ThreadProgress(self.view, thread, "Comparing...", "Comparing success: %s" % v_path)
 
 class TfsDeleteCommand(sublime_plugin.TextCommand):
     def run(self, edit):
-        path = self.view.file_name()
-        if not (path is None):
+        v_path = get_unicode_filename(self.view)
+        if not (v_path is None):
             manager = TfsManager()
-            thread = TfsRunnerThread(path, manager.delete)
+            thread = TfsRunnerThread(v_path, manager.delete)
             thread.start()
-            ThreadProgress(self.view, thread, "Deleting...", "Delete success: %s" % path)
+            ThreadProgress(self.view, thread, "Deleting...", "Delete success: %s" % v_path)
 
 class TfsStatusCommand(sublime_plugin.TextCommand):
     def run(self, edit):
-        path = self.view.file_name()
-        if not (path is None):
+        v_path = get_unicode_filename(self.view)
+        if not (v_path is None):
             manager = TfsManager()
-            thread = TfsRunnerThread(path, manager.status)
+            thread = TfsRunnerThread(v_path, manager.status)
             thread.start()
             ThreadProgress(self.view, thread, "Getting status...")
 
 class TfsAnnotateCommand(sublime_plugin.TextCommand):
     def run(self, edit):
-        path = self.view.file_name()
-        if not (path is None):
+        v_path = get_unicode_filename(self.view)
+        if not (v_path is None):
             manager = TfsManager()
-            thread = TfsRunnerThread(path, manager.annotate)
+            thread = TfsRunnerThread(v_path, manager.annotate)
             thread.start()
             ThreadProgress(self.view, thread, "Annotating...")
 
 class TfsEventListener(sublime_plugin.EventListener):
     def on_modified(self, view):
-        path = view.file_name()
-        if not (path is None) and isReadonly(path):
+        v_path = get_unicode_filename(view)
+        if not (v_path is None):
             manager = TfsManager()
-            thread = TfsRunnerThread(path, manager.auto_checkout)
-            thread.start()
-            ThreadProgress(view, thread, "Checkout...", "Checkout success: %s" % path)
+            if isReadonly(v_path):
+                if manager.auto_checkout_enabled:
+                    thread = TfsRunnerThread(v_path, manager.auto_checkout)
+                    thread.start()
+                    ThreadProgress(view, thread, "Checkout...", "Checkout success: %s" % v_path)
 
-def isReadonly(path):
-    fileAtt = os.stat(path)[0]
-    return not fileAtt & stat.S_IWRITE
+def isReadonly(p_path):
+    try:
+        fileAttrs = os.stat(p_path)
+        fileAtt = fileAttrs[0]
+        return not fileAtt & stat.S_IWRITE
+    except WindowsError:
+        pass

sublime_tfs.sublime-settings

 {
     "tf_path": "C:/Program Files (x86)/Microsoft Visual Studio 10.0/Common7/IDE/TF.exe",
-    "tfpt_path": "C:/Program Files (x86)/Microsoft Team Foundation Server 2010 Power Tools/TFPT.exe"
+    "tfpt_path": "C:/Program Files (x86)/Microsoft Team Foundation Server 2010 Power Tools/TFPT.exe",
+    "auto_checkout_enabled" : true,
  1. Jason Sallis

    "auto_checkout_enabled" : true,

    There is a trailing comma on this line that causes a "trailing comma before closing bracket" error and effectively breaks the plugin.

 }
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.