phabricator.py (63 lines of code) (raw):
import os
import re
try:
# Attempt to load Python 2 quote
from urllib import quote
except ImportError:
# Fallback to Python 3 quote
from urllib.parse import quote
import sublime
import sublime_plugin
import subprocess
SETTINGS_FILE = 'Phabricator.sublime-settings'
class PhabricatorOpenCommand(sublime_plugin.WindowCommand):
def run(self):
"""Open a file inside of Phabricator with the selected lines."""
settings = sublime.load_settings(SETTINGS_FILE)
# Get the first selection
view = sublime.active_window().active_view()
first_sel = view.sel()[0]
# Find the lines that are selected. Logic taken from:
# https://github.com/ehamiter/ST2-GitHubinator/blob/c3fce41aaf2fc564/githubinator.py#L44-L49
begin_line = view.rowcol(first_sel.begin())[0] + 1
end_line = view.rowcol(first_sel.end())[0] + 1
if begin_line == end_line:
lines = begin_line
else:
lines = '{0}-{1}'.format(begin_line, end_line)
# Find the file directory and name
filepath = view.file_name()
filedir = os.path.dirname(filepath)
filename = os.path.basename(filepath)
# Find the preselected branch
git_branch = settings.get('branch')
if git_branch is None and settings.get('branch_use_arc_land_onto_default', False):
# Get current branch
arc_args = [settings.get('arc_path', 'arc'), 'get-config', 'arc.land.onto.default']
arc_child = subprocess.Popen(
arc_args, cwd=filedir,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
# DEV: We decode for Python 3 which receives bytes
arc_stdout = arc_child.stdout.read().decode('utf-8')
arc_stderr = arc_child.stderr.read().decode('utf-8')
if arc_stderr:
print('Ran `{0}` in `{1}`'.format(' '.join(arc_args), filedir))
print('STDERR: {0}'.format(arc_stderr))
# Grep the output to find the return value.
# If something fails, git_branch will be unset and we will fallthrough into the next
# case
m = re.search('.*Current Value: "(?P<value>.*)"\n.*', arc_stdout)
git_branch = m.group('value')
# If no preselected branch is provided and we are not using arc.land.onto.default setting
if git_branch is None:
# Get current branch
git_args = ['git', 'symbolic-ref', 'HEAD']
git_child = subprocess.Popen(
git_args, cwd=filedir,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
# DEV: We decode for Python 3 which receives bytes
git_stdout = git_child.stdout.read().decode('utf-8')
git_stderr = git_child.stderr.read().decode('utf-8')
if git_stderr:
print('Ran `{0}` in `{1}`'.format(' '.join(git_args), filedir))
print('STDERR: {0}'.format(git_stderr))
# Strip away `refs/head` that Phabricator dislikes
# `refs/heads/dev/my.branch` -> `dev/my.branch`
git_branch = git_stdout.replace('refs/heads/', '').replace('\r', '').replace('\n', '')
# Double escape branch name for Phabricator
# `dev/my.branch` -> `dev%2Fmy.branch` -> `dev%252Fmy.branch`
escaped_branch = quote(quote(git_branch, safe=''), safe='')
# Run `arc browse` and dump the output to the console
browse_path = '{0}:{1}'.format(filename, lines)
arc_args = [
settings.get('arc_path', 'arc'), 'browse', browse_path, '--branch', escaped_branch]
arc_child = subprocess.Popen(
arc_args, cwd=filedir,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
arc_stdout = arc_child.stdout.read().decode('utf-8')
arc_stderr = arc_child.stderr.read().decode('utf-8')
if arc_stdout or arc_stderr:
print('Ran `{0}` in `{1}`'.format(' '.join(arc_args), filedir))
if arc_stdout:
print('STDOUT: {0}'.format(arc_stdout))
if arc_stderr:
print('STDERR: {0}'.format(arc_stderr))