From a59a3479035371d93f62a59459c16331d91775df Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sat, 3 May 2025 15:53:29 +0530 Subject: [PATCH] diff kitten: Allow diffing named pipes Fixes #8597 --- docs/changelog.rst | 2 ++ kittens/diff/main.go | 44 +++++++++++++++++++++++++++++++++++++------- 2 files changed, 39 insertions(+), 7 deletions(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index 4e92fd6f3..9515e1dfe 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -129,6 +129,8 @@ Detailed list of changes - diff kitten: Add half page and full page scroll vim-like bindings (:pull:`8514`) +- diff kitten: Allow diffing named pipes (:iss:`8597`) + - Fix a regression that caused automatic color themes to not be re-applied after config file reload (:iss:`8530`) - Wayland: When the compositor supports the `xdg-system-bell diff --git a/kittens/diff/main.go b/kittens/diff/main.go index 174ca28ec..3f48ea5c0 100644 --- a/kittens/diff/main.go +++ b/kittens/diff/main.go @@ -6,6 +6,7 @@ import ( "archive/tar" "bytes" "fmt" + "io" "io/fs" "os" "os/exec" @@ -43,9 +44,33 @@ func isdir(path string) bool { return false } -func exists(path string) bool { - _, err := os.Stat(path) - return err == nil +var temp_files []string + +func resolve_path(path string) (ans string, err error) { + var s fs.FileInfo + if s, err = os.Stat(path); err != nil { + return + } else { + if s.Mode()&fs.ModeNamedPipe != 0 { + var src, dest *os.File + if src, err = os.Open(path); err != nil { + return + } + defer src.Close() + if dest, err = os.CreateTemp("", fmt.Sprintf("*-pipe-%d", len(temp_files)+1)); err != nil { + return + } + defer dest.Close() + temp_files = append(temp_files, dest.Name()) + if _, err = io.Copy(dest, src); err != nil { + return + } + return dest.Name(), nil + + } else { + return path, nil + } + } } func get_ssh_file(hostname, rpath string) (string, error) { @@ -136,11 +161,16 @@ func main(_ *cli.Command, opts_ *Options, args []string) (rc int, err error) { if isdir(left) != isdir(right) { return 1, fmt.Errorf("The items to be diffed should both be either directories or files. Comparing a directory to a file is not valid.'") } - if !exists(left) { - return 1, fmt.Errorf("%s does not exist", left) + defer func() { + for _, path := range temp_files { + os.Remove(path) + } + }() + if left, err = resolve_path(left); err != nil { + return 1, err } - if !exists(right) { - return 1, fmt.Errorf("%s does not exist", right) + if right, err = resolve_path(right); err != nil { + return 1, err } lp, err = loop.New() loop.MouseTrackingMode(lp, loop.BUTTONS_AND_DRAG_MOUSE_TRACKING)