branch: elpa/hyperdrive
commit a6b98c19c366900ed0ba6610d9130fa1f62cc832
Author: Adam Porter <[email protected]>
Commit: Joseph Turner <[email protected]>

    Fix: Allow visiting two hyperdrive files with the same name
---
 hyperdrive-lib.el | 47 ++++++++++++++++++++++++++++++-----------------
 1 file changed, 30 insertions(+), 17 deletions(-)

diff --git a/hyperdrive-lib.el b/hyperdrive-lib.el
index 0fbbbf5609..bf3cfdf23a 100644
--- a/hyperdrive-lib.el
+++ b/hyperdrive-lib.el
@@ -567,11 +567,7 @@ echo area when the request for the file is made."
                      ;; Entry is a writable file: create a new buffer
                      ;; that will be saved to its path.
 
-                     ;; FIXME: Don't rely on buffer name to find existing
-                     ;; buffers visiting the same entry.
-                     (if-let ((buffer
-                               (get-buffer
-                                (h//format-entry entry h/buffer-name-format))))
+                     (if-let ((buffer (h//find-buffer-visiting entry)))
                          ;; Buffer already exists: likely the user deleted the
                          ;; entry without killing the buffer.  Switch to the
                          ;; buffer and alert the user that the entry no longer
@@ -1537,28 +1533,44 @@ In other words, this avoids the situation where a 
buffer called
 both point to the same content.
 
 Affected by option `hyperdrive-reuse-buffers', which see."
-  (let* ((buffer-name (h//format-entry
-                       entry h/buffer-name-format))
+  (let* ((existing-buffer
+          (h//find-buffer-visiting entry (eq 'any-version h/reuse-buffers)))
          (buffer
-          (or (and (eq 'any-version h/reuse-buffers)
-                   (h//find-buffer-visiting entry))
-              (get-buffer-create buffer-name))))
+          (if (not existing-buffer)
+              ;; No existing buffer visiting entry: make new buffer.
+              (get-buffer-create (h//generate-new-buffer-name entry))
+            ;; Existing buffer visiting entry.
+            (unless (eq (he/version entry)
+                        (he/version
+                         (buffer-local-value 'hyperdrive-current-entry
+                                             existing-buffer)))
+              ;; Entry versions differ: rename buffer.
+              (with-current-buffer existing-buffer
+                (rename-buffer (h//generate-new-buffer-name entry))))
+            existing-buffer)))
     (with-current-buffer buffer
-      (rename-buffer buffer-name)
       ;; NOTE: We do not erase the buffer because, e.g. the directory
       ;; handler needs to record point before it erases the buffer.
       (h/mode)
       (setq-local h/current-entry entry)
       (current-buffer))))
 
-(defun h//find-buffer-visiting (entry)
-  "Return a buffer visiting ENTRY, or nil if none exist."
+(defun h//generate-new-buffer-name (entry)
+  "Return a new, unique name for a buffer visiting ENTRY."
+  ;; TODO: Use in calls to `h//get-buffer-create', et al.
+  (let ((buffer-name (h//format-entry entry h/buffer-name-format)))
+    (generate-new-buffer-name buffer-name)))
+
+(defun h//find-buffer-visiting (entry &optional any-version-p)
+  "Return a buffer visiting ENTRY, or nil if none exist.
+If ANY-VERSION-P, return the first buffer showing ENTRY at any
+version."
   ;; If `match-buffers' returns more than one buffer, we ignore the others.
   (car (match-buffers
         (lambda (buffer)
           (and-let* ((local-entry
                       (buffer-local-value 'hyperdrive-current-entry buffer)))
-            (he/equal-p entry local-entry))))))
+            (he/equal-p entry local-entry any-version-p))))))
 
 (defun h//format-entry (entry &optional format formats)
   "Return ENTRY formatted according to FORMAT.
@@ -1666,16 +1678,17 @@ When BUFFER is nil, act on current buffer."
       (delete-all-overlays)
       (set-text-properties (point-min) (point-max) nil))))
 
-(defun he/equal-p (a b)
+(defun he/equal-p (a b &optional any-version-p)
   "Return non-nil if hyperdrive entries A and B are equal.
-Compares only public key, version, and path."
+Compares only public key, version, and path.  If ANY-VERSION-P,
+treat A and B as the same entry regardless of version."
   (pcase-let (((cl-struct hyperdrive-entry (path a-path) (version a-version)
                           (hyperdrive (cl-struct hyperdrive (public-key 
a-key))))
                a)
               ((cl-struct hyperdrive-entry (path b-path) (version b-version)
                           (hyperdrive (cl-struct hyperdrive (public-key 
b-key))))
                b))
-    (and (eq a-version b-version)
+    (and (or any-version-p (eq a-version b-version))
          (equal a-path b-path)
          (equal a-key b-key))))
 

Reply via email to