[Cl-darcs-cvs] r6 - cl-darcs/trunk
mhenoch at common-lisp.net
mhenoch at common-lisp.net
Sat Jun 10 15:50:26 UTC 2006
Author: mhenoch
Date: Sat Jun 10 11:50:26 2006
New Revision: 6
Added:
cl-darcs/trunk/commute.lisp
Modified:
cl-darcs/trunk/cl-darcs.asd
Log:
Start hacking commutation.
Modified: cl-darcs/trunk/cl-darcs.asd
==============================================================================
--- cl-darcs/trunk/cl-darcs.asd (original)
+++ cl-darcs/trunk/cl-darcs.asd Sat Jun 10 11:50:26 2006
@@ -37,6 +37,7 @@
(:file "apply-patch" :depends-on ("patch-core"))
(:file "invert-patch" :depends-on ("patch-core"))
(:file "touching" :depends-on ("patch-core"))
+ (:file "commute" :depends-on ("patch-core"))
;; Franz' inflate implementation
#-allegro (:file "ifstar")
Added: cl-darcs/trunk/commute.lisp
==============================================================================
--- (empty file)
+++ cl-darcs/trunk/commute.lisp Sat Jun 10 11:50:26 2006
@@ -0,0 +1,58 @@
+(in-package :darcs)
+
+(defgeneric commute-patches (p2 p1)
+ (:documentation "Attempt to commute the patches P2 and P1.
+Return a list, (P1-NEW P2-NEW), such that applying P2-NEW and then
+P1-NEW has the same effect as applying P1 and then P2.
+If commutations fails, return nil."))
+
+(defmethod commute-patches :around ((p2 file-patch) (p1 file-patch))
+ "If P1 and P2 change different files, commutation is trivial."
+ (let ((p1-file (patch-filename p1))
+ (p2-file (patch-filename p2)))
+ (if (not (equal p1-file p2-file))
+ (list p1 p2)
+ (call-next-method))))
+
+(defmethod commute-patches ((p2 hunk-patch) (p1 hunk-patch))
+ "Attempt to commute the two hunk patches P1 and P2."
+ (assert (equal (patch-filename p1) (patch-filename p2)))
+ (with-accessors ((line1 hunk-line-number)
+ (old1 hunk-old-lines)
+ (new1 hunk-new-lines)) p1
+ (with-accessors ((line2 hunk-line-number)
+ (old2 hunk-old-lines)
+ (new2 hunk-new-lines)) p2
+ (cond
+ ((< (+ line1 (length new1)) line2)
+ ;; The first patch changes text before the second patch.
+ (list p1
+ (make-instance 'hunk-patch :filename (patch-filename p2)
+ :line-number (+ line2 (- (length new1)) (length old1))
+ :old old2 :new new2)))
+ ((< (+ line2 (length old2) line1))
+ ;; The second patch changes text before the first patch.
+ (list (make-instance 'hunk-patch :filename (patch-filename p1)
+ :line-number (+ line1 (length new2) (- (length old2)))
+ :old old1 :new new1)
+ p2))
+ ((and (= (+ line1 (length new1)) line2)
+ (notany #'zerop
+ (mapcar #'length (list old1 old2 new1 new2))))
+ ;; The first patch goes exactly until the beginning of the second patch.
+ (list p1
+ (make-instance 'hunk-patch :filename (patch-filename p2)
+ :line-number (+ line2 (- (length new1)) (length old1))
+ :old old2 :new new2)))
+ ((and (= (+ line2 (length old2)) line1)
+ (notany #'zerop
+ (mapcar #'length (list old1 old2 new1 new2))))
+ ;; The second patch goes exactly until the beginning of the first patch.
+ (list (make-instance 'hunk-patch :filename (patch-filename p1)
+ :line-number (+ line1 (length new2) (- (length old2)))
+ :old old1 :new new1)
+ p2))
+ (t
+ ;; In other cases, there is no failsafe way to commute the
+ ;; patches, so we give up.
+ nil)))))
More information about the Cl-darcs-cvs
mailing list