163 |
;; strip prefix from filename |
;; strip prefix from filename |
164 |
;; returns /dev/null, if can't strip prefix |
;; returns /dev/null, if can't strip prefix |
165 |
(defsubst ediff-file-name-sans-prefix (filename prefix) |
(defsubst ediff-file-name-sans-prefix (filename prefix) |
166 |
(save-match-data |
(if prefix |
167 |
(if (string-match (concat "^" (regexp-quote prefix)) filename) |
(save-match-data |
168 |
(substring filename (match-end 0)) |
(if (string-match (concat "^" (if (stringp prefix) |
169 |
(concat "/null/" filename)))) |
(regexp-quote prefix) |
170 |
|
"")) |
171 |
|
filename) |
172 |
|
(substring filename (match-end 0)) |
173 |
|
(concat "/null/" filename))) |
174 |
|
filename) |
175 |
|
) |
176 |
|
|
177 |
|
|
178 |
|
|
266 |
count))) |
count))) |
267 |
|
|
268 |
;; Fix up the file names in the list using the argument FILENAME |
;; Fix up the file names in the list using the argument FILENAME |
269 |
;; Algorithm: find the first file's directory and cut it out from each file |
;; Algorithm: find the files' directories in the patch and, if a directory is |
270 |
;; name in the patch. Prepend the directory of FILENAME to each file in the |
;; absolute, cut it out from the corresponding file name in the patch. |
271 |
;; patch. In addition, the first file in the patch is replaced by FILENAME. |
;; Relative directories are not cut out. |
272 |
;; Each file is actually a file-pair of files found in the context diff header |
;; Prepend the directory of FILENAME to each resulting file (which came |
273 |
;; In the end, for each pair, we select the shortest existing file. |
;; originally from the patch). |
274 |
|
;; In addition, the first file in the patch document is replaced by FILENAME. |
275 |
|
;; Each file is actually a pair of files found in the context diff header |
276 |
|
;; In the end, for each pair, we ask the user which file to patch. |
277 |
;; Note: Ediff doesn't recognize multi-file patches that are separated |
;; Note: Ediff doesn't recognize multi-file patches that are separated |
278 |
;; with the `Index:' line. It treats them as a single-file patch. |
;; with the `Index:' line. It treats them as a single-file patch. |
279 |
;; |
;; |
284 |
;; directory part of filename |
;; directory part of filename |
285 |
(file-name-as-directory filename) |
(file-name-as-directory filename) |
286 |
(file-name-directory filename))) |
(file-name-directory filename))) |
287 |
;; Filename-spec is objA; at this point it is represented as |
;; In case 2 files are possible patch targets, the user will be offered |
288 |
;; (file1 . file2). We get it using ediff-get-session-objA |
;; to choose file1 or file2. In a multifile patch, if the user chooses |
289 |
;; directory part of the first file in the patch |
;; 1 or 2, this choice is preserved to decide future alternatives. |
290 |
(base-dir1 (file-name-directory |
chosen-alternative |
|
(car (ediff-get-session-objA-name (car ediff-patch-map))))) |
|
|
;; directory part of the 2nd file in the patch |
|
|
(base-dir2 (file-name-directory |
|
|
(cdr (ediff-get-session-objA-name (car ediff-patch-map))))) |
|
291 |
) |
) |
292 |
|
|
293 |
;; chop off base-dirs |
;; chop off base-dirs |
294 |
(mapcar (lambda (session-info) |
(mapcar (lambda (session-info) |
295 |
(let ((proposed-file-names |
(let* ((proposed-file-names |
296 |
(ediff-get-session-objA-name session-info))) |
;; Filename-spec is objA; it is represented as |
297 |
|
;; (file1 . file2). Get it using ediff-get-session-objA. |
298 |
|
(ediff-get-session-objA-name session-info)) |
299 |
|
;; base-dir1 is the dir part of the 1st file in the patch |
300 |
|
(base-dir1 (file-name-directory (car proposed-file-names))) |
301 |
|
;; directory part of the 2nd file in the patch |
302 |
|
(base-dir2 (file-name-directory (cdr proposed-file-names))) |
303 |
|
) |
304 |
|
;; If both base-dir1 and base-dir2 are relative, assume that |
305 |
|
;; these dirs lead to the actual files starting at the present |
306 |
|
;; directory. So, we don't strip these relative dirs from the |
307 |
|
;; file names. This is a heuristic intended to improve guessing |
308 |
|
(unless (or (file-name-absolute-p base-dir1) |
309 |
|
(file-name-absolute-p base-dir2)) |
310 |
|
(setq base-dir1 "" |
311 |
|
base-dir2 "")) |
312 |
(or (string= (car proposed-file-names) "/dev/null") |
(or (string= (car proposed-file-names) "/dev/null") |
313 |
(setcar proposed-file-names |
(setcar proposed-file-names |
314 |
(ediff-file-name-sans-prefix |
(ediff-file-name-sans-prefix |
315 |
(car proposed-file-names) base-dir1))) |
(car proposed-file-names) base-dir1))) |
316 |
(or (string= |
(or (string= |
317 |
(cdr proposed-file-names) "/dev/null") |
(cdr proposed-file-names) "/dev/null") |
318 |
(setcdr proposed-file-names |
(setcdr proposed-file-names |
319 |
(ediff-file-name-sans-prefix |
(ediff-file-name-sans-prefix |
320 |
(cdr proposed-file-names) base-dir2))) |
(cdr proposed-file-names) base-dir2))) |
321 |
)) |
)) |
322 |
ediff-patch-map) |
ediff-patch-map) |
323 |
|
|
324 |
;; take the given file name into account |
;; take the given file name into account |
334 |
(ediff-get-session-objA-name session-info))) |
(ediff-get-session-objA-name session-info))) |
335 |
(if (and (string-match "^/null/" (car proposed-file-names)) |
(if (and (string-match "^/null/" (car proposed-file-names)) |
336 |
(string-match "^/null/" (cdr proposed-file-names))) |
(string-match "^/null/" (cdr proposed-file-names))) |
337 |
;; couldn't strip base-dir1 and base-dir2 |
;; couldn't intuit the file name to patch, so |
338 |
;; hence, something is wrong |
;; something is amiss |
339 |
(progn |
(progn |
340 |
(with-output-to-temp-buffer ediff-msg-buffer |
(with-output-to-temp-buffer ediff-msg-buffer |
341 |
(ediff-with-current-buffer standard-output |
(ediff-with-current-buffer standard-output |
387 |
(f1-exists (file-exists-p file1)) |
(f1-exists (file-exists-p file1)) |
388 |
(f2-exists (file-exists-p file2))) |
(f2-exists (file-exists-p file2))) |
389 |
(cond |
(cond |
390 |
((and (< (length file2) (length file1)) |
((and |
391 |
f2-exists) |
;; The patch program prefers the shortest file as the patch |
392 |
|
;; target. However, this is a questionable heuristic. In an |
393 |
|
;; interactive program, like ediff, we can offer the user a |
394 |
|
;; choice. |
395 |
|
;; (< (length file2) (length file1)) |
396 |
|
(not f1-exists) |
397 |
|
f2-exists) |
398 |
;; replace file-pair with the winning file2 |
;; replace file-pair with the winning file2 |
399 |
(setcar session-file-object file2)) |
(setcar session-file-object file2)) |
400 |
((and (< (length file1) (length file2)) |
((and |
401 |
f1-exists) |
;; (< (length file1) (length file2)) |
402 |
|
(not f2-exists) |
403 |
|
f1-exists) |
404 |
;; replace file-pair with the winning file1 |
;; replace file-pair with the winning file1 |
405 |
(setcar session-file-object file1)) |
(setcar session-file-object file1)) |
406 |
((and f1-exists f2-exists |
((and f1-exists f2-exists |
407 |
(string= file1 file2)) |
(string= file1 file2)) |
408 |
(setcar session-file-object file1)) |
(setcar session-file-object file1)) |
409 |
|
((and f1-exists f2-exists (eq chosen-alternative 1)) |
410 |
|
(setcar session-file-object file1)) |
411 |
|
((and f1-exists f2-exists (eq chosen-alternative 2)) |
412 |
|
(setcar session-file-object file2)) |
413 |
((and f1-exists f2-exists) |
((and f1-exists f2-exists) |
414 |
(with-output-to-temp-buffer ediff-msg-buffer |
(with-output-to-temp-buffer ediff-msg-buffer |
415 |
(ediff-with-current-buffer standard-output |
(ediff-with-current-buffer standard-output |
425 |
Type `y' to use %s as the target; |
Type `y' to use %s as the target; |
426 |
Type `n' to use %s as the target. |
Type `n' to use %s as the target. |
427 |
" |
" |
428 |
file1 file2 file2 file1))) |
file1 file2 file1 file2))) |
429 |
(setcar session-file-object |
(setcar session-file-object |
430 |
(if (y-or-n-p (format "Use %s ? " file2)) |
(if (y-or-n-p (format "Use %s ? " file1)) |
431 |
file2 file1))) |
(progn |
432 |
|
(setq chosen-alternative 1) |
433 |
|
file1) |
434 |
|
(setq chosen-alternative 2) |
435 |
|
file2)) |
436 |
|
) |
437 |
(f2-exists (setcar session-file-object file2)) |
(f2-exists (setcar session-file-object file2)) |
438 |
(f1-exists (setcar session-file-object file1)) |
(f1-exists (setcar session-file-object file1)) |
439 |
(t |
(t |
444 |
(if (string= file1 file2) |
(if (string= file1 file2) |
445 |
(princ (format " |
(princ (format " |
446 |
%s |
%s |
447 |
is the target for this patch. However, this file does not exist." |
is assumed to be the target for this patch. However, this file does not exist." |
448 |
file1)) |
file1)) |
449 |
(princ (format " |
(princ (format " |
450 |
%s |
%s |
478 |
|
|
479 |
;; prompt for file, get the buffer |
;; prompt for file, get the buffer |
480 |
(defun ediff-prompt-for-patch-file () |
(defun ediff-prompt-for-patch-file () |
481 |
(let ((dir (cond (ediff-patch-default-directory) ; try patch default dir |
(let ((dir (cond (ediff-use-last-dir ediff-last-dir-patch) |
482 |
(ediff-use-last-dir ediff-last-dir-patch) |
(ediff-patch-default-directory) ; try patch default dir |
483 |
(t default-directory))) |
(t default-directory))) |
484 |
(coding-system-for-read ediff-coding-system-for-read)) |
(coding-system-for-read ediff-coding-system-for-read) |
485 |
(find-file-noselect |
patch-file-name) |
486 |
(read-file-name |
(setq patch-file-name |
487 |
(format "Patch is in file:%s " |
(read-file-name |
488 |
(cond ((and buffer-file-name |
(format "Patch is in file:%s " |
489 |
(equal (expand-file-name dir) |
(cond ((and buffer-file-name |
490 |
(file-name-directory buffer-file-name))) |
(equal (expand-file-name dir) |
491 |
(concat |
(file-name-directory buffer-file-name))) |
492 |
" (default " |
(concat |
493 |
(file-name-nondirectory buffer-file-name) |
" (default " |
494 |
")")) |
(file-name-nondirectory buffer-file-name) |
495 |
(t ""))) |
")")) |
496 |
dir buffer-file-name 'must-match)) |
(t ""))) |
497 |
|
dir buffer-file-name 'must-match)) |
498 |
|
(if (file-directory-p patch-file-name) |
499 |
|
(error "Patch file cannot be a directory: %s" patch-file-name) |
500 |
|
(find-file-noselect patch-file-name)) |
501 |
)) |
)) |
502 |
|
|
503 |
|
|
688 |
(ediff-maybe-checkout buf-to-patch) |
(ediff-maybe-checkout buf-to-patch) |
689 |
|
|
690 |
(ediff-with-current-buffer patch-diagnostics |
(ediff-with-current-buffer patch-diagnostics |
691 |
(insert-buffer patch-buf) |
(insert-buffer-substring patch-buf) |
692 |
(message "Applying patch ... ") |
(message "Applying patch ... ") |
693 |
;; fix environment for gnu patch, so it won't make numbered extensions |
;; fix environment for gnu patch, so it won't make numbered extensions |
694 |
(setq backup-style (getenv "VERSION_CONTROL")) |
(setq backup-style (getenv "VERSION_CONTROL")) |