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('^', '^^') |