diff kitten: Allow diffing remote files easily via ssh

See #727
This commit is contained in:
Kovid Goyal
2019-10-04 09:08:22 +05:30
parent 53ab7617ca
commit 802da7087c
2 changed files with 22 additions and 2 deletions

View File

@@ -13,6 +13,8 @@ To update |kitty|, :doc:`follow the instructions <binary>`.
- When drawing unicode symbols that are followed by spaces, use multiple cells - When drawing unicode symbols that are followed by spaces, use multiple cells
to avoid resized or cut-off glyphs (:iss:`1452`) to avoid resized or cut-off glyphs (:iss:`1452`)
- diff kitten: Allow diffing remote files easily via ssh (:iss:`727`)
0.14.6 [2019-09-25] 0.14.6 [2019-09-25]
--------------------- ---------------------

View File

@@ -2,14 +2,17 @@
# vim:fileencoding=utf-8 # vim:fileencoding=utf-8
# License: GPL v3 Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net> # License: GPL v3 Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net>
import atexit
import os import os
import signal import signal
import subprocess
import sys import sys
import tempfile
import warnings import warnings
from collections import defaultdict from collections import defaultdict
from contextlib import suppress
from functools import partial from functools import partial
from gettext import gettext as _ from gettext import gettext as _
from contextlib import suppress
from kitty.cli import CONFIG_HELP, parse_args from kitty.cli import CONFIG_HELP, parse_args
from kitty.constants import appname from kitty.constants import appname
@@ -506,7 +509,7 @@ def showwarning(message, category, filename, lineno, file=None, line=None):
showwarning.warnings = [] showwarning.warnings = []
help_text = 'Show a side-by-side diff of the specified files/directories' help_text = 'Show a side-by-side diff of the specified files/directories. You can also use ssh:hostname:remote-file-path to diff remote files.'
usage = 'file_or_directory_left file_or_directory_right' usage = 'file_or_directory_left file_or_directory_right'
@@ -516,6 +519,20 @@ def terminate_processes(processes):
os.kill(pid, signal.SIGKILL) os.kill(pid, signal.SIGKILL)
def get_remote_file(path):
if path.startswith('ssh:'):
parts = path.split(':', 2)
if len(parts) == 3:
hostname, rpath = parts[1:]
with tempfile.NamedTemporaryFile(suffix='-' + os.path.basename(rpath), prefix='remote:', delete=False) as tf:
atexit.register(os.remove, tf.name)
p = subprocess.Popen(['ssh', hostname, 'cat', rpath], stdout=tf)
if p.wait() != 0:
raise SystemExit(p.returncode)
return tf.name
return path
def main(args): def main(args):
warnings.showwarning = showwarning warnings.showwarning = showwarning
args, items = parse_args(args[1:], OPTIONS, usage, help_text, 'kitty +kitten diff') args, items = parse_args(args[1:], OPTIONS, usage, help_text, 'kitty +kitten diff')
@@ -528,6 +545,7 @@ def main(args):
opts = init_config(args) opts = init_config(args)
set_diff_command(opts.diff_cmd) set_diff_command(opts.diff_cmd)
lines_for_path.replace_tab_by = opts.replace_tab_by lines_for_path.replace_tab_by = opts.replace_tab_by
left, right = map(get_remote_file, (left, right))
for f in left, right: for f in left, right:
if not os.path.exists(f): if not os.path.exists(f):
raise SystemExit('{} does not exist'.format(f)) raise SystemExit('{} does not exist'.format(f))