aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Monnier2013-06-20 23:08:47 -0400
committerStefan Monnier2013-06-20 23:08:47 -0400
commitfd846ab406e00ac85b6ed01a6715e795a549c02f (patch)
tree4134d89eb45a3a63fce8902d7d07f1f5ffd49e34
parentd1f7f5a0d927a5a51c989fcf97688e57916bf9d9 (diff)
downloademacs-fd846ab406e00ac85b6ed01a6715e795a549c02f.tar.gz
emacs-fd846ab406e00ac85b6ed01a6715e795a549c02f.zip
* lisp/emacs-lisp/package.el: Use tar-mode rather than tar executable.
Consolidate the single-file vs tarball code. (package-desc-suffix): New function. (package-desc-full-name): Don't bother inlining it. (package-load-descriptor): Return the new package-desc. (package-mark-obsolete): Remove unused arg `package'. (package-unpack): Make it work for single files as well. Make it update package-alist. (package--make-autoloads-and-stuff): Rename from package--make-autoloads-and-compile. Don't compile any more. (package--compile): New function. (package-generate-description-file): New function, extracted from package-unpack-single. (package-unpack-single): Remove. (package--with-work-buffer): Add indentation and debugging info. (package-download-single): Remove. (package-install-from-archive): Rename from package-download-tar, make it take a pkg-desc, and make it work for single files as well. (package-download-transaction): Simplify. (package-tar-file-info): Remove `file' arg. Rewrite not to use an external tar program. (package-install-from-buffer): Remove `pkg-desc' argument. Use package-tar-file-info for tar-mode buffers. (package-install-file): Simplify accordingly. (package-archive-base): Change to take a pkg-desc. * lisp/tar-mode.el (tar--check-descriptor): New function, extracted from tar-get-descriptor. (tar-get-descriptor): Use it. (tar-get-file-descriptor): New function. (tar--extract): New function, extracted from tar-extract. (tar--extract): Use it. * lisp/emacs-lisp/package-x.el (package-upload-file): Decode the file, in case the summary uses non-ascii. Adjust to new calling convention of package-tar-file-info.
-rw-r--r--lisp/ChangeLog46
-rw-r--r--lisp/emacs-lisp/package-x.el5
-rw-r--r--lisp/emacs-lisp/package.el302
-rw-r--r--lisp/tar-mode.el193
4 files changed, 284 insertions, 262 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index e4c67dde1d9..39013982477 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,7 +1,45 @@
12013-06-21 Stefan Monnier <monnier@iro.umontreal.ca>
2 Daniel Hackney <dan@haxney.org>
3
4 * emacs-lisp/package.el: Use tar-mode rather than tar executable.
5 Consolidate the single-file vs tarball code.
6 (package-desc-suffix): New function.
7 (package-desc-full-name): Don't bother inlining it.
8 (package-load-descriptor): Return the new package-desc.
9 (package-mark-obsolete): Remove unused arg `package'.
10 (package-unpack): Make it work for single files as well.
11 Make it update package-alist.
12 (package--make-autoloads-and-stuff): Rename from
13 package--make-autoloads-and-compile. Don't compile any more.
14 (package--compile): New function.
15 (package-generate-description-file): New function, extracted from
16 package-unpack-single.
17 (package-unpack-single): Remove.
18 (package--with-work-buffer): Add indentation and debugging info.
19 (package-download-single): Remove.
20 (package-install-from-archive): Rename from package-download-tar, make
21 it take a pkg-desc, and make it work for single files as well.
22 (package-download-transaction): Simplify.
23 (package-tar-file-info): Remove `file' arg. Rewrite not to use an
24 external tar program.
25 (package-install-from-buffer): Remove `pkg-desc' argument.
26 Use package-tar-file-info for tar-mode buffers.
27 (package-install-file): Simplify accordingly.
28 (package-archive-base): Change to take a pkg-desc.
29 * tar-mode.el (tar--check-descriptor): New function, extracted from
30 tar-get-descriptor.
31 (tar-get-descriptor): Use it.
32 (tar-get-file-descriptor): New function.
33 (tar--extract): New function, extracted from tar-extract.
34 (tar--extract): Use it.
35 * emacs-lisp/package-x.el (package-upload-file): Decode the file, in
36 case the summary uses non-ascii. Adjust to new calling convention of
37 package-tar-file-info.
38
12013-06-21 Leo Liu <sdl.web@gmail.com> 392013-06-21 Leo Liu <sdl.web@gmail.com>
2 40
3 * comint.el (comint-redirect-results-list-from-process): Fix 41 * comint.el (comint-redirect-results-list-from-process):
4 random delay. (Bug#14681) 42 Fix random delay. (Bug#14681)
5 43
62013-06-21 Juanma Barranquero <lekktu@gmail.com> 442013-06-21 Juanma Barranquero <lekktu@gmail.com>
7 45
@@ -135,8 +173,8 @@
1352013-06-19 Michael Albinus <michael.albinus@gmx.de> 1732013-06-19 Michael Albinus <michael.albinus@gmx.de>
136 174
137 * net/secrets.el (secrets-struct-secret-content-type): Replace 175 * net/secrets.el (secrets-struct-secret-content-type): Replace
138 check of introspection data by a test call of "CreateItem". Some 176 check of introspection data by a test call of "CreateItem".
139 servers do not offer introspection. 177 Some servers do not offer introspection.
140 178
1412013-06-19 Stefan Monnier <monnier@iro.umontreal.ca> 1792013-06-19 Stefan Monnier <monnier@iro.umontreal.ca>
142 180
diff --git a/lisp/emacs-lisp/package-x.el b/lisp/emacs-lisp/package-x.el
index 3300e89ec1e..7d0d75f7cee 100644
--- a/lisp/emacs-lisp/package-x.el
+++ b/lisp/emacs-lisp/package-x.el
@@ -291,10 +291,11 @@ If `package-archive-upload-base' does not specify a valid upload
291destination, prompt for one." 291destination, prompt for one."
292 (interactive "fPackage file name: ") 292 (interactive "fPackage file name: ")
293 (with-temp-buffer 293 (with-temp-buffer
294 (insert-file-contents-literally file) 294 (insert-file-contents file)
295 (let ((pkg-desc 295 (let ((pkg-desc
296 (cond 296 (cond
297 ((string-match "\\.tar\\'" file) (package-tar-file-info file)) 297 ((string-match "\\.tar\\'" file)
298 (tar-mode) (package-tar-file-info))
298 ((string-match "\\.el\\'" file) (package-buffer-info)) 299 ((string-match "\\.el\\'" file) (package-buffer-info))
299 (t (error "Unrecognized extension `%s'" 300 (t (error "Unrecognized extension `%s'"
300 (file-name-extension file)))))) 301 (file-name-extension file))))))
diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el
index ae4ebb87ee2..1bf1e6027e2 100644
--- a/lisp/emacs-lisp/package.el
+++ b/lisp/emacs-lisp/package.el
@@ -340,11 +340,17 @@ package came.
340 dir) 340 dir)
341 341
342;; Pseudo fields. 342;; Pseudo fields.
343(defsubst package-desc-full-name (pkg-desc) 343(defun package-desc-full-name (pkg-desc)
344 (format "%s-%s" 344 (format "%s-%s"
345 (package-desc-name pkg-desc) 345 (package-desc-name pkg-desc)
346 (package-version-join (package-desc-version pkg-desc)))) 346 (package-version-join (package-desc-version pkg-desc))))
347 347
348(defun package-desc-suffix (pkg-desc)
349 (pcase (package-desc-kind pkg-desc)
350 (`single ".el")
351 (`tar ".tar")
352 (kind (error "Unknown package kind: %s" kind))))
353
348;; Package descriptor format used in finder-inf.el and package--builtins. 354;; Package descriptor format used in finder-inf.el and package--builtins.
349(cl-defstruct (package--bi-desc 355(cl-defstruct (package--bi-desc
350 (:constructor package-make-builtin (version summary)) 356 (:constructor package-make-builtin (version summary))
@@ -422,7 +428,8 @@ This is, approximately, the inverse of `version-to-list'.
422 (goto-char (point-min)) 428 (goto-char (point-min))
423 (let ((pkg-desc (package-process-define-package 429 (let ((pkg-desc (package-process-define-package
424 (read (current-buffer)) pkg-file))) 430 (read (current-buffer)) pkg-file)))
425 (setf (package-desc-dir pkg-desc) pkg-dir)))))) 431 (setf (package-desc-dir pkg-desc) pkg-dir)
432 pkg-desc)))))
426 433
427(defun package-load-all-descriptors () 434(defun package-load-all-descriptors ()
428 "Load descriptors for installed Emacs Lisp packages. 435 "Load descriptors for installed Emacs Lisp packages.
@@ -529,13 +536,13 @@ Required package `%s-%s' is unavailable"
529 ;; If all goes well, activate the package itself. 536 ;; If all goes well, activate the package itself.
530 (package-activate-1 pkg-vec))))))) 537 (package-activate-1 pkg-vec)))))))
531 538
532(defun package-mark-obsolete (package pkg-vec) 539(defun package-mark-obsolete (pkg-desc)
533 "Put package on the obsolete list, if not already there." 540 "Put PKG-DESC on the obsolete list, if not already there."
534 (push pkg-vec package-obsolete-list)) 541 (push pkg-desc package-obsolete-list))
535 542
536(defun define-package (name-string version-string 543(defun define-package (_name-string _version-string
537 &optional docstring requirements 544 &optional _docstring _requirements
538 &rest _extra-properties) 545 &rest _extra-properties)
539 "Define a new package. 546 "Define a new package.
540NAME-STRING is the name of the package, as a string. 547NAME-STRING is the name of the package, as a string.
541VERSION-STRING is the version of the package, as a string. 548VERSION-STRING is the version of the package, as a string.
@@ -559,13 +566,13 @@ EXTRA-PROPERTIES is currently unused."
559 ;; If it's not newer than a builtin version, mark it obsolete. 566 ;; If it's not newer than a builtin version, mark it obsolete.
560 ((let ((bi (assq name package--builtin-versions))) 567 ((let ((bi (assq name package--builtin-versions)))
561 (and bi (version-list-<= version (cdr bi)))) 568 (and bi (version-list-<= version (cdr bi))))
562 (package-mark-obsolete name new-pkg-desc)) 569 (package-mark-obsolete new-pkg-desc))
563 ;; If there's no old package, just add this to `package-alist'. 570 ;; If there's no old package, just add this to `package-alist'.
564 ((null old-pkg) 571 ((null old-pkg)
565 (push (cons name new-pkg-desc) package-alist)) 572 (push (cons name new-pkg-desc) package-alist))
566 ((version-list-< (package-desc-version (cdr old-pkg)) version) 573 ((version-list-< (package-desc-version (cdr old-pkg)) version)
567 ;; Remove the old package and declare it obsolete. 574 ;; Remove the old package and declare it obsolete.
568 (package-mark-obsolete name (cdr old-pkg)) 575 (package-mark-obsolete (cdr old-pkg))
569 (setq package-alist (cons (cons name new-pkg-desc) 576 (setq package-alist (cons (cons name new-pkg-desc)
570 (delq old-pkg package-alist)))) 577 (delq old-pkg package-alist))))
571 ;; You can have two packages with the same version, e.g. one in 578 ;; You can have two packages with the same version, e.g. one in
@@ -573,10 +580,10 @@ EXTRA-PROPERTIES is currently unused."
573 ;; directory. We just let the first one win. 580 ;; directory. We just let the first one win.
574 ((not (version-list-= (package-desc-version (cdr old-pkg)) version)) 581 ((not (version-list-= (package-desc-version (cdr old-pkg)) version))
575 ;; The package is born obsolete. 582 ;; The package is born obsolete.
576 (package-mark-obsolete name new-pkg-desc))) 583 (package-mark-obsolete new-pkg-desc)))
577 new-pkg-desc)) 584 new-pkg-desc))
578 585
579;; From Emacs 22. 586;; From Emacs 22, but changed so it adds to load-path.
580(defun package-autoload-ensure-default-file (file) 587(defun package-autoload-ensure-default-file (file)
581 "Make sure that the autoload file FILE exists and if not create it." 588 "Make sure that the autoload file FILE exists and if not create it."
582 (unless (file-exists-p file) 589 (unless (file-exists-p file)
@@ -632,74 +639,79 @@ untar into a directory named DIR; otherwise, signal an error."
632 (error "Package does not untar cleanly into directory %s/" dir))))) 639 (error "Package does not untar cleanly into directory %s/" dir)))))
633 (tar-untar-buffer)) 640 (tar-untar-buffer))
634 641
635(defun package-unpack (package version) 642(defun package-generate-description-file (pkg-desc pkg-dir)
636 (let* ((name (symbol-name package)) 643 "Create the foo-pkg.el file for single-file packages."
637 (dirname (concat name "-" version)) 644 (let* ((name (package-desc-name pkg-desc))
645 (pkg-file (expand-file-name (package--description-file pkg-dir)
646 pkg-dir)))
647 (let ((print-level nil)
648 (print-quoted t)
649 (print-length nil))
650 (write-region
651 (concat
652 (prin1-to-string
653 (list 'define-package
654 (symbol-name name)
655 (package-version-join (package-desc-version pkg-desc))
656 (package-desc-summary pkg-desc)
657 (let ((requires (package-desc-reqs pkg-desc)))
658 (list 'quote
659 ;; Turn version lists into string form.
660 (mapcar
661 (lambda (elt)
662 (list (car elt)
663 (package-version-join (cadr elt))))
664 requires)))))
665 "\n")
666 nil
667 pkg-file))))
668
669(defun package-unpack (pkg-desc)
670 "Install the contents of the current buffer as a package."
671 (let* ((name (package-desc-name pkg-desc))
672 (dirname (package-desc-full-name pkg-desc))
638 (pkg-dir (expand-file-name dirname package-user-dir))) 673 (pkg-dir (expand-file-name dirname package-user-dir)))
639 (make-directory package-user-dir t) 674 (pcase (package-desc-kind pkg-desc)
640 ;; FIXME: should we delete PKG-DIR if it exists? 675 (`tar
641 (let* ((default-directory (file-name-as-directory package-user-dir))) 676 (make-directory package-user-dir t)
642 (package-untar-buffer dirname) 677 ;; FIXME: should we delete PKG-DIR if it exists?
643 (package--make-autoloads-and-compile package pkg-dir) 678 (let* ((default-directory (file-name-as-directory package-user-dir)))
644 pkg-dir))) 679 (package-untar-buffer dirname)))
645 680 (`single
646(defun package--make-autoloads-and-compile (name pkg-dir) 681 (let ((el-file (expand-file-name (format "%s.el" name) pkg-dir)))
647 "Generate autoloads and do byte-compilation for package named NAME. 682 (make-directory pkg-dir t)
648PKG-DIR is the name of the package directory." 683 (package--write-file-no-coding el-file)))
649 (let ((auto-name (package-generate-autoloads name pkg-dir)) 684 (kind (error "Unknown package kind: %S" kind)))
650 (load-path (cons pkg-dir load-path))) 685 (package--make-autoloads-and-stuff pkg-desc pkg-dir)
651 ;; We must load the autoloads file before byte compiling, in 686 ;; Update package-alist.
652 ;; case there are magic cookies to set up non-trivial paths. 687 (let ((new-desc (package-load-descriptor pkg-dir)))
653 (load auto-name nil t) 688 ;; FIXME: Check that `new-desc' matches `desc'!
654 ;; FIXME: Compilation should be done as a separate, optional, step. 689 ;; FIXME: Compilation should be done as a separate, optional, step.
655 ;; E.g. for multi-package installs, we should first install all packages 690 ;; E.g. for multi-package installs, we should first install all packages
656 ;; and then compile them. 691 ;; and then compile them.
657 (byte-recompile-directory pkg-dir 0 t))) 692 (package--compile new-desc))
693 ;; Try to activate it.
694 (package-activate name (package-desc-version pkg-desc))
695 pkg-dir))
696
697(defun package--make-autoloads-and-stuff (pkg-desc pkg-dir)
698 "Generate autoloads, description file, etc.. for PKG-DESC installed at PKG-DIR."
699 (package-generate-autoloads (package-desc-name pkg-desc) pkg-dir)
700 (let ((desc-file (package--description-file pkg-dir)))
701 (unless (file-exists-p desc-file)
702 (package-generate-description-file pkg-desc pkg-dir)))
703 ;; FIXME: Create foo.info and dir file from foo.texi?
704 )
705
706(defun package--compile (pkg-desc)
707 "Byte-compile installed package PKG-DESC."
708 (package-activate-1 pkg-desc)
709 (byte-recompile-directory (package-desc-dir pkg-desc) 0 t))
658 710
659(defun package--write-file-no-coding (file-name) 711(defun package--write-file-no-coding (file-name)
660 (let ((buffer-file-coding-system 'no-conversion)) 712 (let ((buffer-file-coding-system 'no-conversion))
661 (write-region (point-min) (point-max) file-name))) 713 (write-region (point-min) (point-max) file-name)))
662 714
663(defun package-unpack-single (name version desc requires)
664 "Install the contents of the current buffer as a package."
665 ;; Special case "package". FIXME: Should this still be supported?
666 (if (eq name 'package)
667 (package--write-file-no-coding
668 (expand-file-name (format "%s.el" name) package-user-dir))
669 (let* ((pkg-dir (expand-file-name (format "%s-%s" name
670 (package-version-join
671 (version-to-list version)))
672 package-user-dir))
673 (el-file (expand-file-name (format "%s.el" name) pkg-dir))
674 (pkg-file (expand-file-name (package--description-file pkg-dir)
675 pkg-dir)))
676 (make-directory pkg-dir t)
677 (package--write-file-no-coding el-file)
678 (let ((print-level nil)
679 (print-quoted t)
680 (print-length nil))
681 (write-region
682 (concat
683 (prin1-to-string
684 (list 'define-package
685 (symbol-name name)
686 version
687 desc
688 (when requires ;Don't bother quoting nil.
689 (list 'quote
690 ;; Turn version lists into string form.
691 (mapcar
692 (lambda (elt)
693 (list (car elt)
694 (package-version-join (cadr elt))))
695 requires)))))
696 "\n")
697 nil
698 pkg-file
699 nil nil nil 'excl))
700 (package--make-autoloads-and-compile name pkg-dir)
701 pkg-dir)))
702
703(defmacro package--with-work-buffer (location file &rest body) 715(defmacro package--with-work-buffer (location file &rest body)
704 "Run BODY in a buffer containing the contents of FILE at LOCATION. 716 "Run BODY in a buffer containing the contents of FILE at LOCATION.
705LOCATION is the base location of a package archive, and should be 717LOCATION is the base location of a package archive, and should be
@@ -709,6 +721,7 @@ FILE is the name of a file relative to that base location.
709This macro retrieves FILE from LOCATION into a temporary buffer, 721This macro retrieves FILE from LOCATION into a temporary buffer,
710and evaluates BODY while that buffer is current. This work 722and evaluates BODY while that buffer is current. This work
711buffer is killed afterwards. Return the last value in BODY." 723buffer is killed afterwards. Return the last value in BODY."
724 (declare (indent 2) (debug t))
712 `(let* ((http (string-match "\\`https?:" ,location)) 725 `(let* ((http (string-match "\\`https?:" ,location))
713 (buffer 726 (buffer
714 (if http 727 (if http
@@ -741,19 +754,13 @@ It will move point to somewhere in the headers."
741 (error "Error during download request:%s" 754 (error "Error during download request:%s"
742 (buffer-substring-no-properties (point) (line-end-position)))))) 755 (buffer-substring-no-properties (point) (line-end-position))))))
743 756
744(defun package-download-single (name version desc requires) 757(defun package-install-from-archive (pkg-desc)
745 "Download and install a single-file package."
746 (let ((location (package-archive-base name))
747 (file (concat (symbol-name name) "-" version ".el")))
748 (package--with-work-buffer location file
749 (package-unpack-single name version desc requires))))
750
751(defun package-download-tar (name version)
752 "Download and install a tar package." 758 "Download and install a tar package."
753 (let ((location (package-archive-base name)) 759 (let ((location (package-archive-base pkg-desc))
754 (file (concat (symbol-name name) "-" version ".tar"))) 760 (file (concat (package-desc-full-name pkg-desc)
761 (package-desc-suffix pkg-desc))))
755 (package--with-work-buffer location file 762 (package--with-work-buffer location file
756 (package-unpack name version)))) 763 (package-unpack pkg-desc))))
757 764
758(defvar package--initialized nil) 765(defvar package--initialized nil)
759 766
@@ -918,30 +925,8 @@ PACKAGE-LIST are satisfied, i.e. that PACKAGE-LIST is computed
918using `package-compute-transaction'." 925using `package-compute-transaction'."
919 ;; FIXME: make package-list a list of pkg-desc. 926 ;; FIXME: make package-list a list of pkg-desc.
920 (dolist (elt package-list) 927 (dolist (elt package-list)
921 (let* ((desc (cdr (assq elt package-archive-contents))) 928 (let ((desc (cdr (assq elt package-archive-contents))))
922 ;; As an exception, if package is "held" in 929 (package-install-from-archive desc))))
923 ;; `package-load-list', download the held version.
924 (hold (cadr (assq elt package-load-list)))
925 (v-string (or (and (stringp hold) hold)
926 (package-version-join (package-desc-version desc))))
927 (kind (package-desc-kind desc))
928 (pkg-dir
929 (cond
930 ((eq kind 'tar)
931 (package-download-tar elt v-string))
932 ((eq kind 'single)
933 (package-download-single elt v-string
934 (package-desc-summary desc)
935 (package-desc-reqs desc)))
936 (t
937 (error "Unknown package kind: %s" (symbol-name kind))))))
938 ;; Update package-alist.
939 ;; FIXME: Check that the installed package's descriptor matches `desc'!
940 (package-load-descriptor pkg-dir)
941 ;; If package A depends on package B, then A may `require' B
942 ;; during byte compilation. So we need to activate B before
943 ;; unpacking A.
944 (package-activate elt (version-to-list v-string)))))
945 930
946;;;###autoload 931;;;###autoload
947(defun package-install (pkg-desc) 932(defun package-install (pkg-desc)
@@ -1018,60 +1003,48 @@ boundaries."
1018 (if requires-str (package-read-from-string requires-str)) 1003 (if requires-str (package-read-from-string requires-str))
1019 :kind 'single)))) 1004 :kind 'single))))
1020 1005
1021(defun package-tar-file-info (file) 1006(defun package-tar-file-info ()
1022 "Find package information for a tar file. 1007 "Find package information for a tar file.
1023FILE is the name of the tar file to examine. 1008The return result is a `package-desc'."
1024The return result is a vector like `package-buffer-info'." 1009 (cl-assert (derived-mode-p 'tar-mode))
1025 (let* ((default-directory (file-name-directory file)) 1010 (let* ((dir-name (file-name-directory
1026 (file (file-name-nondirectory file)) 1011 (tar-header-name (car tar-parse-info))))
1027 (dir-name
1028 (if (string-match "\\.tar\\'" file)
1029 (substring file 0 (match-beginning 0))
1030 (error "Invalid package name `%s'" file)))
1031 (desc-file (package--description-file dir-name)) 1012 (desc-file (package--description-file dir-name))
1032 ;; Extract the package descriptor. 1013 (tar-desc (tar-get-file-descriptor (concat dir-name desc-file))))
1033 (pkg-def-contents (shell-command-to-string 1014 (unless tar-desc
1034 ;; Requires GNU tar. 1015 (error "No package descriptor file found"))
1035 (concat "tar -xOf " file " " 1016 (with-current-buffer (tar--extract tar-desc)
1036 dir-name "/" desc-file))) 1017 (goto-char (point-min))
1037 (pkg-def-parsed (package-read-from-string pkg-def-contents))) 1018 (unwind-protect
1038 (unless (eq (car pkg-def-parsed) 'define-package) 1019 (let* ((pkg-def-parsed (read (current-buffer)))
1039 (error "Can't find define-package in %s" desc-file)) 1020 (pkg-desc
1040 (let ((pkg-desc 1021 (if (not (eq (car pkg-def-parsed) 'define-package))
1041 (apply #'package-desc-from-define (append (cdr pkg-def-parsed) 1022 (error "Can't find define-package in %s"
1042 '(:kind tar))))) 1023 (tar-header-name tar-desc))
1043 (unless (equal dir-name (package-desc-full-name pkg-desc)) 1024 (apply #'package-desc-from-define
1044 ;; FIXME: Shouldn't this just be a message/warning? 1025 (append (cdr pkg-def-parsed))))))
1045 (error "Package has inconsistent name")) 1026 (setf (package-desc-kind pkg-desc) 'tar)
1046 pkg-desc))) 1027 pkg-desc)
1028 (kill-buffer (current-buffer))))))
1047 1029
1048 1030
1049;;;###autoload 1031;;;###autoload
1050(defun package-install-from-buffer (pkg-desc) 1032(defun package-install-from-buffer ()
1051 "Install a package from the current buffer. 1033 "Install a package from the current buffer.
1052When called interactively, the current buffer is assumed to be a 1034The current buffer is assumed to be a single .el or .tar file that follows the
1053single .el file that follows the packaging guidelines; see info 1035packaging guidelines; see info node `(elisp)Packaging'.
1054node `(elisp)Packaging'. 1036Downloads and installs required packages as needed."
1055 1037 (interactive)
1056When called from Lisp, PKG-DESC is a `package-desc' describing the 1038 (let ((pkg-desc (if (derived-mode-p 'tar-mode)
1057information)." 1039 (package-tar-file-info)
1058 (interactive (list (package-buffer-info))) 1040 (package-buffer-info))))
1059 (save-excursion 1041 ;; Download and install the dependencies.
1060 (save-restriction 1042 (let* ((requires (package-desc-reqs pkg-desc))
1061 (let* ((name (package-desc-name pkg-desc)) 1043 (transaction (package-compute-transaction nil requires)))
1062 (requires (package-desc-reqs pkg-desc)) 1044 (package-download-transaction transaction))
1063 (desc (package-desc-summary pkg-desc)) 1045 ;; Install the package itself.
1064 (pkg-version (package-desc-version pkg-desc))) 1046 (package-unpack pkg-desc)
1065 ;; Download and install the dependencies. 1047 pkg-desc))
1066 (let ((transaction (package-compute-transaction nil requires)))
1067 (package-download-transaction transaction))
1068 ;; Install the package itself.
1069 (pcase (package-desc-kind pkg-desc)
1070 (`single (package-unpack-single name pkg-version desc requires))
1071 (`tar (package-unpack name pkg-version))
1072 (type (error "Unknown type: %S" type)))
1073 ;; Try to activate it.
1074 (package-initialize)))))
1075 1048
1076;;;###autoload 1049;;;###autoload
1077(defun package-install-file (file) 1050(defun package-install-file (file)
@@ -1080,12 +1053,8 @@ The file can either be a tar file or an Emacs Lisp file."
1080 (interactive "fPackage file name: ") 1053 (interactive "fPackage file name: ")
1081 (with-temp-buffer 1054 (with-temp-buffer
1082 (insert-file-contents-literally file) 1055 (insert-file-contents-literally file)
1083 (cond 1056 (when (string-match "\\.tar\\'" file) (tar-mode))
1084 ((string-match "\\.el\\'" file) 1057 (package-install-from-buffer)))
1085 (package-install-from-buffer (package-buffer-info)))
1086 ((string-match "\\.tar\\'" file)
1087 (package-install-from-buffer (package-tar-file-info file)))
1088 (t (error "Unrecognized extension `%s'" (file-name-extension file))))))
1089 1058
1090(defun package-delete (pkg-desc) 1059(defun package-delete (pkg-desc)
1091 (let ((dir (package-desc-dir pkg-desc))) 1060 (let ((dir (package-desc-dir pkg-desc)))
@@ -1099,10 +1068,9 @@ The file can either be a tar file or an Emacs Lisp file."
1099 (error "Package `%s' is a system package, not deleting" 1068 (error "Package `%s' is a system package, not deleting"
1100 (package-desc-full-name pkg-desc))))) 1069 (package-desc-full-name pkg-desc)))))
1101 1070
1102(defun package-archive-base (name) 1071(defun package-archive-base (desc)
1103 "Return the archive containing the package NAME." 1072 "Return the archive containing the package NAME."
1104 (let ((desc (cdr (assq (intern-soft name) package-archive-contents)))) 1073 (cdr (assoc (package-desc-archive desc) package-archives)))
1105 (cdr (assoc (package-desc-archive desc) package-archives))))
1106 1074
1107(defun package--download-one-archive (archive file) 1075(defun package--download-one-archive (archive file)
1108 "Retrieve an archive file FILE from ARCHIVE, and cache it. 1076 "Retrieve an archive file FILE from ARCHIVE, and cache it.
@@ -1292,7 +1260,7 @@ If optional arg NO-ACTIVATE is non-nil, don't activate packages."
1292 ;; For elpa packages, try downloading the commentary. If that 1260 ;; For elpa packages, try downloading the commentary. If that
1293 ;; fails, try an existing readme file in `package-user-dir'. 1261 ;; fails, try an existing readme file in `package-user-dir'.
1294 (cond ((condition-case nil 1262 (cond ((condition-case nil
1295 (package--with-work-buffer (package-archive-base package) 1263 (package--with-work-buffer (package-archive-base desc)
1296 (concat package-name "-readme.txt") 1264 (concat package-name "-readme.txt")
1297 (setq buffer-file-name 1265 (setq buffer-file-name
1298 (expand-file-name readme package-user-dir)) 1266 (expand-file-name readme package-user-dir))
diff --git a/lisp/tar-mode.el b/lisp/tar-mode.el
index 109107e857f..be7bdb25d26 100644
--- a/lisp/tar-mode.el
+++ b/lisp/tar-mode.el
@@ -740,10 +740,8 @@ tar-file's buffer."
740 nil 740 nil
741 (error "This line does not describe a tar-file entry")))) 741 (error "This line does not describe a tar-file entry"))))
742 742
743(defun tar-get-descriptor () 743(defun tar--check-descriptor (descriptor)
744 (let* ((descriptor (tar-current-descriptor)) 744 (let ((link-p (tar-header-link-type descriptor)))
745 (size (tar-header-size descriptor))
746 (link-p (tar-header-link-type descriptor)))
747 (if link-p 745 (if link-p
748 (error "This is %s, not a real file" 746 (error "This is %s, not a real file"
749 (cond ((eq link-p 5) "a directory") 747 (cond ((eq link-p 5) "a directory")
@@ -754,10 +752,24 @@ tar-file's buffer."
754 ((eq link-p 38) "a volume header") 752 ((eq link-p 38) "a volume header")
755 ((eq link-p 55) "a pax global extended header") 753 ((eq link-p 55) "a pax global extended header")
756 ((eq link-p 72) "a pax extended header") 754 ((eq link-p 72) "a pax extended header")
757 (t "a link")))) 755 (t "a link"))))))
756
757(defun tar-get-descriptor ()
758 (let* ((descriptor (tar-current-descriptor))
759 (size (tar-header-size descriptor)))
760 (tar--check-descriptor descriptor)
758 (if (zerop size) (message "This is a zero-length file")) 761 (if (zerop size) (message "This is a zero-length file"))
759 descriptor)) 762 descriptor))
760 763
764(defun tar-get-file-descriptor (file)
765 ;; Used by package.el.
766 (let ((desc ()))
767 (dolist (hdr tar-parse-info)
768 (when (equal file (tar-header-name hdr))
769 (setq desc hdr)))
770 (tar--check-descriptor desc)
771 desc))
772
761(defun tar-mouse-extract (event) 773(defun tar-mouse-extract (event)
762 "Extract a file whose tar directory line you click on." 774 "Extract a file whose tar directory line you click on."
763 (interactive "e") 775 (interactive "e")
@@ -776,96 +788,99 @@ tar-file's buffer."
776 (let ((file-name-handler-alist nil)) 788 (let ((file-name-handler-alist nil))
777 (apply op args)))) 789 (apply op args))))
778 790
791(defun tar--extract (descriptor)
792 "Extract this entry of the tar file into its own buffer."
793 (let* ((name (tar-header-name descriptor))
794 (size (tar-header-size descriptor))
795 (start (tar-header-data-start descriptor))
796 (end (+ start size))
797 (tarname (buffer-name))
798 (bufname (concat (file-name-nondirectory name)
799 " ("
800 tarname
801 ")"))
802 (buffer (generate-new-buffer bufname)))
803 (with-current-buffer buffer
804 (setq buffer-undo-list t))
805 (with-current-buffer tar-data-buffer
806 (let (coding)
807 (narrow-to-region start end)
808 (goto-char start)
809 (setq coding (or coding-system-for-read
810 (and set-auto-coding-function
811 (funcall set-auto-coding-function
812 name (- end start)))
813 ;; The following binding causes
814 ;; find-buffer-file-type-coding-system
815 ;; (defined on dos-w32.el) to act as if
816 ;; the file being extracted existed, so
817 ;; that the file's contents' encoding and
818 ;; EOL format are auto-detected.
819 (let ((file-name-handler-alist
820 '(("" . tar-file-name-handler))))
821 (car (find-operation-coding-system
822 'insert-file-contents
823 (cons name (current-buffer)) t)))))
824 (if (or (not coding)
825 (eq (coding-system-type coding) 'undecided))
826 (setq coding (detect-coding-region start end t)))
827 (if (and (default-value 'enable-multibyte-characters)
828 (coding-system-get coding :for-unibyte))
829 (with-current-buffer buffer
830 (set-buffer-multibyte nil)))
831 (widen)
832 (decode-coding-region start end coding buffer)))
833 buffer))
834
779(defun tar-extract (&optional other-window-p) 835(defun tar-extract (&optional other-window-p)
780 "In Tar mode, extract this entry of the tar file into its own buffer." 836 "In Tar mode, extract this entry of the tar file into its own buffer."
781 (interactive) 837 (interactive)
782 (let* ((view-p (eq other-window-p 'view)) 838 (let* ((view-p (eq other-window-p 'view))
783 (descriptor (tar-get-descriptor)) 839 (descriptor (tar-get-descriptor))
784 (name (tar-header-name descriptor)) 840 (name (tar-header-name descriptor))
785 (size (tar-header-size descriptor)) 841 (tar-buffer (current-buffer))
786 (start (tar-header-data-start descriptor)) 842 (tarname (buffer-name))
787 (end (+ start size))) 843 (read-only-p (or buffer-read-only view-p))
788 (let* ((tar-buffer (current-buffer)) 844 (new-buffer-file-name (expand-file-name
789 (tarname (buffer-name)) 845 ;; `:' is not allowed on Windows
790 (bufname (concat (file-name-nondirectory name) 846 (concat tarname "!"
791 " (" 847 (if (string-match "/" name)
792 tarname 848 name
793 ")")) 849 ;; Make sure `name' contains a /
794 (read-only-p (or buffer-read-only view-p)) 850 ;; so set-auto-mode doesn't try
795 (new-buffer-file-name (expand-file-name 851 ;; to look at `tarname' for hints.
796 ;; `:' is not allowed on Windows 852 (concat "./" name)))))
797 (concat tarname "!" 853 (buffer (get-file-buffer new-buffer-file-name))
798 (if (string-match "/" name) 854 (just-created nil))
799 name 855 (unless buffer
800 ;; Make sure `name' contains a / 856 (setq buffer (tar--extract descriptor))
801 ;; so set-auto-mode doesn't try 857 (setq just-created t)
802 ;; to look at `tarname' for hints. 858 (with-current-buffer buffer
803 (concat "./" name))))) 859 (goto-char (point-min))
804 (buffer (get-file-buffer new-buffer-file-name)) 860 (setq buffer-file-name new-buffer-file-name)
805 (just-created nil) 861 (setq buffer-file-truename
806 undo-list) 862 (abbreviate-file-name buffer-file-name))
807 (unless buffer 863 ;; Force buffer-file-coding-system to what
808 (setq buffer (generate-new-buffer bufname)) 864 ;; decode-coding-region actually used.
809 (with-current-buffer buffer 865 (set-buffer-file-coding-system last-coding-system-used t)
810 (setq undo-list buffer-undo-list 866 ;; Set the default-directory to the dir of the
811 buffer-undo-list t)) 867 ;; superior buffer.
812 (setq bufname (buffer-name buffer)) 868 (setq default-directory
813 (setq just-created t) 869 (with-current-buffer tar-buffer
814 (with-current-buffer tar-data-buffer 870 default-directory))
815 (let (coding) 871 (set-buffer-modified-p nil)
816 (narrow-to-region start end) 872 (setq buffer-undo-list t)
817 (goto-char start) 873 (normal-mode) ; pick a mode.
818 (setq coding (or coding-system-for-read 874 (set (make-local-variable 'tar-superior-buffer) tar-buffer)
819 (and set-auto-coding-function 875 (set (make-local-variable 'tar-superior-descriptor) descriptor)
820 (funcall set-auto-coding-function 876 (setq buffer-read-only read-only-p)
821 name (- end start))) 877 (tar-subfile-mode 1)))
822 ;; The following binding causes 878 (cond
823 ;; find-buffer-file-type-coding-system 879 (view-p
824 ;; (defined on dos-w32.el) to act as if 880 (view-buffer buffer (and just-created 'kill-buffer-if-not-modified)))
825 ;; the file being extracted existed, so 881 ((eq other-window-p 'display) (display-buffer buffer))
826 ;; that the file's contents' encoding and 882 (other-window-p (switch-to-buffer-other-window buffer))
827 ;; EOL format are auto-detected. 883 (t (switch-to-buffer buffer)))))
828 (let ((file-name-handler-alist
829 '(("" . tar-file-name-handler))))
830 (car (find-operation-coding-system
831 'insert-file-contents
832 (cons name (current-buffer)) t)))))
833 (if (or (not coding)
834 (eq (coding-system-type coding) 'undecided))
835 (setq coding (detect-coding-region start end t)))
836 (if (and (default-value 'enable-multibyte-characters)
837 (coding-system-get coding :for-unibyte))
838 (with-current-buffer buffer
839 (set-buffer-multibyte nil)))
840 (widen)
841 (decode-coding-region start end coding buffer)))
842 (with-current-buffer buffer
843 (goto-char (point-min))
844 (setq buffer-file-name new-buffer-file-name)
845 (setq buffer-file-truename
846 (abbreviate-file-name buffer-file-name))
847 ;; Force buffer-file-coding-system to what
848 ;; decode-coding-region actually used.
849 (set-buffer-file-coding-system last-coding-system-used t)
850 ;; Set the default-directory to the dir of the
851 ;; superior buffer.
852 (setq default-directory
853 (with-current-buffer tar-buffer
854 default-directory))
855 (rename-buffer bufname)
856 (set-buffer-modified-p nil)
857 (setq buffer-undo-list undo-list)
858 (normal-mode) ; pick a mode.
859 (set (make-local-variable 'tar-superior-buffer) tar-buffer)
860 (set (make-local-variable 'tar-superior-descriptor) descriptor)
861 (setq buffer-read-only read-only-p)
862 (tar-subfile-mode 1)))
863 (cond
864 (view-p
865 (view-buffer buffer (and just-created 'kill-buffer-if-not-modified)))
866 ((eq other-window-p 'display) (display-buffer buffer))
867 (other-window-p (switch-to-buffer-other-window buffer))
868 (t (switch-to-buffer buffer))))))
869 884
870 885
871(defun tar-extract-other-window () 886(defun tar-extract-other-window ()