317 lines
9.2 KiB
Python
317 lines
9.2 KiB
Python
# coding=utf8
|
|
import sublime
|
|
import os
|
|
import subprocess
|
|
|
|
from SideBarItem import SideBarItem
|
|
|
|
class Object():
|
|
pass
|
|
|
|
s = sublime.load_settings('SideBarGit.sublime-settings')
|
|
path_to_git_unixes = s.get('path_to_git_unixes');
|
|
|
|
class SideBarGit:
|
|
|
|
last_stdout = ''
|
|
|
|
def run(
|
|
self,
|
|
object,
|
|
modal = False,
|
|
background = False,
|
|
|
|
refresh_funct_view = False,
|
|
refresh_funct_command = False,
|
|
refresh_funct_item = False,
|
|
refresh_funct_to_status_bar = False,
|
|
refresh_funct_title = False,
|
|
refresh_funct_no_results = False,
|
|
refresh_funct_syntax_file = False
|
|
):
|
|
|
|
if not refresh_funct_view:
|
|
pass
|
|
else:
|
|
object = Object()
|
|
object.command = refresh_funct_command
|
|
object.item = SideBarItem(refresh_funct_item, os.path.isdir(refresh_funct_item))
|
|
object.to_status_bar = refresh_funct_to_status_bar
|
|
object.title = refresh_funct_title
|
|
object.no_results = refresh_funct_no_results
|
|
object.syntax_file = refresh_funct_syntax_file
|
|
|
|
debug = False
|
|
if debug:
|
|
print '----------------------------------------------------------'
|
|
print 'GIT:'
|
|
print object.command
|
|
print 'CWD:'
|
|
print object.item.forCwdSystemPath()
|
|
print 'PATH:'
|
|
print object.item.forCwdSystemName()
|
|
|
|
failed = False
|
|
|
|
if sublime.platform() == 'windows':
|
|
object.command = map(self.escapeCMDWindows, object.command)
|
|
|
|
if sublime.platform() is not 'windows' and object.command[0] == 'git':
|
|
if path_to_git_unixes != '':
|
|
object.command[0] = s.get('path_to_git_unixes')
|
|
elif os.path.exists('/usr/local/git/bin'):
|
|
object.command[0] = '/usr/local/git/bin/git'
|
|
|
|
cwd = object.item.forCwdSystemPath()
|
|
|
|
try:
|
|
if sublime.platform() == 'windows':
|
|
|
|
process = subprocess.Popen(
|
|
#" ".join(object.command),
|
|
object.command,
|
|
cwd=cwd,
|
|
stdout=subprocess.PIPE,
|
|
stderr=subprocess.STDOUT,
|
|
shell=True,
|
|
universal_newlines=True)
|
|
else:
|
|
process = subprocess.Popen(
|
|
object.command,
|
|
cwd=cwd,
|
|
stdout=subprocess.PIPE,
|
|
stderr=subprocess.STDOUT,
|
|
shell=False,
|
|
universal_newlines=True)
|
|
|
|
if background:
|
|
if debug:
|
|
print 'SUCCESS'
|
|
print '----------------------------------------------------------'
|
|
return True
|
|
|
|
stdout, stderr = process.communicate()
|
|
SideBarGit.last_stdout = str(stdout).rstrip()
|
|
self.last_stdout = str(stdout).rstrip()
|
|
|
|
stdout = stdout.strip()
|
|
|
|
if stdout.find('fatal:') == 0 or stdout.find('error:') == 0 or stdout.find('Permission denied') == 0 or stderr:
|
|
print 'FAILED'
|
|
failed = True
|
|
else:
|
|
if debug:
|
|
print 'SUCCESS'
|
|
if stdout:
|
|
if debug:
|
|
print 'STDOUT'
|
|
print stdout
|
|
if stderr:
|
|
print 'STDERR'
|
|
print stderr
|
|
except OSError as (errno, strerror):
|
|
print 'FAILED'
|
|
failed = True
|
|
print errno
|
|
print strerror
|
|
SideBarGit.last_stdout = ''
|
|
self.last_stdout = ''
|
|
except IOError as (errno, strerror):
|
|
print 'FAILED'
|
|
failed = True
|
|
print errno
|
|
print strerror
|
|
SideBarGit.last_stdout = ''
|
|
self.last_stdout = ''
|
|
if debug:
|
|
print '----------------------------------------------------------'
|
|
|
|
try:
|
|
object.to_status_bar
|
|
except:
|
|
object.to_status_bar = False
|
|
|
|
try:
|
|
object.silent
|
|
return
|
|
except:
|
|
pass
|
|
|
|
if failed:
|
|
try:
|
|
strerror
|
|
if errno == 2:
|
|
self.alert(strerror+'\nPossible error:\n'+object.command[0]+' not found on $PATH')
|
|
else:
|
|
self.alert(strerror)
|
|
return False
|
|
except:
|
|
if not stdout and not stderr:
|
|
return False
|
|
if stdout.find('Permission denied') == 0 or stdout.find('fatal: The remote end hung up unexpectedly') == 0:
|
|
self.alert((stdout or '')+'\n'+(stderr or '')+'\nPossible error:\nssh keys not in .ssh/ directory or keys not opened')
|
|
else:
|
|
self.alert((stdout or '')+'\n'+(stderr or ''))
|
|
return False
|
|
else:
|
|
if stdout != '' and refresh_funct_view == False and (object.to_status_bar or " ".join(object.command).find('git push') == 0 or stdout.find('nothing to commit') == 0):
|
|
self.status(stdout)
|
|
else:
|
|
if stdout == '' and refresh_funct_view == False:
|
|
try:
|
|
self.status(object.no_results)
|
|
except:
|
|
self.status('No output to show')
|
|
return True
|
|
if stdout == '' and refresh_funct_view != False:
|
|
try:
|
|
stdout = object.no_results
|
|
except:
|
|
stdout = 'No output to show'
|
|
if stdout == '':
|
|
return True
|
|
|
|
if refresh_funct_view == False:
|
|
view = sublime.active_window().new_file()
|
|
else:
|
|
view = refresh_funct_view
|
|
try:
|
|
view.set_name(object.title.decode('utf-8'))
|
|
except:
|
|
view.set_name('No Title')
|
|
try:
|
|
if object.syntax_file != False:
|
|
view.set_syntax_file(object.syntax_file)
|
|
except:
|
|
pass
|
|
try:
|
|
object.word_wrap
|
|
view.settings().set('word_wrap', False)
|
|
except:
|
|
pass
|
|
view.settings().set('fallback_encoding', 'UTF-8')
|
|
view.settings().set('encoding', 'UTF-8')
|
|
view.settings().set('default_dir', object.item.dirname())
|
|
view.set_scratch(True)
|
|
|
|
if refresh_funct_view == False:
|
|
view.settings().set('SideBarGitIsASideBarGitTab', True)
|
|
view.settings().set('SideBarGitCommand', object.command)
|
|
view.settings().set('SideBarGitModal', modal)
|
|
view.settings().set('SideBarGitBackground', background)
|
|
view.settings().set('SideBarGitItem', object.item.path())
|
|
try:
|
|
view.settings().set('SideBarGitToStatusBar', object.to_status_bar)
|
|
except:
|
|
view.settings().set('SideBarGitToStatusBar', False)
|
|
try:
|
|
view.settings().set('SideBarGitTitle', object.title)
|
|
except:
|
|
view.settings().set('SideBarGitTitle', 'No Title')
|
|
try:
|
|
view.settings().set('SideBarGitNoResults', object.no_results)
|
|
except:
|
|
view.settings().set('SideBarGitNoResults', 'No output to show')
|
|
try:
|
|
view.settings().set('SideBarGitSyntaxFile', object.syntax_file)
|
|
except:
|
|
view.settings().set('SideBarGitSyntaxFile', False)
|
|
|
|
content = "[SideBarGit@SublimeText "
|
|
content += object.item.name().decode('utf-8')
|
|
content += "/] "
|
|
content += (" ".join(object.command)).decode('utf-8')
|
|
content += "\n\n"
|
|
content += "# Improve this command, the output or the tab title by posting here:"
|
|
content += "\n"
|
|
content += "# http://www.sublimetext.com/forum/viewtopic.php?f=5&t=3405"
|
|
content += "\n"
|
|
content += "# Tip: F5 will run the command again and refresh the contents of this tab"
|
|
content += "\n\n"
|
|
try:
|
|
content += stdout
|
|
except:
|
|
content += unicode(stdout, 'UTF-8', errors='ignore')
|
|
|
|
edit = view.begin_edit()
|
|
view.replace(edit, sublime.Region(0, view.size()), content);
|
|
view.sel().clear()
|
|
view.sel().add(sublime.Region(0))
|
|
view.end_edit(edit)
|
|
return True
|
|
|
|
def confirm(self, message, function, arg1):
|
|
if int(sublime.version()) >= 2186:
|
|
if sublime.ok_cancel_dialog(u'Side Bar Git : '+message):
|
|
function(arg1, True)
|
|
else:
|
|
import functools
|
|
sublime.active_window().run_command('hide_panel');
|
|
sublime.active_window().show_input_panel("Confirmation Required:", message.decode('utf-8'), functools.partial(function, arg1, True), None, None)
|
|
|
|
def prompt(self, message, default, function, arg1):
|
|
import functools
|
|
sublime.active_window().run_command('hide_panel');
|
|
sublime.active_window().show_input_panel(message.decode('utf-8'), default.decode('utf-8'), functools.partial(function, arg1, True), None, None)
|
|
|
|
def alert(self, message):
|
|
try:
|
|
sublime.error_message('Git : '+(message.decode('utf-8')))
|
|
except:
|
|
try:
|
|
sublime.error_message('Git : '+message)
|
|
except:
|
|
print message
|
|
|
|
def status(self, message):
|
|
message = message[:200] + (message[200:] and '…')
|
|
message = message.replace('\n', ' ')
|
|
try:
|
|
v = sublime.active_window().active_view()
|
|
v.set_status('SideBarGit', 'Git : '+(message.decode('utf-8')))
|
|
sublime.set_timeout(lambda: SideBarGit().statusRemove(v), 16000)
|
|
except:#there is no tabs opened
|
|
sublime.status_message('Git : '+(message.decode('utf-8')))
|
|
|
|
def statusRemove(self, v):
|
|
try:
|
|
v.erase_status('SideBarGit')
|
|
except:#this view is not there
|
|
pass
|
|
|
|
def quickPanel(self, function, extra, data):
|
|
import functools
|
|
window = sublime.active_window()
|
|
# window.show_input_panel("BUG!", '', '', None, None)
|
|
# window.run_command('hide_panel');
|
|
data = [item[:70] for item in data]
|
|
window.show_quick_panel(data, functools.partial(self.quickPanelDone, function, extra, data))
|
|
|
|
def quickPanelDone(self, function, extra, data, result):
|
|
if result != -1:
|
|
function(extra, data, result)
|
|
|
|
def getSelectedRepos(self, items):
|
|
repos = []
|
|
reposTemp = []
|
|
for item in items:
|
|
original = item.path()
|
|
while not os.path.exists(item.join('.git')):
|
|
if item.dirname() == item.path():
|
|
break;
|
|
item.path(item.dirname())
|
|
|
|
if os.path.exists(item.join('.git')):
|
|
try:
|
|
index = reposTemp.index(item.path())
|
|
except ValueError:
|
|
reposTemp.append(item.path())
|
|
index = reposTemp.index(item.path())
|
|
repos.append(Object())
|
|
repos[index].repository = item
|
|
repos[index].items = []
|
|
repos[index].items.append(SideBarItem(original, os.path.isdir(original)))
|
|
return repos
|
|
|
|
def escapeCMDWindows(self, string):
|
|
return string.replace('^', '^^') |