aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChong Yidong2011-03-06 15:19:39 -0500
committerChong Yidong2011-03-06 15:19:39 -0500
commit5c69cb2ce354d499609c202ff3ad48240202bb15 (patch)
tree7273206acac51f594517aaaf8cc4f1f0b86ccaf9
parent78f5433f6ba4f787c766342b6ac68f79425bc685 (diff)
downloademacs-5c69cb2ce354d499609c202ff3ad48240202bb15.tar.gz
emacs-5c69cb2ce354d499609c202ff3ad48240202bb15.zip
Usability improvements to commands in package-x.el.
* lisp/emacs-lisp/package-x.el (package-archive-upload-base): Make it a defcustom. (package--update-file): Doc fix. Accept relative file names. (package--archive-contents-from-file): Remove the argument, since it's necessarily always "archive-contents". (package-maint-add-news-item): Pass relative file name args to package--update-file. (package-upload-buffer-internal): Prompt for a destination if package-archive-upload-base is invalid. Create the directory if it does not exist. (package-upload-buffer, package-upload-file): Doc fix.
-rw-r--r--lisp/ChangeLog14
-rw-r--r--lisp/emacs-lisp/package-x.el253
2 files changed, 159 insertions, 108 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index e4d402afa76..5e9e134e746 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,5 +1,19 @@
12011-03-06 Chong Yidong <cyd@stupidchicken.com> 12011-03-06 Chong Yidong <cyd@stupidchicken.com>
2 2
3 * emacs-lisp/package-x.el (package-archive-upload-base): Make it a
4 defcustom.
5 (package--update-file): Doc fix. Accept relative file names.
6 (package--archive-contents-from-file): Remove the argument, since
7 it's necessarily always "archive-contents".
8 (package-maint-add-news-item): Pass relative file name args to
9 package--update-file.
10 (package-upload-buffer-internal): Prompt for a destination if
11 package-archive-upload-base is invalid. Create the directory if
12 it does not exist.
13 (package-upload-buffer, package-upload-file): Doc fix.
14
152011-03-06 Chong Yidong <cyd@stupidchicken.com>
16
3 * isearch.el (isearch-mode-map): Bind C-y to isearch-yank-kill, 17 * isearch.el (isearch-mode-map): Bind C-y to isearch-yank-kill,
4 and move isearch-yank-line to M-s C-e (Bug#8183). 18 and move isearch-yank-line to M-s C-e (Bug#8183).
5 19
diff --git a/lisp/emacs-lisp/package-x.el b/lisp/emacs-lisp/package-x.el
index 61f23abf0a7..4de95f65702 100644
--- a/lisp/emacs-lisp/package-x.el
+++ b/lisp/emacs-lisp/package-x.el
@@ -27,21 +27,41 @@
27 27
28;;; Commentary: 28;;; Commentary:
29 29
30;; This file currently contains parts of the package system most 30;; This file currently contains parts of the package system that many
31;; people won't need, such as package uploading. 31;; won't need, such as package uploading.
32
33;; To upload to an archive, first set `package-archive-upload-base' to
34;; some desired directory. For testing purposes, you can specify any
35;; directory you want, but if you want the archive to be accessible to
36;; others via http, this is typically a directory in the /var/www tree
37;; (possibly one on a remote machine, accessed via Tramp).
38
39;; Then call M-x package-upload-file, which prompts for a file to
40;; upload. Alternatively, M-x package-upload-buffer uploads the
41;; current buffer, if it's visiting a package file.
42
43;; Once a package is uploaded, users can access it via the Package
44;; Menu, by adding the archive to `package-archives'.
32 45
33;;; Code: 46;;; Code:
34 47
35(require 'package) 48(require 'package)
36(defvar gnus-article-buffer) 49(defvar gnus-article-buffer)
37 50
38;; Note that this only works if you have the password, which you 51(defcustom package-archive-upload-base "/path/to/archive"
39;; probably don't :-). 52 "The base location of the archive to which packages are uploaded.
40(defvar package-archive-upload-base nil 53This should be an absolute directory name. If the archive is on
41 "Base location for uploading to package archive.") 54another machine, you may specify a remote name in the usual way,
55e.g. \"/ssh:foo@example.com:/var/www/packages/\".
56See Info node `(emacs)Remote Files'.
57
58Unlike `package-archives', you can't specify a HTTP URL."
59 :type 'directory
60 :group 'package
61 :version "24.1")
42 62
43(defvar package-update-news-on-upload nil 63(defvar package-update-news-on-upload nil
44 "Whether package upload should also update NEWS and RSS feeds.") 64 "Whether uploading a package should also update NEWS and RSS feeds.")
45 65
46(defun package--encode (string) 66(defun package--encode (string)
47 "Encode a string by replacing some characters with XML entities." 67 "Encode a string by replacing some characters with XML entities."
@@ -75,13 +95,18 @@
75 title " - " (package--encode text) 95 title " - " (package--encode text)
76 " </li>\n")) 96 " </li>\n"))
77 97
78(defun package--update-file (file location text) 98(defun package--update-file (file tag text)
99 "Update the package archive file named FILE.
100FILE should be relative to `package-archive-upload-base'.
101TAG is a string that can be found within the file; TEXT is
102inserted after its first occurrence in the file."
103 (setq file (expand-file-name file package-archive-upload-base))
79 (save-excursion 104 (save-excursion
80 (let ((old-buffer (find-buffer-visiting file))) 105 (let ((old-buffer (find-buffer-visiting file)))
81 (with-current-buffer (let ((find-file-visit-truename t)) 106 (with-current-buffer (let ((find-file-visit-truename t))
82 (or old-buffer (find-file-noselect file))) 107 (or old-buffer (find-file-noselect file)))
83 (goto-char (point-min)) 108 (goto-char (point-min))
84 (search-forward location) 109 (search-forward tag)
85 (forward-line) 110 (forward-line)
86 (insert text) 111 (insert text)
87 (let ((file-precious-flag t)) 112 (let ((file-precious-flag t))
@@ -105,30 +130,31 @@ Return the file contents, as a string, or nil if unsuccessful."
105 (buffer-substring-no-properties (point-min) (point-max))) 130 (buffer-substring-no-properties (point-min) (point-max)))
106 (kill-buffer buffer)))))) 131 (kill-buffer buffer))))))
107 132
108(defun package--archive-contents-from-file (file) 133(defun package--archive-contents-from-file ()
109 "Parse the given archive-contents file." 134 "Parse the archive-contents at `package-archive-upload-base'"
110 (if (not (file-exists-p file)) 135 (let ((file (expand-file-name "archive-contents"
111 ;; no existing archive-contents, possibly a new ELPA repo. 136 package-archive-upload-base)))
112 (list package-archive-version) 137 (if (not (file-exists-p file))
113 (let ((dont-kill (find-buffer-visiting file))) 138 ;; No existing archive-contents means a new archive.
114 (with-current-buffer (let ((find-file-visit-truename t)) 139 (list package-archive-version)
115 (find-file-noselect file)) 140 (let ((dont-kill (find-buffer-visiting file)))
116 (prog1 141 (with-current-buffer (let ((find-file-visit-truename t))
117 (package-read-from-string 142 (find-file-noselect file))
118 (buffer-substring-no-properties (point-min) (point-max))) 143 (prog1
119 (unless dont-kill 144 (package-read-from-string
120 (kill-buffer (current-buffer)))))))) 145 (buffer-substring-no-properties (point-min) (point-max)))
146 (unless dont-kill
147 (kill-buffer (current-buffer)))))))))
121 148
122(defun package-maint-add-news-item (title description archive-url) 149(defun package-maint-add-news-item (title description archive-url)
123 "Add a news item to the ELPA web pages. 150 "Add a news item to the webpages associated with the package archive.
124TITLE is the title of the news item. 151TITLE is the title of the news item.
125DESCRIPTION is the text of the news item. 152DESCRIPTION is the text of the news item."
126You need administrative access to ELPA to use this."
127 (interactive "sTitle: \nsText: ") 153 (interactive "sTitle: \nsText: ")
128 (package--update-file (concat package-archive-upload-base "elpa.rss") 154 (package--update-file "elpa.rss"
129 "<description>" 155 "<description>"
130 (package--make-rss-entry title description archive-url)) 156 (package--make-rss-entry title description archive-url))
131 (package--update-file (concat package-archive-upload-base "news.html") 157 (package--update-file "news.html"
132 "New entries go here" 158 "New entries go here"
133 (package--make-html-entry title description))) 159 (package--make-html-entry title description)))
134 160
@@ -144,8 +170,8 @@ PKG-INFO is the package info, see `package-buffer-info'.
144EXTENSION is the file extension, a string. It can be either 170EXTENSION is the file extension, a string. It can be either
145\"el\" or \"tar\". 171\"el\" or \"tar\".
146 172
147The variable `package-archive-upload-base' specifies the upload 173The upload destination is given by `package-archive-upload-base'.
148destination. If this is nil, signal an error. 174If its value is invalid, prompt for a directory.
149 175
150Optional arg ARCHIVE-URL is the URL of the destination archive. 176Optional arg ARCHIVE-URL is the URL of the destination archive.
151If it is non-nil, compute the new \"archive-contents\" file 177If it is non-nil, compute the new \"archive-contents\" file
@@ -156,85 +182,97 @@ addition, if `package-update-news-on-upload' is non-nil, call
156If ARCHIVE-URL is nil, compute the new \"archive-contents\" file 182If ARCHIVE-URL is nil, compute the new \"archive-contents\" file
157from the \"archive-contents\" at `package-archive-upload-base', 183from the \"archive-contents\" at `package-archive-upload-base',
158if it exists." 184if it exists."
159 (unless package-archive-upload-base 185 (let ((package-archive-upload-base package-archive-upload-base))
160 (error "No destination specified in `package-archive-upload-base'")) 186 ;; Check if `package-archive-upload-base' is valid.
161 (save-excursion 187 (when (or (not (stringp package-archive-upload-base))
162 (save-restriction 188 (eq package-archive-upload-base
163 (let* ((file-type (cond 189 (car-safe
164 ((equal extension "el") 'single) 190 (get 'package-archive-upload-base 'standard-value))))
165 ((equal extension "tar") 'tar) 191 (setq package-archive-upload-base
166 (t (error "Unknown extension `%s'" extension)))) 192 (read-directory-name
167 (file-name (aref pkg-info 0)) 193 "Base directory for package archive: ")))
168 (pkg-name (intern file-name)) 194 (unless (file-directory-p package-archive-upload-base)
169 (requires (aref pkg-info 1)) 195 (if (y-or-n-p (format "%s does not exist; create it? "
170 (desc (if (string= (aref pkg-info 2) "") 196 package-archive-upload-base))
171 (read-string "Description of package: ") 197 (make-directory package-archive-upload-base t)
172 (aref pkg-info 2))) 198 (error "Aborted")))
173 (pkg-version (aref pkg-info 3)) 199 (save-excursion
174 (commentary (aref pkg-info 4)) 200 (save-restriction
175 (split-version (version-to-list pkg-version)) 201 (let* ((file-type (cond
176 (pkg-buffer (current-buffer))) 202 ((equal extension "el") 'single)
177 203 ((equal extension "tar") 'tar)
178 ;; Get archive-contents from ARCHIVE-URL if it's non-nil, or 204 (t (error "Unknown extension `%s'" extension))))
179 ;; from `package-archive-upload-base' otherwise. 205 (file-name (aref pkg-info 0))
180 (let ((contents (or (package--archive-contents-from-url archive-url) 206 (pkg-name (intern file-name))
181 (package--archive-contents-from-file 207 (requires (aref pkg-info 1))
182 (concat package-archive-upload-base 208 (desc (if (string= (aref pkg-info 2) "")
183 "archive-contents")))) 209 (read-string "Description of package: ")
184 (new-desc (vector split-version requires desc file-type))) 210 (aref pkg-info 2)))
185 (if (> (car contents) package-archive-version) 211 (pkg-version (aref pkg-info 3))
186 (error "Unrecognized archive version %d" (car contents))) 212 (commentary (aref pkg-info 4))
187 (let ((elt (assq pkg-name (cdr contents)))) 213 (split-version (version-to-list pkg-version))
188 (if elt 214 (pkg-buffer (current-buffer)))
189 (if (version-list-<= split-version 215
190 (package-desc-vers (cdr elt))) 216 ;; Get archive-contents from ARCHIVE-URL if it's non-nil, or
191 (error "New package has smaller version: %s" pkg-version) 217 ;; from `package-archive-upload-base' otherwise.
192 (setcdr elt new-desc)) 218 (let ((contents (or (package--archive-contents-from-url archive-url)
193 (setq contents (cons (car contents) 219 (package--archive-contents-from-file)))
194 (cons (cons pkg-name new-desc) 220 (new-desc (vector split-version requires desc file-type)))
195 (cdr contents)))))) 221 (if (> (car contents) package-archive-version)
196 222 (error "Unrecognized archive version %d" (car contents)))
197 ;; Now CONTENTS is the updated archive contents. Upload 223 (let ((elt (assq pkg-name (cdr contents))))
198 ;; this and the package itself. For now we assume ELPA is 224 (if elt
199 ;; writable via file primitives. 225 (if (version-list-<= split-version
200 (let ((print-level nil) 226 (package-desc-vers (cdr elt)))
201 (print-length nil)) 227 (error "New package has smaller version: %s" pkg-version)
202 (write-region (concat (pp-to-string contents) "\n") 228 (setcdr elt new-desc))
203 nil 229 (setq contents (cons (car contents)
204 (concat package-archive-upload-base 230 (cons (cons pkg-name new-desc)
205 "archive-contents"))) 231 (cdr contents))))))
206 232
207 ;; If there is a commentary section, write it. 233 ;; Now CONTENTS is the updated archive contents. Upload
208 (when commentary 234 ;; this and the package itself. For now we assume ELPA is
209 (write-region commentary nil 235 ;; writable via file primitives.
210 (concat package-archive-upload-base 236 (let ((print-level nil)
211 (symbol-name pkg-name) "-readme.txt"))) 237 (print-length nil))
212 238 (write-region (concat (pp-to-string contents) "\n")
213 (set-buffer pkg-buffer) 239 nil
214 (write-region (point-min) (point-max) 240 (expand-file-name "archive-contents"
215 (concat package-archive-upload-base 241 package-archive-upload-base)))
216 file-name "-" pkg-version 242
217 "." extension) 243 ;; If there is a commentary section, write it.
218 nil nil nil 'excl) 244 (when commentary
219 245 (write-region commentary nil
220 ;; Write a news entry. 246 (expand-file-name
221 (and package-update-news-on-upload 247 (concat (symbol-name pkg-name) "-readme.txt")
222 archive-url 248 package-archive-upload-base)))
223 (package--update-news (concat file-name "." extension) 249
224 pkg-version desc archive-url)) 250 (set-buffer pkg-buffer)
225 251 (write-region (point-min) (point-max)
226 ;; special-case "package": write a second copy so that the 252 (expand-file-name
227 ;; installer can easily find the latest version. 253 (concat file-name "-" pkg-version "." extension)
228 (if (string= file-name "package") 254 package-archive-upload-base)
229 (write-region (point-min) (point-max) 255 nil nil nil 'excl)
230 (concat package-archive-upload-base 256
231 file-name "." extension) 257 ;; Write a news entry.
232 nil nil nil 'ask))))))) 258 (and package-update-news-on-upload
259 archive-url
260 (package--update-news (concat file-name "." extension)
261 pkg-version desc archive-url))
262
263 ;; special-case "package": write a second copy so that the
264 ;; installer can easily find the latest version.
265 (if (string= file-name "package")
266 (write-region (point-min) (point-max)
267 (expand-file-name
268 (concat file-name "." extension)
269 package-archive-upload-base)
270 nil nil nil 'ask))))))))
233 271
234(defun package-upload-buffer () 272(defun package-upload-buffer ()
235 "Upload the current buffer as a single-file Emacs Lisp package. 273 "Upload the current buffer as a single-file Emacs Lisp package.
236The variable `package-archive-upload-base' specifies the upload 274If `package-archive-upload-base' does not specify a valid upload
237destination." 275destination, prompt for one."
238 (interactive) 276 (interactive)
239 (save-excursion 277 (save-excursion
240 (save-restriction 278 (save-restriction
@@ -247,9 +285,8 @@ destination."
247Interactively, prompt for FILE. The package is considered a 285Interactively, prompt for FILE. The package is considered a
248single-file package if FILE ends in \".el\", and a multi-file 286single-file package if FILE ends in \".el\", and a multi-file
249package if FILE ends in \".tar\". 287package if FILE ends in \".tar\".
250 288If `package-archive-upload-base' does not specify a valid upload
251The variable `package-archive-upload-base' specifies the upload 289destination, prompt for one."
252destination."
253 (interactive "fPackage file name: ") 290 (interactive "fPackage file name: ")
254 (with-temp-buffer 291 (with-temp-buffer
255 (insert-file-contents-literally file) 292 (insert-file-contents-literally file)