[Cl-darcs-cvs] r74 - cl-darcs/trunk

mhenoch at common-lisp.net mhenoch at common-lisp.net
Mon Nov 27 21:41:32 UTC 2006


Author: mhenoch
Date: Mon Nov 27 16:41:32 2006
New Revision: 74

Modified:
   cl-darcs/trunk/diff.lisp
Log:
Handle added and removed files


Modified: cl-darcs/trunk/diff.lisp
==============================================================================
--- cl-darcs/trunk/diff.lisp	(original)
+++ cl-darcs/trunk/diff.lisp	Mon Nov 27 16:41:32 2006
@@ -22,39 +22,71 @@
   (setf original (make-upath original))
   (setf modified (make-upath modified))
   (let* ((original-lines
-	  (with-open-stream (in (open-upath original :binary t))
-	    (loop for line = (read-binary-line in nil)
-	       while line collect line)))
+	  (if (fad:file-exists-p original)
+	      (with-open-stream (in (open-upath original :binary t))
+		(loop for line = (read-binary-line in nil)
+		   while line collect line))
+	      :nonexistent))
 	 (modified-lines
-	  (with-open-stream (in (open-upath modified :binary t))
-	    (loop for line = (read-binary-line in nil)
-	       while line collect line)))
+	  (if (fad:file-exists-p modified)
+	      (with-open-stream (in (open-upath modified :binary t))
+		(loop for line = (read-binary-line in nil)
+		   while line collect line))
+	      :nonexistent))
 
 	 ;; using equalp is safe (i.e. non-case-clobbering), as
 	 ;; we use bytes instead of characters
-	 (opcodes (difflib:get-opcodes
-		   (make-instance 'difflib:sequence-matcher
-				  :a original-lines
-				  :b modified-lines
-				  :test-function #'equalp)))
+	 (opcodes (when (and (listp original-lines)
+			     (listp modified-lines))
+		    (difflib:get-opcodes
+		     (make-instance 'difflib:sequence-matcher
+				    :a original-lines
+				    :b modified-lines
+				    :test-function #'equalp))))
 
 	 patches)
+    (cond
+      ((and (eql original-lines :nonexistent)
+	    (eql modified-lines :nonexistent))
+       (error "Neither ~A nor ~A exist." original modified))
+      ((eql original-lines :nonexistent)
+       ;; Newly created file
+       ;; XXX: should we automatically add such files?
+       (list
+	(make-instance 'add-file-patch
+		       :filename filename)
+	(make-instance 'hunk-patch
+		       :filename filename
+		       :line-number 1
+		       :old ()
+		       :new modified-lines)))
+      ((eql modified-lines :nonexistent)
+       ;; Removed file
+       (list
+	(make-instance 'hunk-patch
+		       :filename filename
+		       :line-number 1
+		       :old original-lines
+		       :new ())
+	(make-instance 'rm-file-patch
+		       :filename filename)))
+      (t
+       ;; Possibly changed file
+       (dolist (opcode opcodes)
+	 (unless (eql (difflib:opcode-tag opcode) :equal)
+	   (push 
+	    (make-instance 'hunk-patch
+			   :filename filename
+			   :line-number (difflib:opcode-j1 opcode)
+			   :old (subseq original-lines
+					(difflib:opcode-i1 opcode)
+					(difflib:opcode-i2 opcode))
+			   :new (subseq modified-lines
+					(difflib:opcode-j1 opcode)
+					(difflib:opcode-j2 opcode)))
+	    patches)))
 
-    (dolist (opcode opcodes)
-      (unless (eql (difflib:opcode-tag opcode) :equal)
-	 (push 
-	  (make-instance 'hunk-patch
-			 :filename filename
-			 :line-number (difflib:opcode-j1 opcode)
-			 :old (subseq original-lines
-					      (difflib:opcode-i1 opcode)
-					      (difflib:opcode-i2 opcode))
-			 :new (subseq modified-lines
-					      (difflib:opcode-j1 opcode)
-					      (difflib:opcode-j2 opcode)))
-	  patches)))
-
-    (nreverse patches)))
+       (nreverse patches)))))
 
 (defun diff-binary-file (original modified &key filename)
   "Find changes between binary files ORIGINAL and MODIFIED.
@@ -96,34 +128,54 @@
 			      :type :wild
 			      :version :wild))
 	 (repo-wild (merge-pathnames wild repo))
+	 (pristine (upath-subdir repo '("_darcs" "pristine")))
+	 (pristine-wild (merge-pathnames wild pristine))
 	 (original-wild (merge-pathnames wild original))
 	 (modified-wild (merge-pathnames wild modified))
 	 patches)
-    (dolist (original-pathname (fad:list-directory original))
-      (let* ((modified-pathname
-	      (translate-pathname original-pathname original-wild modified-wild))
-	     (pathname-string
-	      (pathname-to-string
-	       (translate-pathname modified-pathname repo-wild wild))))
-	(cond
-	  ((fad:directory-pathname-p original-pathname)
-	   (format t "~&Skipping directory ~A for now" modified-pathname)
-	   (let ((last-element (car (last (pathname-directory original-pathname)))))
-	     (unless (file-boring-p repo last-element)
-	       ;; We have a non-boring subdirectory.
-	       (setf patches (nconc patches
-				    (diff-repo repo original-pathname modified-pathname))))))
+    ;; XXX: check if both directories exist
 
-	  ((file-binary-p repo pathname-string)
-	   (setf patches (nconc patches
-				(diff-binary-file original-pathname
-						  modified-pathname
-						  :filename pathname-string))))
-
-	  (t
-	   (setf patches (nconc patches 
-				(diff-file original-pathname
-					   modified-pathname
-					   :filename pathname-string)))))))
+    ;; With fad:list-directory, we get absolute pathnames.  We make
+    ;; them relative to the "root", so they can be compared.
+    (flet ((original-to-repo-relative (p)
+	     (translate-pathname p pristine-wild wild))
+	   (modified-to-repo-relative (p)
+	     (translate-pathname p repo-wild wild)))
+      ;; We list the files in the current directory, both in the
+      ;; original and the modified tree, and get the union.
+      (let* ((files-in-original 
+	      (mapcar #'original-to-repo-relative
+		      (fad:list-directory original)))
+	     (files-in-modified 
+	      (mapcar #'modified-to-repo-relative
+		      (fad:list-directory modified)))
+	     (files (nunion files-in-original files-in-modified
+			    :test #'equal)))
+	;; Then we iterate through the union.
+	(dolist (file files)
+	  (let ((original-pathname 
+		 (merge-pathnames file pristine))
+		(modified-pathname
+		 (merge-pathnames file repo))
+		(pathname-string
+		 (pathname-to-string file)))
+	    (cond
+	      ((fad:directory-pathname-p file)
+	       (unless (file-boring-p repo pathname-string)
+		 ;; We have a non-boring subdirectory.
+		 (setf patches (nconc patches
+				      (diff-repo repo original-pathname modified-pathname)))))
+
+	      ((file-binary-p repo pathname-string)
+	       (setf patches (nconc patches
+				    (diff-binary-file original-pathname
+						      modified-pathname
+						      :filename pathname-string))))
+
+	      (t
+	       (setf patches (nconc patches 
+				    (diff-file original-pathname
+					       modified-pathname
+					       :filename pathname-string)))))))
 
-    patches))
+	patches))))



More information about the Cl-darcs-cvs mailing list