Permalink
Browse files

Code copied from git plugin (https://github.com/kemayo/sublime-text-2…

…-git) and partially adopted to vlt status, and vlt add.
  • Loading branch information...
Tomek Wytrębowicz
Tomek Wytrębowicz committed Sep 10, 2012
1 parent bdecab9 commit 4334ee2d24b847b11de3d880db4a4a87a6d47479
Showing with 313 additions and 2 deletions.
  1. +12 −1 Default.sublime-commands
  2. +301 −1 vlt.py
  3. BIN vlt.pyc
View
@@ -1,5 +1,4 @@
[
-
{
"caption": "vlt: Commit",
"command": "vlt_commit"
@@ -8,10 +7,22 @@
"caption": "vlt: Add",
"command": "vlt_add"
},
+ {
+ "caption": "vlt: Add...",
+ "command": "vlt_add_choice"
+ },
{
"caption": "vlt: Update",
"command": "vlt_update"
},
+ {
+ "caption": "vlt: Resolve",
+ "command": "vlt_resolve"
+ },
+ {
+ "caption": "vlt: Status",
+ "command": "vlt_status"
+ },
{
"caption": "vlt: Import",
"command": "vlt_import"
View
302 vlt.py
@@ -7,9 +7,42 @@
import subprocess
import tempfile
import threading
+import os.path
+import functools
+import time
# Plugin Settings are located in 'vlt.sublime-settings' make a copy in the User folder to keep changes
+vlt_root_cache = {}
+def vlt_root(directory):
+ global vlt_root_cache
+
+ retval = False
+ leaf_dir = directory
+
+ if leaf_dir in vlt_root_cache and vlt_root_cache[leaf_dir]['expires'] > time.time():
+ return vlt_root_cache[leaf_dir]['retval']
+
+ while directory:
+ if os.path.exists(os.path.join(directory, '.vlt')):
+ retval = directory
+ else:
+ #break with last directory containing .vlt
+ if retval != False:
+ break
+
+ parent = os.path.realpath(os.path.join(directory, os.path.pardir))
+ if parent == directory:
+ # /.. == /
+ retval = False
+ break
+
+ directory = parent
+
+ vlt_root_cache[leaf_dir] = { 'retval': retval, 'expires': time.time() + 5 }
+
+ return retval
+
# Utility functions
def ConstructCommand(in_command):
command = ''
@@ -20,6 +53,7 @@ def ConstructCommand(in_command):
def VltCommandOnFile(in_command, in_folder, in_filename):
command = ConstructCommand('vlt ' + in_command + ' "' + in_filename + '"')
+ print "vlt [debug]: " + (vlt_root(in_folder) or "[no-vlt repo]") + ': '+ 'vlt ' + in_command + ' "' + in_filename + '"'
p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=in_folder, shell=True)
result, err = p.communicate()
@@ -28,6 +62,221 @@ def VltCommandOnFile(in_command, in_folder, in_filename):
else:
return 0, err.strip()
+def main_thread(callback, *args, **kwargs):
+ # sublime.set_timeout gets used to send things onto the main thread
+ # most sublime.[something] calls need to be on the main thread
+ sublime.set_timeout(functools.partial(callback, *args, **kwargs), 0)
+def _make_text_safeish(text, fallback_encoding, method='decode'):
+ # The unicode decode here is because sublime converts to unicode inside
+ # insert in such a way that unknown characters will cause errors, which is
+ # distinctly non-ideal... and there's no way to tell what's coming out of
+ # git in output. So...
+ try:
+ unitext = getattr(text, method)('utf-8')
+ except (UnicodeEncodeError, UnicodeDecodeError):
+ unitext = getattr(text, method)(fallback_encoding)
+ return unitext
+
+class CommandThread(threading.Thread):
+ def __init__(self, command, on_done, working_dir="", fallback_encoding="", **kwargs):
+ threading.Thread.__init__(self)
+ self.command = command
+ self.on_done = on_done
+ self.working_dir = working_dir
+ if "stdin" in kwargs:
+ self.stdin = kwargs["stdin"]
+ else:
+ self.stdin = None
+ if "stdout" in kwargs:
+ self.stdout = kwargs["stdout"]
+ else:
+ self.stdout = subprocess.PIPE
+ self.fallback_encoding = fallback_encoding
+ self.kwargs = kwargs
+
+ def run(self):
+ try:
+ # Per http://bugs.python.org/issue8557 shell=True is required to
+ # get $PATH on Windows. Yay portable code.
+ shell = os.name == 'nt'
+ if self.working_dir != "":
+ os.chdir(self.working_dir)
+
+ proc = subprocess.Popen(self.command,
+ stdout=self.stdout, stderr=subprocess.STDOUT,
+ stdin=subprocess.PIPE,
+ shell=shell, universal_newlines=True)
+ output = proc.communicate(self.stdin)[0]
+ if not output:
+ output = ''
+ # if sublime's python gets bumped to 2.7 we can just do:
+ # output = subprocess.check_output(self.command)
+ main_thread(self.on_done,
+ _make_text_safeish(output, self.fallback_encoding), **self.kwargs)
+ except subprocess.CalledProcessError, e:
+ main_thread(self.on_done, e.returncode)
+ except OSError, e:
+ if e.errno == 2:
+ main_thread(sublime.error_message, "Git binary could not be found in PATH\n\nConsider using the git_command setting for the Git plugin\n\nPATH is: %s" % os.environ['PATH'])
+ else:
+ raise e
+
+# Draft A base for all commands
+class VltCommand(object):
+ may_change_files = False
+
+ def run_command(self, command, callback=None, show_status=True,
+ filter_empty_args=True, no_save=False, **kwargs):
+ if filter_empty_args:
+ command = [arg for arg in command if arg]
+ if 'working_dir' not in kwargs:
+ kwargs['working_dir'] = self.get_working_dir()
+ if 'fallback_encoding' not in kwargs and self.active_view() and self.active_view().settings().get('fallback_encoding'):
+ kwargs['fallback_encoding'] = self.active_view().settings().get('fallback_encoding').rpartition('(')[2].rpartition(')')[0]
+
+ s = sublime.load_settings("Vlt.sublime-settings")
+ if s.get('save_first') and self.active_view() and self.active_view().is_dirty() and not no_save:
+ self.active_view().run_command('save')
+ if command[0] == 'vlt' and s.get('vlt_command'):
+ command[0] = s.get('vlt_command')
+ #if not callback:
+ # callback = self.generic_done
+ print "vlt[debug]: " + ' '.join(command)
+
+ thread = CommandThread(command, callback, **kwargs)
+ thread.start()
+
+ if show_status:
+ message = kwargs.get('status_message', False) or ' '.join(command)
+ sublime.status_message(message)
+
+
+ def _output_to_view(self, output_file, output, clear=False,
+ syntax="Packages/Diff/Diff.tmLanguage", **kwargs):
+ output_file.set_syntax_file(syntax)
+ edit = output_file.begin_edit()
+ if clear:
+ region = sublime.Region(0, self.output_view.size())
+ output_file.erase(edit, region)
+ output_file.insert(edit, 0, output)
+ output_file.end_edit(edit)
+
+ def scratch(self, output, title=False, position=None, **kwargs):
+ scratch_file = self.get_window().new_file()
+ if title:
+ scratch_file.set_name(title)
+ scratch_file.set_scratch(True)
+ self._output_to_view(scratch_file, output, **kwargs)
+ scratch_file.set_read_only(True)
+ if position:
+ sublime.set_timeout(lambda: scratch_file.set_viewport_position(position), 0)
+ return scratch_file
+
+ def panel(self, output, **kwargs):
+ if not hasattr(self, 'output_view'):
+ self.output_view = self.get_window().get_output_panel("vlt")
+ self.output_view.set_read_only(False)
+ self._output_to_view(self.output_view, output, clear=True, **kwargs)
+ self.output_view.set_read_only(True)
+ self.get_window().run_command("show_panel", {"panel": "output.vlt"})
+
+ def quick_panel(self, *args, **kwargs):
+ self.get_window().show_quick_panel(*args, **kwargs)
+
+# A base for all vlt commands that work with the entire repository
+class VltWindowCommand(VltCommand, sublime_plugin.WindowCommand):
+ def active_view(self):
+ return self.window.active_view()
+
+ def _active_file_name(self):
+ view = self.active_view()
+ if view and view.file_name() and len(view.file_name()) > 0:
+ return view.file_name()
+
+ @property
+ def fallback_encoding(self):
+ if self.active_view() and self.active_view().settings().get('fallback_encoding'):
+ return self.active_view().settings().get('fallback_encoding').rpartition('(')[2].rpartition(')')[0]
+
+ # If there's no active view or the active view is not a file on the
+ # filesystem (e.g. a search results view), we can infer the folder
+ # that the user intends Vlt commands to run against when there's only
+ # only one.
+ def is_enabled(self):
+ if self._active_file_name() or len(self.window.folders()) == 1:
+ return vlt_root(self.get_working_dir())
+
+ def get_file_name(self):
+ return ''
+
+ # If there is a file in the active view use that file's directory to
+ # search for the Vlt root. Otherwise, use the only folder that is
+ # open.
+ def get_working_dir(self):
+ file_name = self._active_file_name()
+ if file_name:
+ return os.path.realpath(os.path.dirname(file_name))
+ else:
+ try: # handle case with no open folder
+ return self.window.folders()[0]
+ except IndexError:
+ return ''
+
+ def get_window(self):
+ return self.window
+
+class VltStatusCommand(VltWindowCommand):
+ force_open = False
+
+ def run(self):
+ #self.run_command(['vlt', 'status' ], self.status_done)
+ self.run_command(['vlt', 'status', vlt_root(self.get_working_dir()) ], self.status_done, True)
+
+ def status_done(self, result):
+ self.results = filter(self.status_filter, result.rstrip().split('\n'))
+ if len(self.results):
+ self.show_status_list()
+ else:
+ sublime.status_message("Nothing to show")
+
+ def show_status_list(self):
+ self.quick_panel(self.results, self.panel_done,
+ sublime.MONOSPACE_FONT)
+
+ def status_filter(self, item):
+ # for this class we don't actually care
+ return len(item) > 0
+
+ def panel_done(self, picked):
+ if 0 > picked < len(self.results):
+ return
+ picked_file = self.results[picked]
+ # first 2 characters are status codes, the third is a space
+ picked_status = picked_file[:1]
+ picked_file = picked_file[2:]
+ self.panel_followup(picked_status, picked_file, picked)
+
+ def panel_followup(self, picked_status, picked_file, picked_index):
+ # split out solely so I can override it for laughs
+
+ s = sublime.load_settings("Vlt.sublime-settings")
+ #root = vlt_root(self.get_working_dir())
+ #vlt even if asked for other destination always prints paths relative to current working dir
+ root = self.get_working_dir()
+ print os.path.join(root, picked_file)
+ print os.path.isfile(os.path.join(root, picked_file))
+ if picked_status == '?' or s.get('status_opens_file') or self.force_open:
+ if(os.path.isfile(os.path.join(root, picked_file))): self.window.open_file(os.path.join(root, picked_file))
+ else:
+ self.run_command(['vlt', 'diff', picked_file.strip('"')],
+ self.diff_done, working_dir=root)
+
+ def diff_done(self, result):
+ if not result.strip():
+ return
+ self.scratch(result, title="Vlt Diff")
+
+
def WarnUser(message):
vlt_settings = sublime.load_settings('vlt.sublime-settings')
if(vlt_settings.get('vlt_warnings_enabled')):
@@ -50,6 +299,7 @@ def Commit(in_folder, in_filename):
class VltAutoCommit(sublime_plugin.EventListener):
preSaveIsFileInRepo = 0
def on_pre_save(self, view):
+ print "vlt: presave"
vlt_settings = sublime.load_settings('vlt.sublime-settings')
self.preSaveIsFileInRepo = 0
@@ -63,6 +313,7 @@ def on_pre_save(self, view):
self.preSaveIsFileInRepo = IsFileInRepo(folder_name, filename)
def on_post_save(self, view):
+ print "vlt: postsave"
if(self.preSaveIsFileInRepo == -1):
folder_name, filename = os.path.split(view.file_name())
success, message = Add(folder_name, filename)
@@ -99,6 +350,39 @@ def run(self, edit):
else:
WarnUser("View does not contain a file")
+class VltAddChoiceCommand(VltStatusCommand):
+#VltStatusCommand):
+ def status_filter(self, item):
+ return item[0]=="?"
+
+ def show_status_list(self):
+ self.results = [[" + All Files", "apart from untracked files"]] + self.results
+ self.quick_panel(self.results, self.panel_done,
+ sublime.MONOSPACE_FONT)
+
+ def panel_followup(self, picked_status, picked_file, picked_index):
+ working_dir=self.get_working_dir()
+
+ if picked_index == 0:
+ command = ['vlt', 'add', vlt_root(working_dir)]
+ else:
+ command = ['vlt']
+ picked_file = picked_file.strip('"')
+ print working_dir+"/"+picked_file
+ print os.path.isfile(working_dir+"/"+picked_file)
+ #if os.path.isfile(working_dir+"/"+picked_file):
+ command += ['add']
+ #else:
+ # command += ['rm']
+ command += [picked_file]
+
+ self.run_command(command, self.rerun,
+ working_dir=working_dir)
+
+ def rerun(self, result):
+ self.run()
+
+
def IsFileInRepo(in_folder, in_filename):
success, message = VltCommandOnFile("info", in_folder, in_filename);
if(not success):
@@ -147,4 +431,20 @@ def run(self, edit):
LogResults(success, message)
else:
- WarnUser("View does not contain a file")
+ WarnUser("View does not contain a file")
+# Update section
+def Resolve(in_folder, in_filename):
+ # resolve the file
+ return VltCommandOnFile("resolve", in_folder, in_filename);
+
+class VltResolveCommand(sublime_plugin.TextCommand):
+ def run(self, edit):
+ if(self.view.file_name()):
+ folder_name, filename = os.path.split(self.view.file_name())
+ success, message = Commit(folder_name, filename)
+ LogResults(success, message)
+ else:
+ WarnUser("View does not contain a file")
+
+
+
View
BIN vlt.pyc
Binary file not shown.

0 comments on commit 4334ee2

Please sign in to comment.