* Curse that hunk!
@ 2021-08-11 19:53 Alan Mackenzie
2021-08-11 21:24 ` Stefan Monnier
2021-08-12 7:49 ` Juri Linkov
0 siblings, 2 replies; 3+ messages in thread
From: Alan Mackenzie @ 2021-08-11 19:53 UTC (permalink / raw)
To: emacs-devel
Hello, Emacs.
I found myself this evening trying to patch a file with a 1400 line hunk
which didn't (quite) match. This happens to me quite often, though it's
never been as bad as a 1400 line mismatch before.
Finding the point where a patch hunk's old lines fail to match the file
being patched is tedious and error prone. There surely ought to be a
Lisp program, perhaps in diff.el which would fine these differences.
This evening, I hacked together the following command which, though
ugly, did the job:
(defun crack-patch (p-buf s-buf)
(interactive "b\nb")
(let (str
)
(catch 'found
(while (progn (set-buffer p-buf) (not (eobp)))
(re-search-forward "^\\([ -]\\)\\(.*\\)$")
(setq str (match-string-no-properties 2))
(set-buffer s-buf)
(message "point: %s" (point))
(unless (looking-at (concat "^"
(regexp-quote str) "$"))
(throw 'found nil))
(forward-line)))))
To use it, type in the p-buf, the name of the patch buffer, and s-buf,
the name of the source buffer you want to patch. In p-buf, point should
be at the start of a context or - line, and in s-buf, point should be at
the corresponding point. The command will run and stop at the first
discrepancy between the two.
As I say, very rough and ready, but I managed to get my 1400 line patch
hunk working with it.
Surely there ought to be some facility like this in Emacs?
--
Alan Mackenzie (Nuremberg, Germany).
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: Curse that hunk!
2021-08-11 19:53 Curse that hunk! Alan Mackenzie
@ 2021-08-11 21:24 ` Stefan Monnier
2021-08-12 7:49 ` Juri Linkov
1 sibling, 0 replies; 3+ messages in thread
From: Stefan Monnier @ 2021-08-11 21:24 UTC (permalink / raw)
To: Alan Mackenzie; +Cc: emacs-devel
Alan Mackenzie [2021-08-11 19:53:46] wrote:
> Finding the point where a patch hunk's old lines fail to match the file
> being patched is tedious and error prone. There surely ought to be a
> Lisp program, perhaps in diff.el which would fine these differences.
[...]
> Surely there ought to be some facility like this in Emacs?
It's been on my todo-list for quite some years to provide some command
to turn a diff into an diff3 conflict (after which you can use
`smerge-mode` to do the rest of the job).
At some point I thought I had found my solution in the form of Wiggle
https://neil.brown.name/wiggle/ but when I tried it (like 10 years ago)
it either crashed or gave weird results.
I suspect that a lower-tech solution that applies to a single hunk at
a time and where the user provides manually the region covered by the
hunk should be easy enough to write, tho maybe a bit cumbersome to use
(I guess we could have a `diff-select-hunk-for-application` command
that records the hunk somewhere and then a `diff-apply-selected-hunk`
to use in the destination buffer).
Maybe a better option is to have a command which turns the hunk into an
diff3 conflict at some location that's auto-selected using a very
naive/simple algorithm, and then provide smerge commands to move the
resulting conflict.
Stefan
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: Curse that hunk!
2021-08-11 19:53 Curse that hunk! Alan Mackenzie
2021-08-11 21:24 ` Stefan Monnier
@ 2021-08-12 7:49 ` Juri Linkov
1 sibling, 0 replies; 3+ messages in thread
From: Juri Linkov @ 2021-08-12 7:49 UTC (permalink / raw)
To: Alan Mackenzie; +Cc: emacs-devel
> Finding the point where a patch hunk's old lines fail to match the file
> being patched is tedious and error prone. There surely ought to be a
> Lisp program, perhaps in diff.el which would fine these differences.
If you need only to find the point of mismatch, then what I do
is just remove the diff indicators from the diff buffers with
(replace-regexp "^[+-]" ""), and then compare two buffers
with the usual compare-windows or ediff-buffers.
Also sometimes there is a need to isearch a multi-line string
in the diff buffer. For such cases I wrote an isearch mode that
ignores diff-mode hunk indicators such as '+' or '-' at the
beginning of the diff lines. For example, put the deleted hunk
to the search string, then search it for the next match,
and it will find the hunk moved to another part of the file:
#+begin_src emacs-lisp
(isearch-define-mode-toggle diff-hunk "+" diff-hunk-to-regexp "\
Ignore diff-mode hunk indicators such as ‘+’ or ‘-’ at bol.")
(defun diff-hunk-to-regexp (string &optional _lax _from)
(replace-regexp-in-string
"[[:space:]]+" "[[:space:]]+"
(replace-regexp-in-string
"^\\(\\\\\\+\\|-\\)" "\\(^\\)[+-]"
(regexp-quote string) nil t)))
(add-hook 'diff-mode-hook
(lambda ()
(setq-local search-default-mode 'diff-hunk-to-regexp)))
#+end_src
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2021-08-12 7:49 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2021-08-11 19:53 Curse that hunk! Alan Mackenzie
2021-08-11 21:24 ` Stefan Monnier
2021-08-12 7:49 ` Juri Linkov
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/emacs.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).