forked from deathaxe/sublime-gitformats
-
Notifications
You must be signed in to change notification settings - Fork 0
/
open_file.py
207 lines (151 loc) · 5.58 KB
/
open_file.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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
import os
import sys
import sublime_plugin
__all__ = ["GitOpenFileCommand"]
GIT_SEP = os.sep + ".git" + os.sep
if (
sys.version < "3.8"
and sys.platform == "win32"
and sys.getwindowsversion().major >= 6
):
from nt import _getfinalpathname
def realpath(path):
"""Resolve symlinks and return real path to file.
Note:
This is a fix for the issue of `os.path.realpath()` not to resolve
symlinks on Windows as it is an alias to `os.path.abspath()` only.
see: http://bugs.python.org/issue9949
This fix applies to local paths only as symlinks are not resolved
by _getfinalpathname on network drives anyway.
Also note that _getfinalpathname in Python 3.3 throws
`NotImplementedError` on Windows versions prior to Windows Vista,
hence we fallback to `os.path.abspath()` on these platforms.
Arguments:
path (string): The path to resolve.
Returns:
string: The resolved absolute path if exists or path as provided
otherwise.
"""
try:
if path:
real_path = _getfinalpathname(path)
if real_path[5] == ":":
# Remove \\?\ from beginning of resolved path
return real_path[4:]
return os.path.abspath(path)
except FileNotFoundError:
pass
return path
else:
def realpath(path):
"""Resolve symlinks and return real path to file.
Arguments:
path (string): The path to resolve.
Returns:
string: The resolved absolute path.
"""
return os.path.realpath(path) if path else None
def git_path(path):
return os.path.join(path, ".git")
def parse_gitfile(gitfile):
try:
with open(gitfile) as file:
text = file.read()
if text.startswith("gitdir: "):
return realpath(text[len("gitdir: ") :].strip())
except OSError:
pass
return gitfile
def is_work_tree(path):
"""Check if 'path' is a valid git working tree.
A working tree contains a `.git` directory or file.
Arguments:
path (string): The path to check.
Returns:
bool: True if path contains a '.git'
"""
return path and os.path.exists(git_path(path))
def rev_parse_commondir(file_path):
"""Return the .git directory of the file's worktree's super repository.
This is a local alternative to calling the git command:
git rev-parse --git-common-dir
Arguments:
file_path (string): a absolute or relative file path
Returns:
string: The .git directory of the file_path's worktree's super repository or
None: if the file is not located in a repository.
"""
path = rev_parse_gitdir(file_path)
if path and not path.endswith(".git"):
start = path.find(GIT_SEP)
if start > -1:
return path[: start + len(GIT_SEP) - 1]
return path
def rev_parse_gitdir(file_path):
"""Return the .git directory of the file's worktree.
This is a local alternative to calling the git command:
git rev-parse --absolute-git-dir
Arguments:
file_path (string): a absolute or relative file path
Returns:
string: The .git directory of the file_path's worktree or
None: if the file is not located in a repository.
"""
path = rev_parse_worktree(file_path)
if path:
return parse_gitfile(git_path(path))
return path
def rev_parse_super_worktree(file_path):
"""Return the root directory of the file's worktree's super repository.
This is a local alternative to calling the git command:
git rev-parse --show-superproject-working-tree
Arguments:
file_path (string): a absolute or relative file path
Returns:
string: The root directory of the file_path's worktree's super repository or
None: if the file is not located in a repository.
"""
path = rev_parse_gitdir(file_path)
if path:
if path.endswith(".git"):
return os.path.split(path)[0]
else:
return path.split(GIT_SEP)[0]
return path
def rev_parse_worktree(file_path):
"""Return the toplevel directory of the file's worktree.
This is a local alternative to calling the git command:
git rev-parse --show-toplevel
Arguments:
file_path (string): a absolute or relative file path
Returns:
string: The worktree root directory or
None: if the file is not located in a repository.
"""
if file_path:
path, name = os.path.split(realpath(file_path))
while path and name:
if is_work_tree(path):
return path
path, name = os.path.split(path)
return None
class GitOpenFileCommand(sublime_plugin.TextCommand):
variables = {
"$GIT_COMMON_DIR": rev_parse_commondir,
"$GIT_DIR": rev_parse_gitdir,
"$GIT_SUPER_WORK_TREE": rev_parse_super_worktree,
"$GIT_WORK_TREE": rev_parse_worktree,
}
def is_enabled(self):
return rev_parse_worktree(self.view.file_name()) is not None
def run(self, edit, name, syntax=None):
file_path = name
for var, expander in self.variables.items():
if var in file_path:
abspath = expander(self.view.file_name())
if abspath:
file_path = file_path.replace(var, abspath)
break
view = self.view.window().open_file(file_path)
if syntax:
view.assign_syntax(syntax)