More work on porting diff kitten
This commit is contained in:
parent
d208670172
commit
3c550bcd28
48
tools/cmd/diff/collect.go
Normal file
48
tools/cmd/diff/collect.go
Normal file
@ -0,0 +1,48 @@
|
||||
// License: GPLv3 Copyright: 2023, Kovid Goyal, <kovid at kovidgoyal.net>
|
||||
|
||||
package diff
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
var _ = fmt.Print
|
||||
var path_name_map, remote_dirs map[string]string
|
||||
|
||||
type Collection struct {
|
||||
}
|
||||
|
||||
func create_collection(left, right string) (ans *Collection, err error) {
|
||||
path_name_map = make(map[string]string, 32)
|
||||
remote_dirs = make(map[string]string, 32)
|
||||
ans = &Collection{}
|
||||
left_stat, err := os.Stat(left)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if left_stat.IsDir() {
|
||||
err = ans.collect_files(left, right)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
pl, err := filepath.Abs(left)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pr, err := filepath.Abs(right)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
path_name_map[pl] = resolve_remote_name(pl, left)
|
||||
path_name_map[pr] = resolve_remote_name(pr, right)
|
||||
err = ans.add_change(pl, pr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
err = ans.finalize()
|
||||
return ans, err
|
||||
}
|
||||
@ -4,6 +4,7 @@ package diff
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"kitty/tools/cli"
|
||||
"kitty/tools/config"
|
||||
@ -26,6 +27,18 @@ var conf *Config
|
||||
var opts *Options
|
||||
var lp *loop.Loop
|
||||
|
||||
func isdir(path string) bool {
|
||||
if s, err := os.Stat(path); err == nil {
|
||||
return s.IsDir()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func exists(path string) bool {
|
||||
_, err := os.Stat(path)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
func main(_ *cli.Command, opts_ *Options, args []string) (rc int, err error) {
|
||||
opts = opts_
|
||||
conf, err = load_config(opts)
|
||||
@ -35,7 +48,19 @@ func main(_ *cli.Command, opts_ *Options, args []string) (rc int, err error) {
|
||||
if len(args) != 2 {
|
||||
return 1, fmt.Errorf("You must specify exactly two files/directories to compare")
|
||||
}
|
||||
left, right := args[0], args[1]
|
||||
if err = set_diff_command(conf.Diff_cmd); err != nil {
|
||||
return 1, err
|
||||
}
|
||||
left, right := get_remote_file(args[0]), get_remote_file(args[1])
|
||||
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)
|
||||
}
|
||||
if !exists(right) {
|
||||
return 1, fmt.Errorf("%s does not exist", right)
|
||||
}
|
||||
lp, err = loop.New()
|
||||
if err != nil {
|
||||
return 1, err
|
||||
|
||||
84
tools/cmd/diff/patch.go
Normal file
84
tools/cmd/diff/patch.go
Normal file
@ -0,0 +1,84 @@
|
||||
// License: GPLv3 Copyright: 2023, Kovid Goyal, <kovid at kovidgoyal.net>
|
||||
|
||||
package diff
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"kitty/tools/utils"
|
||||
"kitty/tools/utils/shlex"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var _ = fmt.Print
|
||||
|
||||
const GIT_DIFF = `git diff --no-color --no-ext-diff --exit-code -U_CONTEXT_ --no-index --`
|
||||
const DIFF_DIFF = `diff -p -U _CONTEXT_ --`
|
||||
|
||||
var diff_cmd []string
|
||||
|
||||
var GitExe = (&utils.Once[string]{Run: func() string {
|
||||
return utils.FindExe("git")
|
||||
}}).Get
|
||||
|
||||
var DiffExe = (&utils.Once[string]{Run: func() string {
|
||||
return utils.FindExe("diff")
|
||||
}}).Get
|
||||
|
||||
func find_differ() error {
|
||||
if GitExe() != "git" && exec.Command(GitExe(), "--help").Run() == nil {
|
||||
diff_cmd, _ = shlex.Split(GIT_DIFF)
|
||||
return nil
|
||||
}
|
||||
if DiffExe() != "diff" && exec.Command(DiffExe(), "--help").Run() == nil {
|
||||
diff_cmd, _ = shlex.Split(DIFF_DIFF)
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("Neither the git nor the diff programs were found in PATH")
|
||||
}
|
||||
|
||||
func set_diff_command(q string) error {
|
||||
if q == "auto" {
|
||||
return find_differ()
|
||||
}
|
||||
c, err := shlex.Split(q)
|
||||
if err == nil {
|
||||
diff_cmd = c
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func run_diff(file1, file2 string, num_of_context_lines int) (ok, is_different bool, patch string, err error) {
|
||||
context := strconv.Itoa(num_of_context_lines)
|
||||
cmd := utils.Map(func(x string) string {
|
||||
return strings.ReplaceAll(x, "_CONTEXT_", context)
|
||||
}, diff_cmd)
|
||||
// we resolve symlinks because git diff does not follow symlinks, while diff
|
||||
// does. We want consistent behavior, also for integration with git difftool
|
||||
// we always want symlinks to be followed.
|
||||
path1, err := filepath.EvalSymlinks(file1)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
path2, err := filepath.EvalSymlinks(file2)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
cmd = append(cmd, path1, path2)
|
||||
c := exec.Command(cmd[0], cmd[1:]...)
|
||||
stdout, stderr := bytes.Buffer{}, bytes.Buffer{}
|
||||
c.Stdout, c.Stderr = &stdout, &stderr
|
||||
err = c.Run()
|
||||
if err != nil {
|
||||
var e *exec.ExitError
|
||||
if errors.As(err, &e) && e.ExitCode() == 1 {
|
||||
return true, true, stdout.String(), nil
|
||||
}
|
||||
return false, false, stderr.String(), err
|
||||
}
|
||||
return true, false, stdout.String(), nil
|
||||
}
|
||||
@ -23,15 +23,7 @@ import (
|
||||
var _ = fmt.Print
|
||||
|
||||
var RgExe = (&utils.Once[string]{Run: func() string {
|
||||
ans := utils.Which("rg")
|
||||
if ans != "" {
|
||||
return ans
|
||||
}
|
||||
ans = utils.Which("rg", utils.DefaultExeSearchPaths()...)
|
||||
if ans == "" {
|
||||
ans = "rg"
|
||||
}
|
||||
return ans
|
||||
return utils.FindExe("rg")
|
||||
}}).Get
|
||||
|
||||
func get_options_for_rg() (expecting_args map[string]bool, alias_map map[string]string, err error) {
|
||||
|
||||
@ -18,15 +18,7 @@ import (
|
||||
var _ = fmt.Print
|
||||
|
||||
var SSHExe = (&utils.Once[string]{Run: func() string {
|
||||
ans := utils.Which("ssh")
|
||||
if ans != "" {
|
||||
return ans
|
||||
}
|
||||
ans = utils.Which("ssh", utils.DefaultExeSearchPaths()...)
|
||||
if ans == "" {
|
||||
ans = "ssh"
|
||||
}
|
||||
return ans
|
||||
return utils.FindExe("ssh")
|
||||
}}).Get
|
||||
|
||||
var SSHOptions = (&utils.Once[map[string]string]{Run: func() (ssh_options map[string]string) {
|
||||
|
||||
@ -47,3 +47,15 @@ func Which(cmd string, paths ...string) string {
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func FindExe(name string) string {
|
||||
ans := Which(name)
|
||||
if ans != "" {
|
||||
return ans
|
||||
}
|
||||
ans = Which(name, DefaultExeSearchPaths()...)
|
||||
if ans == "" {
|
||||
ans = name
|
||||
}
|
||||
return ans
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user