This repository has been archived by the owner on Nov 28, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 9
/
sourcegraph.py
139 lines (120 loc) · 4.85 KB
/
sourcegraph.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
import sublime, sublime_plugin
import webbrowser
import os, subprocess
import platform
import sys
from urllib.parse import urlparse, urlencode
# Define a startupinfo which can be passed to subprocess calls which hides the
# command prompt on Windows. Otherwise doing simple things like e.g. running a
# git command would create a visual Command Prompt window, annoying the user.
startupinfo = None
if platform.system() == 'Windows':
startupinfo = subprocess.STARTUPINFO()
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
startupinfo.wShowWindow = subprocess.SW_HIDE
VERSION = 'v1.0.7'
FILENAME_SETTINGS = 'Sourcegraph.sublime-settings'
# gitRemotes returns the names of all git remotes, e.g. ['origin', 'foobar']
def gitRemotes(repoDir):
proc = subprocess.Popen(['git', 'remote'], stdout=subprocess.PIPE, cwd=repoDir, startupinfo=startupinfo)
return proc.stdout.read().decode('utf-8').splitlines()
# gitRemoteURL returns the remote URL for the given remote name.
# e.g. 'origin' -> 'git@github.com:foo/bar'
def gitRemoteURL(repoDir, remoteName):
proc = subprocess.Popen(['git', 'remote', 'get-url', remoteName], stdout=subprocess.PIPE, cwd=repoDir, startupinfo=startupinfo)
return proc.stdout.read().decode('utf-8').rstrip()
# gitDefaultRemoteURL returns the remote URL of the first Git remote found. An
# exception is raised if there is not one.
def gitDefaultRemoteURL(repoDir):
remotes = gitRemotes(repoDir)
if len(remotes) == 0:
raise Exception('no configured git remotes')
if len(remotes) > 1:
print('using first git remote:', remotes[0])
return gitRemoteURL(repoDir, remotes[0])
# gitRootDir returns the repository root directory for any directory within the
# repository.
def gitRootDir(repoDir):
proc = subprocess.Popen(['git', 'rev-parse', '--show-toplevel'], stdout=subprocess.PIPE, cwd=repoDir, startupinfo=startupinfo)
return proc.stdout.read().decode('utf-8').rstrip()
# gitBranch returns either the current branch name of the repository OR in all
# other cases (e.g. detached HEAD state), it returns "HEAD".
def gitBranch(repoDir):
proc = subprocess.Popen(['git', 'rev-parse', '--abbrev-ref', 'HEAD'], stdout=subprocess.PIPE, cwd=repoDir, startupinfo=startupinfo)
return proc.stdout.read().decode('utf-8').rstrip()
def sourcegraphURL(settings):
sourcegraphURL = settings.get('SOURCEGRAPH_URL')
if not sourcegraphURL.endswith('/'):
return sourcegraphURL + '/'
return sourcegraphURL
# repoInfo returns the Sourcegraph repository URI, and the file path relative
# to the repository root. If the repository URI cannot be determined, an
# exception is logged and ("", "", "") is returned.
def repoInfo(fileName):
repo = ""
fileRel = ""
branch = ""
try:
# Determine repository root directory.
fileDir = os.path.dirname(fileName)
repoRoot = gitRootDir(fileDir)
# Determine file path, relative to repository root.
fileRel = fileName[len(repoRoot)+1:]
remoteURL = gitDefaultRemoteURL(repoRoot)
branch = gitBranch(repoRoot)
except Exception as e:
print("repoInfo:", e)
return remoteURL, branch, fileRel
class SourcegraphOpenCommand(sublime_plugin.TextCommand):
def run(self, edit):
remoteURL, branch, fileRel = repoInfo(self.view.file_name())
if remoteURL == "":
return
# For now, we assume the first selection is the most interesting one.
(row,col) = self.view.rowcol(self.view.sel()[0].begin())
(row2,col2) = self.view.rowcol(self.view.sel()[0].end())
# Open in browser
settings = sublime.load_settings(FILENAME_SETTINGS)
url = sourcegraphURL(settings)+'-/editor?' + urlencode({
'remote_url': remoteURL,
'branch': branch,
'file': fileRel,
'editor': 'Sublime',
'version': VERSION,
'start_row': row,
'start_col': col,
'end_row': row2,
'end_col': col2,
})
webbrowserOpen(url)
class SourcegraphSearchCommand(sublime_plugin.TextCommand):
def run(self, edit):
remoteURL, branch, fileRel = repoInfo(self.view.file_name())
# For now, we assume the first selection is the most interesting one.
(row,col) = self.view.rowcol(self.view.sel()[0].begin())
(row2,col2) = self.view.rowcol(self.view.sel()[0].end())
query = self.view.substr((self.view.sel())[0])
if query == '':
return # nothing to query
# Search in browser
settings = sublime.load_settings(FILENAME_SETTINGS)
url = sourcegraphURL(settings)+'-/editor?' + urlencode({
'remote_url': remoteURL,
'branch': branch,
'file': fileRel,
'editor': 'Sublime',
'version': VERSION,
'search': query,
})
webbrowserOpen(url)
def webbrowserOpen(url):
if sys.platform == 'darwin':
# HACK: There exists a bug in a bad release of MacOS that breaks
# osascript, and subsequently the webbrowser module. The default
# browser does not open, and so it will open e.g. Firefox instead of
# the user's default Chrome.
#
# See https://bugs.python.org/issue30392
subprocess.check_call(["/usr/bin/open", url])
return
webbrowser.open(url, new=2)