Skip to content

Commit

Permalink
Merge 055917d into 9b2ed17
Browse files Browse the repository at this point in the history
  • Loading branch information
kaste committed Dec 12, 2018
2 parents 9b2ed17 + 055917d commit a76966d
Show file tree
Hide file tree
Showing 3 changed files with 223 additions and 2 deletions.
38 changes: 36 additions & 2 deletions core/commands/diff.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,7 @@ def run_async(self, in_cached_mode=False, file_path=None, current_file=False, ba
diff_view = diff_views[view_key]
else:
diff_view = util.view.get_scratch_view(self, "diff", read_only=True)
if not title:
title = (DIFF_CACHED_TITLE if in_cached_mode else DIFF_TITLE).format(os.path.basename(repo_path))

settings = diff_view.settings()
settings.set("git_savvy.repo_path", repo_path)
settings.set("git_savvy.file_path", file_path)
Expand All @@ -64,6 +63,41 @@ def run_async(self, in_cached_mode=False, file_path=None, current_file=False, ba
settings.set("git_savvy.diff_view.target_commit", target_commit)
settings.set("git_savvy.diff_view.show_diffstat", self.savvy_settings.get("show_diffstat", True))
settings.set("git_savvy.diff_view.disable_stage", disable_stage)

# Clickable lines:
# (A) common/commands/view_manipulation.py | 1 +
# (B) --- a/common/commands/view_manipulation.py
# (C) +++ b/common/commands/view_manipulation.py
# (D) diff --git a/common/commands/view_manipulation.py b/common/commands/view_manipulation.py
#
# Now the actual problem is that Sublime only accepts a subset of modern reg expressions,
# B, C, and D are relatively straight forward because they match a whole line, and
# basically all other lines in a diff start with one of `[+- ]`.
FILE_RE = (
r"^(?:\s(?=.*\s+\|\s+\d+\s)|--- a\/|\+{3} b\/|diff .+b\/)"
# ^^^^^^^^^^^^^^^^^^^^^ (A)
# ^ one space, and then somewhere later on the line the pattern ` | 23 `
# ^^^^^^^ (B)
# ^^^^^^^^ (C)
# ^^^^^^^^^^^ (D)
r"(\S[^|]*?)"
# ^ ! lazy to not match the trailing spaces, see below

r"(?:\s+\||$)"
# ^ (B), (C), (D)
# ^^^^^ (A) We must match the spaces here bc Sublime will not rstrip() the
# filename for us.
)

settings.set("result_file_regex", FILE_RE)
# Clickable line:
# @@ -69,6 +69,7 @@ class GsHandleVintageousCommand(TextCommand):
# ^^ we want the second (current) line offset of the diff
settings.set("result_line_regex", r"^@@ [^+]*\+(\d+),")
settings.set("result_base_dir", repo_path)

if not title:
title = (DIFF_CACHED_TITLE if in_cached_mode else DIFF_TITLE).format(os.path.basename(repo_path))
diff_view.set_name(title)
diff_view.set_syntax_file("Packages/GitSavvy/syntax/diff.sublime-syntax")
diff_views[view_key] = diff_view
Expand Down
75 changes: 75 additions & 0 deletions tests/fixtures/diff_1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
core/commands/custom.py | 2 +-
core/commands/diff.py | 39 +++++++++++++++++++++++++++++++++++----
2 files changed, 36 insertions(+), 5 deletions(-)

diff --git a/core/commands/custom.py b/core/commands/custom.py
index 1facb191..8b079d4d 100644
--- a/core/commands/custom.py
+++ b/core/commands/custom.py
@@ -16,7 +16,7 @@ class CustomCommandThread(threading.Thread):
self.daemon = True

def run(self):
- return self.cmd_func(*self.cmd_args,
+ return self.cmd_func( *self.cmd_args,
custom_environ=self.custom_environ)


diff --git a/core/commands/diff.py b/core/commands/diff.py
index 185eb6ee..f3581797 100644
--- a/core/commands/diff.py
+++ b/core/commands/diff.py
@@ -52,8 +52,7 @@ class GsDiffCommand(WindowCommand, GitCommand):
diff_view = diff_views[view_key]
else:
diff_view = util.view.get_scratch_view(self, "diff", read_only=True)
- if not title:
- title = (DIFF_CACHED_TITLE if in_cached_mode else DIFF_TITLE).format(os.path.basename(repo_path))
+
settings = diff_view.settings()
settings.set("git_savvy.repo_path", repo_path)
settings.set("git_savvy.file_path", file_path)
@@ -64,9 +63,41 @@ class GsDiffCommand(WindowCommand, GitCommand):
settings.set("git_savvy.diff_view.target_commit", target_commit)
settings.set("git_savvy.diff_view.show_diffstat", self.savvy_settings.get("show_diffstat", True))
settings.set("git_savvy.diff_view.disable_stage", disable_stage)
- settings.set("result_file_regex", r"^\+\+\+ b/(.+)$")
- settings.set("result_line_regex", r"^@@ -(\d+),")
+
+ # Clickable lines:
+ # (A) common/commands/view_manipulation.py | 1 +
+ # (B) --- a/common/commands/view_manipulation.py
+ # (C) +++ b/common/commands/view_manipulation.py
+ # (D) diff --git a/common/commands/view_manipulation.py b/common/commands/view_manipulation.py
+ #
+ # Now the actual problem is that Sublime only accepts a subset of modern reg expressions,
+ # B, C, and D are relatively straight forward because they match a whole line, and
+ # basically all other lines in a diff start with one of `[+- ]`.
+ FILE_RE = (
+ r"^(?:\s(?=.*\s+\|\s+\d+\s)|--- a\/|\+{3} b\/|diff .+b\/)"
+ # ^^^^^^^^^^^^^^^^^^^^^ (A)
+ # ^ one space, and then somewhere later on the line the pattern ` | 23 `
+ # ^^^^^^^ (B)
+ # ^^^^^^^^ (C)
+ # ^^^^^^^^^^^ (D)
+ r"(?<filename>\S[^|]*?)"
+ # ^ ! lazy to not match the trailing spaces, see below
+
+ r"(?:\s+\||$)"
+ # ^ (B), (C), (D)
+ # ^^^^^ (A) We must match the spaces here bc Sublime will not rstrip() the
+ # filename for us.
+ )
+
+ settings.set("result_file_regex", FILE_RE)
+ # Clickable line:
+ # @@ -69,6 +69,7 @@ class GsHandleVintageousCommand(TextCommand):
+ # ^^ we want the second (current) line offset of the diff
+ settings.set("result_line_regex", r"^@@ [^+]*\+(\d+),")
settings.set("result_base_dir", repo_path)
+
+ if not title:
+ title = (DIFF_CACHED_TITLE if in_cached_mode else DIFF_TITLE).format(os.path.basename(repo_path))
diff_view.set_name(title)
diff_view.set_syntax_file("Packages/GitSavvy/syntax/diff.sublime-syntax")
diff_views[view_key] = diff_view
112 changes: 112 additions & 0 deletions tests/test_diff_view.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import os
import re

import sublime

from unittesting import DeferrableTestCase
from GitSavvy.tests.mockito import expect, unstub, when, spy2

from GitSavvy.core.commands.diff import GsDiffCommand, GsDiffRefreshCommand


THIS_DIRNAME = os.path.dirname(os.path.realpath(__file__))


def fixture(name):
with open(os.path.join(THIS_DIRNAME, 'fixtures', name)) as f:
return f.read()


class TestDiffView(DeferrableTestCase):
def setUp(self):
original_window_id = sublime.active_window().id()
sublime.run_command("new_window")

yield lambda: sublime.active_window().id() != original_window_id

self.window = sublime.active_window()
self.view = sublime.active_window().new_file()
self.window.focus_view(self.view)
yield lambda: sublime.active_window().active_view().id() == self.view.id()
# make sure we have a window to work with
s = sublime.load_settings("Preferences.sublime-settings")
s.set("close_windows_when_empty", False)

def tearDown(self):
if self.view:
self.view.set_scratch(True)
self.view.window().focus_view(self.view)
self.view.close()
self.window.run_command('close_window')
unstub()

def test_extract_clickable_lines(self):
REPO_PATH = '/not/there'
FILE_PATH = '/not/there/README.md'
DIFF = fixture('diff_1.txt')

when(GsDiffRefreshCommand).git('diff', ...).thenReturn(DIFF)
cmd = GsDiffCommand(self.window)
when(cmd).get_repo_path().thenReturn(REPO_PATH)
cmd.run_async()

diff_view = self.window.active_view()
actual = diff_view.find_all_results()
# `find_all_results` only returns full filename-with-line matches.
# These match clicking on `@@ -52,8 +XX,7` lines
expected = [
('/not/there/core/commands/custom.py', 16, 0),
('/not/there/core/commands/diff.py', 52, 0),
('/not/there/core/commands/diff.py', 63, 0)
]

self.assertEqual(actual, expected)

def test_result_file_regex(self):
REPO_PATH = '/not/there'
FILE_PATH = '/not/there/README.md'
DIFF = fixture('diff_1.txt')

when(GsDiffRefreshCommand).git('diff', ...).thenReturn(DIFF)
cmd = GsDiffCommand(self.window)
when(cmd).get_repo_path().thenReturn(REPO_PATH)
cmd.run_async()

diff_view = self.window.active_view()
self.assertEqual(diff_view.substr(sublime.Region(0, diff_view.size())), DIFF)

regex = diff_view.settings().get('result_file_regex')

matches = re.findall(regex, DIFF, re.M)
expected = [
'core/commands/custom.py',
'core/commands/diff.py',
'core/commands/custom.py',
'core/commands/custom.py',
'core/commands/custom.py',
'core/commands/diff.py',
'core/commands/diff.py',
'core/commands/diff.py'
]
self.assertEqual(matches, expected)

matches = re.finditer(regex, DIFF, re.M)
actual = [
(m.group(0), diff_view.rowcol(m.span(1)[0])[0] + 1)
# Oh boy, a oneliner. ^^^^^^^^^^^^ start offset
# ^^^^^^ convert to (row, col)
# ^^^^^^^ only take row
# but add 1 for convenience
for m in matches
]
expected = [
(' core/commands/custom.py |', 1),
(' core/commands/diff.py |', 2),
('diff --git a/core/commands/custom.py b/core/commands/custom.py', 5),
('--- a/core/commands/custom.py', 7),
('+++ b/core/commands/custom.py', 8),
('diff --git a/core/commands/diff.py b/core/commands/diff.py', 18),
('--- a/core/commands/diff.py', 20),
('+++ b/core/commands/diff.py', 21)
]
self.assertEqual(actual, expected)

0 comments on commit a76966d

Please sign in to comment.