                          "Emacsmirror")
                  package)))))
 
+(defvar straight--recipe-cache (make-hash-table :test 'equal))
+
 (defun straight--convert-recipe (melpa-style-recipe)
-  (let* ((recipe-specified-p (listp melpa-style-recipe))
-         (full-melpa-style-recipe
-          (if recipe-specified-p
-              melpa-style-recipe
-            (let ((package melpa-style-recipe))
-              (straight--lookup-recipe package)))))
-    (cl-destructuring-bind (package . plist) full-melpa-style-recipe
-      (straight--with-plist plist
-          (local-repo repo url)
-        (let ((package (symbol-name package)))
-          (straight--put plist :package package)
-          (unless local-repo
-            (straight--put plist :local-repo
-                           (or (when repo
-                                 (replace-regexp-in-string
-                                  "^.+/" "" repo))
-                               ;; The following is a half-hearted
-                               ;; attempt to turn arbitrary URLs into
-                               ;; repository names.
-                               (let ((regexp "^.*/\\(.+\\)\\.git$"))
-                                 (when (and url (string-match regexp url))
-                                   (match-string 1 url)))
-                               package)))
-          ;; This code is here to deal with complications that can
-          ;; arise with manual recipe specifications when multiple
-          ;; packages are versioned in the same repository.
-          ;;
-          ;; Specifically, let's suppose packages `swiper' and `ivy'
-          ;; are both versioned in repository "swiper", and let's
-          ;; suppose that I load both of them in my init-file (`ivy'
-          ;; first and then `swiper'). Now suppose that I discover a
-          ;; bug in `ivy' and fix it in my fork, so that (until my fix
-          ;; is merged) I need to provide an explicit recipe in my
-          ;; init-file's call to `straight-use-package' for `ivy', in
-          ;; order to use my fork. That will cause a conflict, because
-          ;; the recipe for `swiper' is automatically taken from
-          ;; MELPA, and it does not point at my fork, but instead at
-          ;; the official repository. To fix the problem, I would have
-          ;; to specify my fork in the recipe for `swiper' (and also
-          ;; `counsel', a third package versioned in the same
-          ;; repository). That violates DRY and is a pain.
-          ;;
-          ;; Instead, this code makes it so that if a recipe has been
-          ;; automatically retrieved from a package source (for
-          ;; example, MELPA, GNU ELPA, or Emacsmirror), and the
-          ;; `:local-repo' specified in that recipe has already been
-          ;; used for another package, then the configuration for that
-          ;; repository will silently be copied over, and everything
-          ;; should "just work".
-          (unless recipe-specified-p
-            (straight--with-plist plist
-                (local-repo)
-              (when-let (original-recipe (gethash local-repo
-                                                  straight--repo-cache))
-                (dolist (keyword straight--fetch-keywords)
-                  (when-let ((value (plist-get original-recipe keyword)))
-                    (straight--put plist keyword value))))))
-          plist)))))
+  (or (and (symbolp melpa-style-recipe)
+           (gethash (symbol-name melpa-style-recipe) straight--recipe-cache))
+      (let* ((recipe-specified-p (listp melpa-style-recipe))
+             (full-melpa-style-recipe
+              (if recipe-specified-p
+                  melpa-style-recipe
+                (let ((package melpa-style-recipe))
+                  (straight--lookup-recipe package)))))
+        (cl-destructuring-bind (package . plist) full-melpa-style-recipe
+          (straight--with-plist plist
+              (local-repo repo url)
+            (let ((package (symbol-name package)))
+              (straight--put plist :package package)
+              (unless local-repo
+                (straight--put plist :local-repo
+                               (or (when repo
+                                     (replace-regexp-in-string
+                                      "^.+/" "" repo))
+                                   ;; The following is a half-hearted
+                                   ;; attempt to turn arbitrary URLs into
+                                   ;; repository names.
+                                   (let ((regexp "^.*/\\(.+\\)\\.git$"))
+                                     (when (and url (string-match regexp url))
+                                       (match-string 1 url)))
+                                   package)))
+              ;; This code is here to deal with complications that can
+              ;; arise with manual recipe specifications when multiple
+              ;; packages are versioned in the same repository.
+              ;;
+              ;; Specifically, let's suppose packages `swiper' and `ivy'
+              ;; are both versioned in repository "swiper", and let's
+              ;; suppose that I load both of them in my init-file (`ivy'
+              ;; first and then `swiper'). Now suppose that I discover a
+              ;; bug in `ivy' and fix it in my fork, so that (until my fix
+              ;; is merged) I need to provide an explicit recipe in my
+              ;; init-file's call to `straight-use-package' for `ivy', in
+              ;; order to use my fork. That will cause a conflict, because
+              ;; the recipe for `swiper' is automatically taken from
+              ;; MELPA, and it does not point at my fork, but instead at
+              ;; the official repository. To fix the problem, I would have
+              ;; to specify my fork in the recipe for `swiper' (and also
+              ;; `counsel', a third package versioned in the same
+              ;; repository). That violates DRY and is a pain.
+              ;;
+              ;; Instead, this code makes it so that if a recipe has been
+              ;; automatically retrieved from a package source (for
+              ;; example, MELPA, GNU ELPA, or Emacsmirror), and the
+              ;; `:local-repo' specified in that recipe has already been
+              ;; used for another package, then the configuration for that
+              ;; repository will silently be copied over, and everything
+              ;; should "just work".
+              (unless recipe-specified-p
+                (straight--with-plist plist
+                    (local-repo)
+                  (when-let (original-recipe (gethash local-repo
+                                                      straight--repo-cache))
+                    (dolist (keyword straight--fetch-keywords)
+                      (when-let ((value (plist-get original-recipe keyword)))
+                        (straight--put plist keyword value))))))
+              plist))))))
 
 (setq melpa-recipe (straight--convert-recipe
                     '(melpa :fetcher github

                   (funcall func recipe)
                   (push local-repo repos))))
             straight--recipe-cache)))

(defun straight--get-recipe (package)
  ;; You might think that this method could be eliminated entirely.
  ;; Instead, we could perform this defaulting behavior all inside
  ;; `straight--convert-recipe', you would say.
  ;;
  ;; It turns out that's not such a good idea, because then we aren't
  ;; able to distinguish between top-level packages and dependencies.
  ;; If the user specifies two incompatible recipes for a package, we
  ;; want to signal an error. However, if the user specifies one
  ;; recipe and a recipe repository provides another for a dependency
  ;; package, we want to silently reconcile the difference. This can
  ;; be done by having the dependency resolution functions call this
  ;; defaulting function, and then having `straight--convert-recipe'
  ;; just throw an error on a conflict (except for the repository
  ;; fetch part of the recipe, see the large comment in
  ;; `straight--convert-recipe' for details).
  (or (gethash package straight--recipe-cache)
      (straight--convert-recipe (intern package))))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Managing repositories

            (straight--maybe-save-build-cache)
            (straight--install-package-autoloads recipe)
            (dolist (dependency (straight--get-dependencies package))
              (straight-use-package (intern dependency) interactive recipe))
            (when (and interactive (not reload))
              (message
               (concat "If you want to keep %s, put "
