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 (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
"kitty/tools/cli"
|
"kitty/tools/cli"
|
||||||
"kitty/tools/config"
|
"kitty/tools/config"
|
||||||
@ -26,6 +27,18 @@ var conf *Config
|
|||||||
var opts *Options
|
var opts *Options
|
||||||
var lp *loop.Loop
|
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) {
|
func main(_ *cli.Command, opts_ *Options, args []string) (rc int, err error) {
|
||||||
opts = opts_
|
opts = opts_
|
||||||
conf, err = load_config(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 {
|
if len(args) != 2 {
|
||||||
return 1, fmt.Errorf("You must specify exactly two files/directories to compare")
|
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()
|
lp, err = loop.New()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 1, err
|
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 _ = fmt.Print
|
||||||
|
|
||||||
var RgExe = (&utils.Once[string]{Run: func() string {
|
var RgExe = (&utils.Once[string]{Run: func() string {
|
||||||
ans := utils.Which("rg")
|
return utils.FindExe("rg")
|
||||||
if ans != "" {
|
|
||||||
return ans
|
|
||||||
}
|
|
||||||
ans = utils.Which("rg", utils.DefaultExeSearchPaths()...)
|
|
||||||
if ans == "" {
|
|
||||||
ans = "rg"
|
|
||||||
}
|
|
||||||
return ans
|
|
||||||
}}).Get
|
}}).Get
|
||||||
|
|
||||||
func get_options_for_rg() (expecting_args map[string]bool, alias_map map[string]string, err error) {
|
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 _ = fmt.Print
|
||||||
|
|
||||||
var SSHExe = (&utils.Once[string]{Run: func() string {
|
var SSHExe = (&utils.Once[string]{Run: func() string {
|
||||||
ans := utils.Which("ssh")
|
return utils.FindExe("ssh")
|
||||||
if ans != "" {
|
|
||||||
return ans
|
|
||||||
}
|
|
||||||
ans = utils.Which("ssh", utils.DefaultExeSearchPaths()...)
|
|
||||||
if ans == "" {
|
|
||||||
ans = "ssh"
|
|
||||||
}
|
|
||||||
return ans
|
|
||||||
}}).Get
|
}}).Get
|
||||||
|
|
||||||
var SSHOptions = (&utils.Once[map[string]string]{Run: func() (ssh_options map[string]string) {
|
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 ""
|
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