[Cl-darcs-cvs] r111 - cl-darcs/trunk
mhenoch at common-lisp.net
mhenoch at common-lisp.net
Thu Mar 15 22:27:17 UTC 2007
Author: mhenoch
Date: Thu Mar 15 17:27:17 2007
New Revision: 111
Added:
cl-darcs/trunk/send.lisp
Modified:
cl-darcs/trunk/cl-darcs.asd
Log:
Add send-to-file
Modified: cl-darcs/trunk/cl-darcs.asd
==============================================================================
--- cl-darcs/trunk/cl-darcs.asd (original)
+++ cl-darcs/trunk/cl-darcs.asd Thu Mar 15 17:27:17 2007
@@ -16,6 +16,7 @@
:trivial-gray-streams
;; SHA1, hex etc
:ironclad
+ :flexi-streams
;; Ironclad's SHA1 doesn't work with CLISP yet
#+clisp :sb-sha1
;; Files and directories
@@ -52,6 +53,7 @@
(:file "merge" :depends-on ("patch-core"))
(:file "unwind" :depends-on ("patch-core"))
(:file "equal" :depends-on ("patch-core"))
+ (:file "send" :depends-on ("patch-core"))
;; Franz' inflate implementation
#-allegro (:file "ifstar")
Added: cl-darcs/trunk/send.lisp
==============================================================================
--- (empty file)
+++ cl-darcs/trunk/send.lisp Thu Mar 15 17:27:17 2007
@@ -0,0 +1,108 @@
+;;; Copyright (C) 2007 Magnus Henoch
+;;;
+;;; This program is free software; you can redistribute it and/or
+;;; modify it under the terms of the GNU General Public License as
+;;; published by the Free Software Foundation; either version 2 of the
+;;; License, or (at your option) any later version.
+;;;
+;;; This program is distributed in the hope that it will be useful,
+;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;;; General Public License for more details.
+;;;
+;;; You should have received a copy of the GNU General Public License
+;;; along with this program; if not, write to the Free Software
+;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+(in-package :darcs)
+
+(defun send-to-file (our-repo file &key their-repo (select-patches :ask))
+ "Write new patches in OUR-REPO to FILE, suitable for sending by e-mail.
+\"New\" patches are those present in OUR-REPO but not in
+THEIR-REPO. If THEIR-REPO is NIL, use default repository
+specified in preferences.
+SELECT-PATCHES specifies how to select which patches to include.
+It can be one of:
+:ALL - include all patches
+:ASK - ask for each patch through Y-OR-N-P
+a function - call this function with a NAMED-PATCH object, and
+ include if it returns true"
+ (setf our-repo (fad:pathname-as-directory our-repo))
+ (unless their-repo
+ (unless (setf their-repo (car (get-preflist our-repo "defaultrepo")))
+ (error "No remote repositiory specified, and no default available.")))
+
+ (with-open-file (f file
+ :direction :output
+ :element-type '(unsigned-byte 8))
+
+ (let ((our-patchinfo (read-repo-patch-list our-repo))
+ (their-patchinfo (read-repo-patch-list their-repo)))
+ (multiple-value-bind (common only-ours only-theirs)
+ (get-common-and-uncommon our-patchinfo their-patchinfo)
+ (declare (ignore only-theirs))
+ (format t "~&Found these new patches:")
+ (dolist (p only-ours)
+ (format t "~& - ~A" p))
+
+ (let* ((all-our-patches
+ (mapcar (lambda (patchinfo)
+ (read-patch-from-repo our-repo patchinfo))
+ only-ours))
+ (patches-to-send
+ (if (or (eq select-patches :all)
+ (and (eq select-patches :ask)
+ (y-or-n-p "Send all patches?")))
+ all-our-patches
+ (select-patches all-our-patches
+ (if (functionp select-patches)
+ select-patches
+ (lambda (patch)
+ (display-patch patch *query-io*)
+ (y-or-n-p "Include patch ~A? " patch)))))))
+
+ (write-byte 10 f)
+ (write-sequence (string-to-bytes "New patches:") f)
+ (write-byte 10 f)
+ (write-byte 10 f)
+ (dolist (patch patches-to-send)
+ (write-patch patch f))
+ (write-byte 10 f)
+
+ (write-sequence (string-to-bytes "Context:") f)
+ (write-byte 10 f)
+ (write-byte 10 f)
+ ;; Context is in reverse order: latest applied first.
+ (setf common (nreverse common))
+
+ ;; XXX: handle tags properly.
+ (let ((latest-tag (member-if
+ (lambda (pi)
+ (string= (patchinfo-name pi) "TAG "
+ :end1 4))
+ common)))
+ ;; Here we just cut history after the latest tag. This
+ ;; should work in most cases.
+ (setf (cdr latest-tag) nil))
+
+ (dolist (patchinfo common)
+ (write-sequence (string-to-bytes
+ (with-output-to-string (strout)
+ (write-patchinfo patchinfo strout)))
+ f)
+ (write-byte 10 f))
+ (write-sequence (string-to-bytes "Patch bundle hash:") f)
+ (write-byte 10 f)
+ (write-sequence (string-to-bytes (hash-bundle patches-to-send)) f)
+ (write-byte 10 f))))))
+
+(defun hash-bundle (patches)
+ (let ((patches-as-vector
+ (flexi-streams:with-output-to-sequence (out)
+ (dolist (patch patches)
+ (write-patch patch out)))))
+ (setf patches-as-vector
+ (coerce patches-as-vector '(simple-array (unsigned-byte 8))))
+ (ironclad:byte-array-to-hex-string
+ #+clisp (sb-sha1:sha1sum-sequence patches-as-vector)
+ #-clisp (ironclad:digest-sequence :sha1 patches-as-vector))))
More information about the Cl-darcs-cvs
mailing list