From 0148ad499e45b8d8fb45ee8831fbca5e9b6d6d95 Mon Sep 17 00:00:00 2001
From: Artur Malabarba <bruce.connor.am@gmail.com>
Date: Mon, 12 Jan 2015 23:24:22 -0200
Subject: [PATCH 1/5] * emacs-lisp/package.el (package--read-pkg-desc): New
 function.

Read a `define-package' form in current buffer. Return the pkg-desc,
with desc-kind set to KIND.
---
 lisp/ChangeLog             |  6 ++++++
 lisp/emacs-lisp/package.el | 26 ++++++++++++++++----------
 2 files changed, 22 insertions(+), 10 deletions(-)

diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 598f9c6..8c73087 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,9 @@
+2015-01-13  Artur Malabarba  <bruce.connor.am@gmail.com>
+
+	* emacs-lisp/package.el (package--read-pkg-desc): New
+	function. Read a `define-package' form in current buffer. Return
+	the pkg-desc, with desc-kind set to KIND.
+
 2015-01-11  Michael Albinus  <michael.albinus@gmx.de>
 
 	* files.el (directory-files-recursively): Do not include
diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el
index 79f8b65..f0af233 100644
--- a/lisp/emacs-lisp/package.el
+++ b/lisp/emacs-lisp/package.el
@@ -1252,19 +1252,25 @@ The return result is a `package-desc'."
     (unless tar-desc
       (error "No package descriptor file found"))
     (with-current-buffer (tar--extract tar-desc)
-      (goto-char (point-min))
       (unwind-protect
-          (let* ((pkg-def-parsed (read (current-buffer)))
-                 (pkg-desc
-                  (if (not (eq (car pkg-def-parsed) 'define-package))
-                      (error "Can't find define-package in %s"
-                             (tar-header-name tar-desc))
-                    (apply #'package-desc-from-define
-                           (append (cdr pkg-def-parsed))))))
-            (setf (package-desc-kind pkg-desc) 'tar)
-            pkg-desc)
+          (package--read-pkg-desc 'tar)
         (kill-buffer (current-buffer))))))
 
+(defun package--read-pkg-desc (kind)
+  "Read a `define-package' form in current buffer.
+Return the pkg-desc, with desc-kind set to KIND."
+  (goto-char (point-min))
+  (unwind-protect
+      (let* ((pkg-def-parsed (read (current-buffer)))
+             (pkg-desc
+              (if (not (eq (car pkg-def-parsed) 'define-package))
+                  (error "Can't find define-package in %s"
+                         (tar-header-name tar-desc))
+                (apply #'package-desc-from-define
+                  (append (cdr pkg-def-parsed))))))
+        (setf (package-desc-kind pkg-desc) kind)
+        pkg-desc)))
+
 
 ;;;###autoload
 (defun package-install-from-buffer ()
-- 
2.1.1


From 7ce7b575a7a399f436b7264fa5c2f165494ed75c Mon Sep 17 00:00:00 2001
From: Artur Malabarba <bruce.connor.am@gmail.com>
Date: Mon, 12 Jan 2015 23:26:58 -0200
Subject: [PATCH 2/5] * emacs-lisp/package.el (package-dir-info): New function.

Find package information for a directory. The return result is a
`package-desc'.
---
 lisp/ChangeLog             |  2 ++
 lisp/emacs-lisp/package.el | 18 ++++++++++++++++++
 2 files changed, 20 insertions(+)

diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 8c73087..ca2d425 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -3,6 +3,8 @@
 	* emacs-lisp/package.el (package--read-pkg-desc): New
 	function. Read a `define-package' form in current buffer. Return
 	the pkg-desc, with desc-kind set to KIND.
+	(package-dir-info): New function. Find package information for a
+	directory. The return result is a `package-desc'.
 
 2015-01-11  Michael Albinus  <michael.albinus@gmx.de>
 
diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el
index f0af233..af292fc 100644
--- a/lisp/emacs-lisp/package.el
+++ b/lisp/emacs-lisp/package.el
@@ -1256,6 +1256,24 @@ The return result is a `package-desc'."
           (package--read-pkg-desc 'tar)
         (kill-buffer (current-buffer))))))
 
+(defun package-dir-info ()
+  "Find package information for a directory.
+The return result is a `package-desc'."
+  (cl-assert (derived-mode-p 'dired-mode))
+  (let* ((desc-file (package--description-file default-directory)))
+    (if (file-readable-p desc-file)
+        (with-temp-buffer
+          (insert-file-contents desc-file)
+          (package--read-pkg-desc 'dir))
+      (let ((files (directory-files default-directory t "\\.el\\'" t))
+            info)
+        (while files
+          (with-temp-buffer
+            (insert-file-contents (pop files))
+            (if (setq info (ignore-errors (package-buffer-info)))
+                (setq files nil)
+              info)))))))
+
 (defun package--read-pkg-desc (kind)
   "Read a `define-package' form in current buffer.
 Return the pkg-desc, with desc-kind set to KIND."
-- 
2.1.1


From 26f6d4368dba0d2ca4ba3c0353b98018f042d4a2 Mon Sep 17 00:00:00 2001
From: Artur Malabarba <bruce.connor.am@gmail.com>
Date: Mon, 12 Jan 2015 23:35:46 -0200
Subject: [PATCH 3/5] (package-install-from-buffer): Install packages from
 dired buffer.

---
 lisp/ChangeLog             |  1 +
 lisp/emacs-lisp/package.el | 29 ++++++++++++++++++++++++-----
 2 files changed, 25 insertions(+), 5 deletions(-)

diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index ca2d425..4bc4082 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -5,6 +5,7 @@
 	the pkg-desc, with desc-kind set to KIND.
 	(package-dir-info): New function. Find package information for a
 	directory. The return result is a `package-desc'.
+	(package-install-from-buffer): Install packages from dired buffer.
 
 2015-01-11  Michael Albinus  <michael.albinus@gmx.de>
 
diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el
index af292fc..1ae6217 100644
--- a/lisp/emacs-lisp/package.el
+++ b/lisp/emacs-lisp/package.el
@@ -784,6 +784,14 @@ untar into a directory named DIR; otherwise, signal an error."
          (dirname (package-desc-full-name pkg-desc))
 	 (pkg-dir (expand-file-name dirname package-user-dir)))
     (pcase (package-desc-kind pkg-desc)
+      (`dir
+       (make-directory pkg-dir t)
+       (dolist (source-file
+                (directory-files
+                 default-directory 'full "\\`[^.].*\\.el\\'" 'nosort))
+         (let ((target-el-file
+                (expand-file-name (file-name-nondirectory source-file) pkg-dir)))
+           (copy-file source-file target-el-file t))))
       (`tar
        (make-directory package-user-dir t)
        ;; FIXME: should we delete PKG-DIR if it exists?
@@ -1293,13 +1301,24 @@ Return the pkg-desc, with desc-kind set to KIND."
 ;;;###autoload
 (defun package-install-from-buffer ()
   "Install a package from the current buffer.
-The current buffer is assumed to be a single .el or .tar file that follows the
-packaging guidelines; see info node `(elisp)Packaging'.
+The current buffer is assumed to be a single .el or .tar file or
+a directory.  These must follow the packaging guidelines (see
+info node `(elisp)Packaging').
+
+Specially, if current buffer is a directory, the -pkg.el
+description file is not mandatory, in which case the information
+is derived from the main .el file in the directory.
+
 Downloads and installs required packages as needed."
   (interactive)
-  (let ((pkg-desc (if (derived-mode-p 'tar-mode)
-                      (package-tar-file-info)
-                    (package-buffer-info))))
+  (let ((pkg-desc
+         (cond
+          ((derived-mode-p 'dired-mode)
+           (package-dir-info))
+          ((derived-mode-p 'tar-mode)
+           (package-tar-file-info))
+          (t
+           (package-buffer-info)))))
     ;; Download and install the dependencies.
     (let* ((requires (package-desc-reqs pkg-desc))
            (transaction (package-compute-transaction nil requires)))
-- 
2.1.1


From 7ab852570e04eb0e17f7287365a37b23b2e1e43f Mon Sep 17 00:00:00 2001
From: Artur Malabarba <bruce.connor.am@gmail.com>
Date: Tue, 13 Jan 2015 00:03:59 -0200
Subject: [PATCH 4/5] (package-install-file): Install packages from directory.

---
 lisp/ChangeLog             | 1 +
 lisp/emacs-lisp/package.el | 8 ++++++--
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 4bc4082..13081c3 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -6,6 +6,7 @@
 	(package-dir-info): New function. Find package information for a
 	directory. The return result is a `package-desc'.
 	(package-install-from-buffer): Install packages from dired buffer.
+	(package-install-file): Install packages from directory.
 
 2015-01-11  Michael Albinus  <michael.albinus@gmx.de>
 
diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el
index 1ae6217..1f93733 100644
--- a/lisp/emacs-lisp/package.el
+++ b/lisp/emacs-lisp/package.el
@@ -1333,8 +1333,12 @@ Downloads and installs required packages as needed."
 The file can either be a tar file or an Emacs Lisp file."
   (interactive "fPackage file name: ")
   (with-temp-buffer
-    (insert-file-contents-literally file)
-    (when (string-match "\\.tar\\'" file) (tar-mode))
+    (if (file-directory-p file)
+        (progn
+          (setq default-directory file)
+          (dired-mode))
+      (insert-file-contents-literally file)
+      (when (string-match "\\.tar\\'" file) (tar-mode)))
     (package-install-from-buffer)))
 
 (defun package-delete (pkg-desc)
-- 
2.1.1


From 05d61e88aa1c0ae2af3f2a859a0ce1270db21a0e Mon Sep 17 00:00:00 2001
From: Artur Malabarba <bruce.connor.am@gmail.com>
Date: Tue, 13 Jan 2015 00:13:55 -0200
Subject: [PATCH 5/5] * NEWS: Document installing packages from directories.

---
 etc/ChangeLog | 4 ++++
 etc/NEWS      | 4 ++++
 2 files changed, 8 insertions(+)

diff --git a/etc/ChangeLog b/etc/ChangeLog
index 20f88bd..10b3fe5 100644
--- a/etc/ChangeLog
+++ b/etc/ChangeLog
@@ -1,3 +1,7 @@
+2015-01-13  Artur Malabarba  <bruce.connor.am@gmail.com>
+
+	* NEWS: Document installing packages from directories.
+
 2015-01-11  Paul Eggert  <eggert@cs.ucla.edu>
 
 	Default to 'configure --enable-silent-rules'
diff --git a/etc/NEWS b/etc/NEWS
index b3267e1..b3f8d87 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -56,6 +56,10 @@ so if you want to use it, you can always take a copy from an older Emacs.
 
 * Changes in Emacs 25.1
 
+** `package-install-from-buffer' and `package-install-file' work on directories.
+This follows the same rules as installing from a .tar file, except the
+-pkg file is optional.
+
 ** New function `custom-prompt-customize-unsaved-options' checks for
 unsaved customizations and prompts user to customize (if found).
 
-- 
2.1.1

