                      (year (substring date 0 4))
                      (month (substring date 4 6))
                      (day (substring date 6 8))
+                     (hour (substring date 8 10))
+                     (min (substring date 10 12))
+                     (sec (substring date 12 14))
+                     (time (vc-annotate-convert-time
+                            (encode-time
+                             (vc-darcs-parse-integer sec)
+                             (vc-darcs-parse-integer min)
+                             (vc-darcs-parse-integer hour)
+                             (vc-darcs-parse-integer day)
+                             (vc-darcs-parse-integer month)
+                             (vc-darcs-parse-integer year))))
                      (begin (point)))
-                (insert (format "%-7s %s/%s/%s %s\n"
+                (insert (format "%-7s "
                                 (if (> (length author) 7)
                                     (substring author 0 7)
-                                    author)
-                                day month year
-                                line))))))))))
-
-(defun vc-darcs-parse-integer (s)
-  (let ((value 0)
-        (index 0)
-        (len (length s)))
-    (while (< index len)
-      (setq value (+ (* 10 value) (- (aref s index) ?0)))
-      (incf index))
-    value))
+                                    author)))
+                (insert
+                 (if (> (- now time) 0.9)
+                     (format "%s/%s/%s " day month (substring year 2 4))
+                     (format "%s:%s:%s " hour min sec)))
+                (insert line)
+                (insert "\n")
+                (add-text-properties
+                 begin (point)
+                 (list 'vc-darcs-annotate (cons rev time)))))))))))
+
+(defun vc-darcs-annotate-extract-revision-at-line ()
+  (car (get-text-property (point) 'vc-darcs-annotate (current-buffer))))
 
 (defun vc-darcs-annotate-time ()
-  (when (looking-at "........[0-9]")
-    (forward-char 8)
-    (and
-     (looking-at "\\(..\\)/\\(..\\)/\\(....\\)")
-     (let ((day (vc-darcs-parse-integer (match-string 1)))
-           (month (vc-darcs-parse-integer (match-string 2)))
-           (year (vc-darcs-parse-integer (match-string 3))))
-       (vc-annotate-convert-time
-        (encode-time 0 0 0 day month year))))))
+  (cdr (get-text-property (point) 'vc-darcs-annotate (current-buffer))))
 
 ;;; protection against editing files under _darcs
 ;;; adapted from an idea by Rob Giardine
 
 (defun vc-darcs-find-file-hook ()
   (let ((f (buffer-file-name (current-buffer))))
-    (and f (string-match "/_darcs" f) (not (string-match "/_darcs/prefs" f))
-         (let ((open-instead
-                (yes-or-no-p
-                 "This is a _darcs file, open the real file instead? ")))
+    (and f (vc-darcs-special-file-p f)
+         (let* ((candidate
+                 (let* ((f (buffer-file-name (current-buffer)))
+                        (match
+                         (and f (string-match
+                                 "/_darcs/\\(current\\|pristine\\)/" f))))
+                   (and match
+                        (concat (substring f 0 (match-beginning 0))
+                                "/"
+                                (substring f (match-end 0))))))
+                (open-instead
+                 (and candidate
+                      (yes-or-no-p
+                       "This is a _darcs file, open the real file instead? "))))
            (cond
              (open-instead
-              (let* ((f (buffer-file-name (current-buffer)))
-                     (match
-                      (and f (string-match
-                              "/_darcs/\\(current\\|pristine\\)/" f))))
-                (unless match
-                  (error "Couldn't find alternate file name"))
-                (find-alternate-file
-                 (concat (substring f 0 (match-beginning 0))
-                         "/"
-                         (substring f (match-end 0))))))
+              (find-alternate-file candidate))
              (t
               (setq buffer-read-only t)
               (push '(:propertize "_DARCS-FILE:" face font-lock-warning-face)

  :type 'boolean
  :group 'vc-darcs)

(defcustom vc-darcs-trust-file-times t
  "*Whether to trust filesystem times when determining the state of a file.
If this is non-nil, vc will consider that a file is up-to-date if its
modification time matches the one of the pristine file.  This may
speed some operations quite a bit, but is potentially unsafe,
especially on non-POSIX filesystems (e.g. vfat).

If you set this, you probably also want to set

  ALL ignore-times

in your Darcs preferences."
  :type 'boolean
  :group 'vc-darcs)

(defun vc-darcs-root-directory (file)
  "Return the root darcs repository directory for FILE, or nil if
there is none."
  (let ((dir (file-name-directory (expand-file-name file)))
        (olddir "/"))
    (while (and (not (equal dir olddir))
                (not (file-directory-p (concat dir "/_darcs"))))
      (setq olddir dir
            dir (file-name-directory (directory-file-name dir))))
    (and (not (equal dir olddir)) dir)))

(defun vc-darcs-darcs-directory (file)
  "Return the darcs directory for FILE, or nil if there is none."
  (let ((dir (vc-darcs-root-directory file)))
    (and dir (concat dir "_darcs/"))))

(defun vc-darcs-pristine-directory (root)
  "Return the pristine directory of repository ROOT."
  (let* ((root (if (eq ?/ (aref root (- (length root) 1)))
                  root
                  (concat root "/")))
         (pristine (concat root "_darcs/pristine/"))
         (current (concat root "_darcs/current/")))
    (or
     (and (file-directory-p pristine) pristine)
     (and (file-directory-p current) current))))

(defun vc-darcs-pristine-file (file)
  "Return the pristine file corresponding to FILE."
  (let* ((root (vc-darcs-root-directory file))
         (pristine (and root (vc-darcs-pristine-directory root))))
    (when (and root pristine
               (string-match (concat "^" (regexp-quote root) "\\(.*\\)") file))
      (concat pristine (match-string 1 file)))))

(defun vc-darcs-do-command (command okstatus file &rest flags)
  "Run darcs COMMAND using `vc-do-command', passing OKSTATUS and FILE
along with FLAGS."
  (let ((arguments (cdr (assq command vc-darcs-program-arguments))))
    (apply #'vc-do-command nil okstatus
           vc-darcs-program-name file (symbol-name command)
           (append arguments flags))))

(defun vc-darcs-report-error ()
  "Report a darcs error in the current buffer."
  (goto-char (point-max))
  (let ((found (search-backward "Fail:" nil t)))
    (if found
        (error (buffer-substring found (point-max)))
        (error (buffer-substring (max 0 (- (point-max) 1000))
                                 (point-max))))))

(defmacro vc-darcs-with-error-reporting (&rest body)
  (list 'condition-case 'nil 
        (if (null (cdr body)) (car body) (cons 'progn body))
        '(vc-darcs-report-error)))

(defun vc-darcs-changes (&optional file &rest flags)
  "Return a list of hashes of the patches that touch FILE in inverse order."
  (with-temp-buffer
    (apply #'vc-do-command t nil vc-darcs-program-name
           (and file (file-name-nondirectory file))
           "changes" "--xml" flags)
    (let ((changes (xml-parse-region 1 (point-max))))
      (unless (and (null (cdr changes))

         (log (if match
                  (substring comment (match-end 0))
                  "")))
    (vc-darcs-do-command 'record 'async nil "-a" "--pipe" file)
    (with-current-buffer (get-buffer "*vc*")
      (process-send-string nil
                           (format "%s\n%s\n%s\n%s"
                                   date vc-darcs-mail-address patch-name log))
      (process-send-eof))))

(defun vc-darcs-find-version (file rev buffer)
  "This gets revision REV of FILE from the darcs repository."
  (let ((rev (vc-darcs-rev-to-hash rev file)))
    (apply #'vc-do-command buffer 0 vc-darcs-program-name file
           "show" "contents"
           (and rev (list "--match" (concat "hash " rev))))))

(defun vc-darcs-checkout (file &optional editable rev)
  "Check out FILE from the Darcs repository.
EDITABLE is ignored."
  (let ((rev (vc-darcs-rev-to-hash rev file)))
    (when (and rev (not (equal rev (vc-darcs-workfile-version file))))
      (error "Cannot checkout old revisions with darcs."))
    (or (file-exists-p file)
        (vc-darcs-do-command "revert" 0 file "-a"))))

(defun vc-darcs-revert (file &optional contents-done)
  "Revert FILE back to the current workfile version."
  (vc-darcs-do-command "revert" 0 file "-a"))

(defun vc-darcs-print-log (file)
  "Print the logfile for the current darcs repository to the *vc* buffer."
  (vc-darcs-do-command 'changes 'async (and (not vc-darcs-full-log) file)))

(defun vc-darcs-diff (file &optional rev1 rev2 buffer)
  "Show the differences in FILE between revisions REV1 and REV2."
  (let* ((async (not vc-disable-async-diff))
         (rev1 (vc-darcs-rev-to-hash rev1 file t))
         (rev2 (vc-darcs-rev-to-hash rev2 file))
         (arguments (cdr (assq 'diff vc-darcs-program-arguments)))
         (from (and rev1 (list "--from-match" (concat "hash " rev1))))
         (to (and rev2 (list "--to-match" (concat "hash " rev2)))))
    (let ((status (apply #'vc-do-command (or buffer "*vc-diff*")
                         (if async 'async 1)
                         vc-darcs-program-name file
                         "diff"
                         (append from to arguments))))
      (if async 1 status))))

(defun vc-darcs-rename-file (old new)
  "Rename the file OLD to NEW in the darcs repository."
  (vc-darcs-do-command 'mv 0 nil (expand-file-name old) (expand-file-name new)))

(defun vc-darcs-delete-file (file)
  (delete-file (expand-file-name file)))

(defun vc-darcs-parse-integer (string)
  (let* ((c (read-from-string string))
         (n (car c)))
    (if (integerp n) n 0)))

(defun vc-darcs-annotate-command (file buffer &optional rev)
  "Produce an annotated display of fiLE in BUFFER.
For Darcs, hashes and times are stored in text properties."
  (let* ((rev (vc-darcs-rev-to-hash rev file))
         (data
          (with-temp-buffer
            (apply #'vc-do-command t 0 vc-darcs-program-name file
                   "annotate" "--xml"
                   (and rev (list "--match" (concat "hash " rev))))
            (let ((output (xml-parse-region 1 (point-max))))
