Mercurial > hg > xemacs-beta
annotate lisp/package-get.el @ 5030:422b4b4fb2a6
Winclient updates
author | Vin Shelton <acs@xemacs.org> |
---|---|
date | Thu, 11 Feb 2010 19:33:50 -0500 |
parents | 2302bb5fa67d |
children | 2a54dfbe434f 308d34e9f07d |
rev | line source |
---|---|
428 | 1 ;;; package-get.el --- Retrieve XEmacs package |
2 | |
3 ;; Copyright (C) 1998 by Pete Ware | |
793 | 4 ;; Copyright (C) 2002 Ben Wing. |
1410 | 5 ;; Copyright (C) 2003, Steve Youngs |
428 | 6 |
7 ;; Author: Pete Ware <ware@cis.ohio-state.edu> | |
8 ;; Heavy-Modifications: Greg Klanderman <greg@alphatech.com> | |
9 ;; Jan Vroonhof <vroonhof@math.ethz.ch> | |
1410 | 10 ;; Steve Youngs <youngs@xemacs.org> |
428 | 11 ;; Keywords: internal |
12 | |
13 ;; This file is part of XEmacs. | |
14 | |
15 ;; XEmacs is free software; you can redistribute it and/or modify it | |
16 ;; under the terms of the GNU General Public License as published by | |
17 ;; the Free Software Foundation; either version 2, or (at your option) | |
18 ;; any later version. | |
19 | |
20 ;; XEmacs is distributed in the hope that it will be useful, but | |
21 ;; WITHOUT ANY WARRANTY; without even the implied warranty of | |
22 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
23 ;; General Public License for more details. | |
24 | |
25 ;; You should have received a copy of the GNU General Public License | |
26 ;; along with XEmacs; see the file COPYING. If not, write to the Free | |
27 ;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | |
28 ;; 02111-1307, USA. | |
29 | |
30 ;;; Synched up with: Not in FSF | |
31 | |
32 ;;; Commentary: | |
33 | |
34 ;; package-get - | |
35 ;; Retrieve a package and any other required packages from an archive | |
36 ;; | |
37 ;; | |
440 | 38 ;; Note (JV): Most of this no longer applies! |
428 | 39 ;; |
40 ;; The idea: | |
41 ;; A new XEmacs lisp-only release is generated with the following steps: | |
42 ;; 1. The maintainer runs some yet to be written program that | |
43 ;; generates all the dependency information. This should | |
44 ;; determine all the require and provide statements and associate | |
45 ;; them with a package. | |
46 ;; 2. All the packages are then bundled into their own tar balls | |
47 ;; (or whatever format) | |
48 ;; 3. Maintainer automatically generates a new `package-get-base' | |
49 ;; data structure which contains information such as the | |
50 ;; package name, the file to be retrieved, an md5 checksum, | |
51 ;; etc (see `package-get-base'). | |
52 ;; 4. The maintainer posts an announcement with the new version | |
53 ;; of `package-get-base'. | |
54 ;; 5. A user/system manager saves this posting and runs | |
55 ;; `package-get-update' which uses the previously saved list | |
56 ;; of packages, `package-get-here' that the user/site | |
57 ;; wants to determine what new versions to download and | |
58 ;; install. | |
59 ;; | |
60 ;; A user/site manager can generate a new `package-get-here' structure | |
61 ;; by using `package-get-setup' which generates a customize like | |
62 ;; interface to the list of packages. The buffer looks something | |
63 ;; like: | |
64 ;; | |
65 ;; gnus - a mail and news reader | |
66 ;; [] Always install | |
67 ;; [] Needs updating | |
68 ;; [] Required by other [packages] | |
69 ;; version: 2.0 | |
70 ;; | |
71 ;; vm - a mail reader | |
72 ;; [] Always install | |
73 ;; [] Needs updating | |
442 | 74 ;; [] Required by other [packages] |
428 | 75 ;; |
76 ;; Where `[]' indicates a toggle box | |
77 ;; | |
78 ;; - Clicking on "Always install" puts this into | |
79 ;; `package-get-here' list. "Needs updating" indicates a new | |
80 ;; version is available. Anything already in | |
81 ;; `package-get-here' has this enabled. | |
82 ;; - "Required by other" means some other packages are going to force | |
83 ;; this to be installed. Clicking on [packages] gives a list | |
84 ;; of packages that require this. | |
442 | 85 ;; |
428 | 86 ;; The `package-get-base' should be installed in a file in |
87 ;; `data-directory'. The `package-get-here' should be installed in | |
88 ;; site-lisp. Both are then read at run time. | |
89 ;; | |
90 ;; TODO: | |
91 ;; - Implement `package-get-setup' | |
92 ;; - Actually put `package-get-base' and `package-get-here' into | |
93 ;; files that are read. | |
94 ;; - Allow users to have their own packages that they want installed | |
95 ;; in ~/.xemacs/. | |
96 ;; - SOMEONE needs to write the programs that generate the | |
97 ;; provides/requires database and makes it into a lisp data | |
98 ;; structure suitable for `package-get-base' | |
99 ;; - Handle errors such as no package providing a required symbol. | |
100 ;; - Tie this into the `require' function to download packages | |
101 ;; transparently. | |
102 | |
103 ;;; Change Log | |
104 | |
105 ;;; Code: | |
106 | |
107 (require 'package-admin) | |
108 ;; (require 'package-get-base) | |
109 | |
110 (defgroup package-tools nil | |
111 "Tools to manipulate packages." | |
112 :group 'emacs) | |
113 | |
114 (defgroup package-get nil | |
115 "Automatic Package Fetcher and Installer." | |
116 :prefix "package-get" | |
117 :group 'package-tools) | |
118 | |
442 | 119 ;;;###autoload |
428 | 120 (defvar package-get-base nil |
121 "List of packages that are installed at this site. | |
122 For each element in the alist, car is the package name and the cdr is | |
123 a plist containing information about the package. Typical fields | |
124 kept in the plist are: | |
125 | |
126 version - version of this package | |
127 provides - list of symbols provided | |
128 requires - list of symbols that are required. | |
129 These in turn are provided by other packages. | |
130 filename - name of the file. | |
131 size - size of the file (aka the bundled package) | |
132 md5sum - computed md5 checksum | |
133 description - What this package is for. | |
134 type - Whether this is a 'binary (default) or 'single file package | |
135 | |
136 More fields may be added as needed. An example: | |
137 | |
138 '( | |
139 (name | |
140 (version \"<version 2>\" | |
141 file \"filename\" | |
142 description \"what this package is about.\" | |
143 provides (<list>) | |
144 requires (<list>) | |
145 size <integer-bytes> | |
146 md5sum \"<checksum\" | |
147 type single | |
148 ) | |
149 (version \"<version 1>\" | |
150 file \"filename\" | |
151 description \"what this package is about.\" | |
152 provides (<list>) | |
153 requires (<list>) | |
154 size <integer-bytes> | |
155 md5sum \"<checksum\" | |
156 type single | |
157 ) | |
158 ... | |
159 )) | |
160 | |
161 For version information, it is assumed things are listed in most | |
162 recent to least recent -- in other words, the version names don't have to | |
163 be lexically ordered. It is debatable if it makes sense to have more than | |
164 one version of a package available.") | |
165 | |
166 (defcustom package-get-dir (temp-directory) | |
167 "*Where to store temporary files for staging." | |
168 :tag "Temporary directory" | |
169 :type 'directory | |
170 :group 'package-get) | |
171 | |
1378 | 172 ;;;###autoload |
1483 | 173 (defcustom package-get-package-index-file-location |
3179 | 174 (cond |
175 ;; historical backage | |
176 ((getenv "EMACSPACKAGEPATH") | |
177 (split-path (getenv "EMACSPACKAGEPATH"))) | |
178 ((getenv "EMACSEARLYPACKAGES") | |
179 (split-path (getenv "EMACSEARLYPACKAGES"))) | |
180 (configure-early-package-directories | |
181 (car configure-early-package-directories)) | |
182 (t | |
183 user-init-directory)) | |
1483 | 184 "*The directory where the package-index file can be found." |
185 :type 'directory | |
186 :group 'package-get) | |
187 | |
188 ;;;###autoload | |
1378 | 189 (defcustom package-get-install-to-user-init-directory nil |
190 "*If non-nil install packages under `user-init-directory'." | |
191 :type 'boolean | |
192 :group 'package-get) | |
193 | |
428 | 194 (define-widget 'host-name 'string |
195 "A Host name." | |
196 :tag "Host") | |
197 | |
198 (defcustom package-get-remote nil | |
1365 | 199 "*The remote site to contact for downloading packages. |
200 Format is '(site-name directory-on-site). As a special case, `site-name' | |
201 can be `nil', in which case `directory-on-site' is treated as a local | |
202 directory." | |
428 | 203 :tag "Package repository" |
1365 | 204 :type '(set (choice (const :tag "None" nil) |
205 (list :tag "Local" (const :tag "Local" nil) directory) | |
206 (list :tag "Remote" host-name directory))) | |
428 | 207 :group 'package-get) |
208 | |
209 ;;;###autoload | |
210 (defcustom package-get-download-sites | |
211 '( | |
1365 | 212 ;; Main XEmacs Site (ftp.xemacs.org) |
1368 | 213 ("US (Main XEmacs Site)" |
1365 | 214 "ftp.xemacs.org" "pub/xemacs/packages") |
215 ;; In alphabetical order of Country, our mirrors... | |
3013 | 216 ("Argentina (xmundo.net)" "xemacs.xmundo.net" "pub/mirrors/xemacs/packages") |
1365 | 217 ("Australia (aarnet.edu.au)" "mirror.aarnet.edu.au" "pub/xemacs/packages") |
218 ("Australia (au.xemacs.org)" "ftp.au.xemacs.org" "pub/xemacs/packages") | |
219 ("Austria (at.xemacs.org)" "ftp.at.xemacs.org" "editors/xemacs/packages") | |
220 ("Belgium (be.xemacs.org)" "ftp.be.xemacs.org" "xemacs/packages") | |
221 ("Brazil (br.xemacs.org)" "ftp.br.xemacs.org" "pub/xemacs/packages") | |
222 ("Canada (ca.xemacs.org)" "ftp.ca.xemacs.org" "pub/Mirror/xemacs/packages") | |
3013 | 223 ("Canada (nrc.ca)" "ftp.nrc.ca" "pub/packages/editors/xemacs/packages") |
4120 | 224 ;; no anonymous ftp available, uncomment when updating website |
225 ;; with | |
226 ;; xemacs-builds/adrian/website/package-get-2-download-sites.el | |
4082 | 227 ; ("Chile (cl.xemacs.org)" "ftp.cl.xemacs.org" "packages") |
4188 | 228 ("China (ftp.cn.xemacs.org)" "ftp.cn.xemacs.org" "pub/xemacs/packages") |
1365 | 229 ("Czech Republic (cz.xemacs.org)" "ftp.cz.xemacs.org" "MIRRORS/ftp.xemacs.org/pub/xemacs/packages") |
230 ("Finland (fi.xemacs.org)" "ftp.fi.xemacs.org" "pub/mirrors/ftp.xemacs.org/pub/tux/xemacs/packages") | |
231 ("France (fr.xemacs.org)" "ftp.fr.xemacs.org" "pub/xemacs/packages") | |
1368 | 232 ("France (mirror.cict.fr)" "mirror.cict.fr" "xemacs/packages") |
1365 | 233 ("France (pasteur.fr)" "ftp.pasteur.fr" "pub/computing/xemacs/packages") |
234 ("Germany (de.xemacs.org)" "ftp.de.xemacs.org" "pub/ftp.xemacs.org/tux/xemacs/packages") | |
4034 | 235 ("Greece (gr.xemacs.org)" "ftp.gr.xemacs.org" "mirrors/XEmacs/ftp/packages") |
3141 | 236 ("Hong Kong (hk.xemacs.org)" "ftp.hk.xemacs.org" "pub/xemacsftp/packages") |
1365 | 237 ("Ireland (ie.xemacs.org)" "ftp.ie.xemacs.org" "mirrors/ftp.xemacs.org/pub/xemacs/packages") |
3013 | 238 ("Ireland (heanet.ie)" "ftp.heanet.ie" "mirrors/ftp.xemacs.org/packages") |
1365 | 239 ("Italy (it.xemacs.org)" "ftp.it.xemacs.org" "unix/packages/XEMACS/packages") |
240 ("Japan (dti.ad.jp)" "ftp.dti.ad.jp" "pub/unix/editor/xemacs/packages") | |
3116 | 241 ; ("Japan (jaist.ac.jp)" "ftp.jaist.ac.jp" "pub/GNU/xemacs/packages") |
4132 | 242 ("Japan (jp.xemacs.org)" "ftp.jp.xemacs.org" "pub/text/xemacs/packages") |
3013 | 243 ; ("Japan (nucba.ac.jp)" "mirror.nucba.ac.jp" "mirror/xemacs/packages") |
1374 | 244 ("Korea (kr.xemacs.org)" "ftp.kr.xemacs.org" "pub/tools/emacs/xemacs/packages") |
3438 | 245 ("Netherlands (nl.xemacs.org)" "ftp.nl.xemacs.org" "pub/xemacs/ftp/packages") |
4184 | 246 ;; no anonymous ftp available, uncomment when updating website |
247 ;; with | |
248 ;; xemacs-builds/adrian/website/package-get-2-download-sites.el | |
249 ; ("Netherlands (xemacsftp.digimirror.nl)" "xemacsftp.digimirror.nl" "packages") | |
1365 | 250 ("Norway (no.xemacs.org)" "ftp.no.xemacs.org" "pub/xemacs/packages") |
3193 | 251 ("Portugal (pt.xemacs.org)" "ftp.pt.xemacs.org" "pub/MIRRORS/ftp.xemacs.org/packages") |
3116 | 252 ("Russia (ru.xemacs.org)" "ftp.ru.xemacs.org" "pub/emacs/xemacs/packages") |
4009 | 253 ("Saudi Arabia (sa.xemacs.org)" "ftp.sa.xemacs.org" "pub/xemacs.org/packages") |
1365 | 254 ("Sweden (se.xemacs.org)" "ftp.se.xemacs.org" "pub/gnu/xemacs/packages") |
255 ("Switzerland (ch.xemacs.org)" "ftp.ch.xemacs.org" "mirror/xemacs/packages") | |
3021 | 256 ("Taiwan (ftp.tw.xemacs.org)" "ftp.tw.xemacs.org" "Unix/Editors/XEmacs/packages") |
1365 | 257 ("UK (uk.xemacs.org)" "ftp.uk.xemacs.org" "sites/ftp.xemacs.org/pub/xemacs/packages") |
3021 | 258 ("US (ibiblio.org)" "mirrors.ibiblio.org" "pub/mirrors/xemacs/packages") |
4120 | 259 ("US (us.xemacs.org)" "ftp.us.xemacs.org" "pub/mirrors/xemacs/packages") |
3116 | 260 ) |
428 | 261 "*List of remote sites available for downloading packages. |
262 List format is '(site-description site-name directory-on-site). | |
263 SITE-DESCRIPTION is a textual description of the site. SITE-NAME | |
264 is the internet address of the download site. DIRECTORY-ON-SITE | |
265 is the directory on the site in which packages may be found. | |
266 This variable is used to initialize `package-get-remote', the | |
267 variable actually used to specify package download sites." | |
268 :tag "Package download sites" | |
442 | 269 :type '(repeat (list (string :tag "Name") host-name directory)) |
428 | 270 :group 'package-get) |
271 | |
1365 | 272 ;;;###autoload |
273 (defcustom package-get-pre-release-download-sites | |
274 '( | |
275 ;; Main XEmacs Site (ftp.xemacs.org) | |
3116 | 276 ("US Pre-Releases (Main XEmacs Site)" "ftp.xemacs.org" |
1365 | 277 "pub/xemacs/beta/experimental/packages") |
278 ;; In alphabetical order of Country, our mirrors... | |
3013 | 279 ("Argentina Pre-Releases (xmundo.net)" "xemacs.xmundo.net" |
280 "pub/mirrors/xemacs/beta/experimental/packages") | |
1368 | 281 ("Australia Pre-Releases (aarnet.edu.au)" "mirror.aarnet.edu.au" |
1365 | 282 "pub/xemacs/beta/experimental/packages") |
1368 | 283 ("Australia Pre-Releases (au.xemacs.org)" "ftp.au.xemacs.org" |
1365 | 284 "pub/xemacs/beta/experimental/packages") |
1368 | 285 ("Austria Pre-Releases (at.xemacs.org)" "ftp.at.xemacs.org" |
3013 | 286 "editors/xemacs/beta/experimental/packages") |
4184 | 287 ("Belgium Pre-Releases (be.xemacs.org)" "ftp.be.xemacs.org" |
3013 | 288 "xemacs/beta/experimental/packages") |
1368 | 289 ("Brazil Pre-Releases (br.xemacs.org)" "ftp.br.xemacs.org" |
1365 | 290 "pub/xemacs/xemacs-21.5/experimental/packages") |
1368 | 291 ("Canada Pre-Releases (ca.xemacs.org)" "ftp.ca.xemacs.org" |
1365 | 292 "pub/Mirror/xemacs/beta/experimental/packages") |
3013 | 293 ("Canada Pre-Releases (nrc.ca)" "ftp.nrc.ca" |
294 "pub/packages/editors/xemacs/beta/experimental/packages") | |
4120 | 295 ;; no anonymous ftp available, uncomment when updating website |
296 ;; with | |
297 ;; xemacs-builds/adrian/website/package-get-2-download-sites.el | |
4082 | 298 ; ("Chile Pre-Releases (cl.xemacs.org)" "ftp.cl.xemacs.org" |
299 ; "beta/experimental/packages") | |
4188 | 300 ("China Pre-Releases (ftp.cn.xemacs.org)" "ftp.cn.xemacs.org" |
4184 | 301 "pub/xemacs/beta/experimental/packages") |
1368 | 302 ("Czech Republic Pre-Releases (cz.xemacs.org)" "ftp.cz.xemacs.org" |
1365 | 303 "MIRRORS/ftp.xemacs.org/pub/xemacs/xemacs-21.5/experimental/packages") |
1368 | 304 ("Finland Pre-Releases (fi.xemacs.org)" "ftp.fi.xemacs.org" |
1365 | 305 "pub/mirrors/ftp.xemacs.org/pub/tux/xemacs/beta/experimental/packages") |
1368 | 306 ("France Pre-Releases (fr.xemacs.org)" "ftp.fr.xemacs.org" |
1365 | 307 "pub/xemacs/beta/experimental/packages") |
1368 | 308 ("France Pre-Releases (mirror.cict.fr)" "mirror.cict.fr" |
309 "xemacs/beta/experimental/packages") | |
310 ("France Pre-Releases (pasteur.fr)" "ftp.pasteur.fr" | |
1365 | 311 "pub/computing/xemacs/beta/experimental/packages") |
1368 | 312 ("Germany Pre-Releases (de.xemacs.org)" "ftp.de.xemacs.org" |
1365 | 313 "pub/ftp.xemacs.org/tux/xemacs/beta/experimental/packages") |
4034 | 314 ("Greece Pre-Releases (gr.xemacs.org)" "ftp.gr.xemacs.org" |
315 "mirrors/XEmacs/ftp/beta/experimental/packages") | |
3141 | 316 ("Hong Kong Pre-Releases (hk.xemacs.org)" "ftp.hk.xemacs.org" |
317 "pub/xemacsftp/beta/experimental/packages") | |
1368 | 318 ("Ireland Pre-Releases (ie.xemacs.org)" "ftp.ie.xemacs.org" |
1365 | 319 "mirrors/ftp.xemacs.org/pub/xemacs/beta/experimental/packages") |
3013 | 320 ("Ireland Pre-Releases (heanet.ie)" "ftp.heanet.ie" |
321 "mirrors/ftp.xemacs.org/beta/experimental/packages") | |
1368 | 322 ("Italy Pre-Releases (it.xemacs.org)" "ftp.it.xemacs.org" |
1365 | 323 "unix/packages/XEMACS/beta/experimental/packages") |
1368 | 324 ("Japan Pre-Releases (dti.ad.jp)" "ftp.dti.ad.jp" |
1365 | 325 "pub/unix/editor/xemacs/beta/experimental/packages") |
3116 | 326 ; ("Japan Pre-Releases (jaist.ac.jp)" "ftp.jaist.ac.jp" |
327 ; "pub/GNU/xemacs/beta/experimental/packages") | |
4132 | 328 ("Japan Pre-Releases (jp.xemacs.org)" "ftp.jp.xemacs.org" |
329 "pub/text/xemacs/beta/experimental/packages") | |
4184 | 330 ("Korea Pre-Releases (kr.xemacs.org)" "ftp.kr.xemacs.org" |
3013 | 331 "pub/tools/emacs/xemacs/beta/experimental/packages") |
4184 | 332 ("Netherlands Pre-Releases (nl.xemacs.org)" "ftp.nl.xemacs.org" |
3438 | 333 "pub/xemacs/ftp/beta/experimental/packages") |
4184 | 334 ;; no anonymous ftp available, uncomment when updating website |
335 ;; with | |
336 ;; xemacs-builds/adrian/website/package-get-2-download-sites.el | |
337 ; ("Netherlands Pre-Releases (xemacsftp.digimirror.nl)" "xemacsftp.digimirror.nl" | |
338 ; "beta/experimental/packages") | |
1368 | 339 ("Norway Pre-Releases (no.xemacs.org)" "ftp.no.xemacs.org" |
1365 | 340 "pub/xemacs/beta/experimental/packages") |
3193 | 341 ("Portugal Pre-Releases (pt.xemacs.org)" "ftp.pt.xemacs.org" |
342 "pub/MIRRORS/ftp.xemacs.org/beta/experimental/packages") | |
1368 | 343 ("Russia Pre-Releases (ru.xemacs.org)" "ftp.ru.xemacs.org" |
3116 | 344 "pub/emacs/xemacs/beta/experimental/packages") |
4184 | 345 ("Saudi Arabia Pre-Releases (sa.xemacs.org)" "ftp.sa.xemacs.org" |
4009 | 346 "pub/xemacs.org/beta/experimental/packages") |
1368 | 347 ("Sweden Pre-Releases (se.xemacs.org)" "ftp.se.xemacs.org" |
1365 | 348 "pub/gnu/xemacs/beta/experimental/packages") |
1368 | 349 ("Switzerland Pre-Releases (ch.xemacs.org)" "ftp.ch.xemacs.org" |
1365 | 350 "mirror/xemacs/beta/experimental/packages") |
3021 | 351 ("Taiwan Pre-Releases (ftp.tw.xemacs.org)" "ftp.tw.xemacs.org" |
352 "Unix/Editors/XEmacs/beta/experimental/packages") | |
1368 | 353 ("UK Pre-Releases (uk.xemacs.org)" "ftp.uk.xemacs.org" |
1365 | 354 "sites/ftp.xemacs.org/pub/xemacs/beta/experimental/packages") |
3021 | 355 ("US Pre-Releases (ibiblio.org)" "mirrors.ibiblio.org" |
356 "pub/mirrors/xemacs/beta/experimental/packages") | |
1368 | 357 ("US Pre-Releases (us.xemacs.org)" "ftp.us.xemacs.org" |
4120 | 358 "pub/mirrors/xemacs/beta/experimental/packages") |
4132 | 359 ) |
1365 | 360 "*List of remote sites available for downloading \"Pre-Release\" packages. |
361 List format is '(site-description site-name directory-on-site). | |
362 SITE-DESCRIPTION is a textual description of the site. SITE-NAME | |
363 is the internet address of the download site. DIRECTORY-ON-SITE | |
364 is the directory on the site in which packages may be found. | |
365 This variable is used to initialize `package-get-remote', the | |
366 variable actually used to specify package download sites." | |
367 :tag "Pre-Release Package download sites" | |
368 :type '(repeat (list (string :tag "Name") host-name directory)) | |
369 :group 'package-get) | |
370 | |
1374 | 371 ;;;###autoload |
372 (defcustom package-get-site-release-download-sites | |
373 nil | |
374 "*List of remote sites available for downloading \"Site Release\" packages. | |
375 List format is '(site-description site-name directory-on-site). | |
376 SITE-DESCRIPTION is a textual description of the site. SITE-NAME | |
377 is the internet address of the download site. DIRECTORY-ON-SITE | |
378 is the directory on the site in which packages may be found. | |
379 This variable is used to initialize `package-get-remote', the | |
380 variable actually used to specify package download sites." | |
381 :tag "Site Release Package download sites" | |
382 :type '(repeat (list (string :tag "Name") host-name directory)) | |
383 :group 'package-get) | |
384 | |
428 | 385 (defcustom package-get-remove-copy t |
386 "*After copying and installing a package, if this is t, then remove the | |
387 copy. Otherwise, keep it around." | |
388 :type 'boolean | |
389 :group 'package-get) | |
390 | |
391 ;; #### it may make sense for this to be a list of names. | |
392 ;; #### also, should we rename "*base*" to "*index*" or "*db*"? | |
393 ;; "base" is a pretty poor name. | |
681 | 394 (defcustom package-get-base-filename "package-index.LATEST.gpg" |
428 | 395 "*Name of the default package-get database file. |
396 This may either be a relative path, in which case it is interpreted | |
397 with respect to `package-get-remote', or an absolute path." | |
398 :type 'file | |
399 :group 'package-get) | |
400 | |
401 (defcustom package-get-always-update nil | |
402 "*If Non-nil always make sure we are using the latest package index (base). | |
403 Otherwise respect the `force-current' argument of `package-get-require-base'." | |
404 :type 'boolean | |
405 :group 'package-get) | |
406 | |
681 | 407 (defvar package-get-continue-update-base nil |
408 "Non-nil update the index even if it hasn't been signed.") | |
409 | |
428 | 410 (defvar package-get-was-current nil |
411 "Non-nil we did our best to fetch a current database.") | |
412 | |
413 ;;;###autoload | |
414 (defun package-get-require-base (&optional force-current) | |
415 "Require that a package-get database has been loaded. | |
416 If the optional FORCE-CURRENT argument or the value of | |
417 `package-get-always-update' is Non-nil, try to update the database | |
418 from a location in `package-get-remote'. Otherwise a local copy is used | |
419 if available and remote access is never done. | |
420 | |
421 Please use FORCE-CURRENT only when the user is explictly dealing with packages | |
422 and remote access is likely in the near future." | |
423 (setq force-current (or force-current package-get-always-update)) | |
424 (unless (and (boundp 'package-get-base) | |
425 package-get-base | |
426 (or (not force-current) package-get-was-current)) | |
427 (package-get-update-base nil force-current)) | |
428 (if (or (not (boundp 'package-get-base)) | |
429 (not package-get-base)) | |
1410 | 430 (error 'void-variable |
431 "Package-get database not loaded") | |
428 | 432 (setq package-get-was-current force-current))) |
433 | |
434 ;;;###autoload | |
435 (defun package-get-update-base-entry (entry) | |
436 "Update an entry in `package-get-base'." | |
437 (let ((existing (assq (car entry) package-get-base))) | |
438 (if existing | |
439 (setcdr existing (cdr entry)) | |
824 | 440 (setq package-get-base (cons entry package-get-base))))) |
428 | 441 |
442 (defun package-get-locate-file (file &optional nil-if-not-found no-remote) | |
443 "Locate an existing FILE with respect to `package-get-remote'. | |
444 If FILE is an absolute path or is not found, simply return FILE. | |
445 If optional argument NIL-IF-NOT-FOUND is non-nil, return nil | |
446 if FILE can not be located. | |
447 If NO-REMOTE is non-nil never search remote locations." | |
448 (if (file-name-absolute-p file) | |
449 file | |
1365 | 450 (let ((site package-get-remote) |
428 | 451 (expanded nil)) |
1365 | 452 (when site |
453 (unless (and no-remote (caar (list site))) | |
454 (let ((expn (package-get-remote-filename (car (list site)) file))) | |
428 | 455 (if (and expn (file-exists-p expn)) |
1365 | 456 (setq site nil |
457 expanded expn))))) | |
428 | 458 (or expanded |
459 (and (not nil-if-not-found) | |
460 file))))) | |
461 | |
462 (defun package-get-locate-index-file (no-remote) | |
1483 | 463 "Locate the package-get index file. |
464 | |
465 Do not return remote paths if NO-REMOTE is non-nil. If the index | |
466 file doesn't exist in `package-get-package-index-file-location', ask | |
467 the user if one should be created using the index file in core as a | |
468 template." | |
428 | 469 (or (package-get-locate-file package-get-base-filename t no-remote) |
1483 | 470 (if (file-exists-p (expand-file-name package-get-base-filename |
471 package-get-package-index-file-location)) | |
472 (expand-file-name package-get-base-filename | |
473 package-get-package-index-file-location) | |
474 (if (y-or-n-p (format "No index file, shall I create one in %s? " | |
475 package-get-package-index-file-location)) | |
476 (progn | |
477 (save-excursion | |
478 (set-buffer | |
479 (find-file-noselect (expand-file-name | |
480 package-get-base-filename | |
481 package-get-package-index-file-location))) | |
482 (let ((coding-system-for-write 'binary)) | |
483 (erase-buffer) | |
484 (insert-file-contents-literally | |
485 (locate-data-file package-get-base-filename)) | |
486 (save-buffer (current-buffer)) | |
487 (kill-buffer (current-buffer)))) | |
488 (expand-file-name package-get-base-filename | |
489 package-get-package-index-file-location)) | |
490 (error 'search-failed | |
491 "Can't locate a package index file."))))) | |
428 | 492 |
493 (defun package-get-maybe-save-index (filename) | |
494 "Offer to save the current buffer as the local package index file, | |
495 if different." | |
496 (let ((location (package-get-locate-index-file t))) | |
497 (unless (and filename (equal filename location)) | |
498 (unless (and location | |
499 (equal (md5 (current-buffer)) | |
500 (with-temp-buffer | |
501 (insert-file-contents-literally location) | |
502 (md5 (current-buffer))))) | |
1483 | 503 (when (not (file-writable-p location)) |
504 (if (y-or-n-p (format "Sorry, %s is read-only, can I use %s? " | |
505 location user-init-directory)) | |
506 (setq location (expand-file-name | |
507 package-get-base-filename | |
508 package-get-package-index-file-location)) | |
509 (error 'file-error | |
510 (format "%s is read-only" location)))) | |
434 | 511 (when (y-or-n-p (concat "Update package index in " location "? ")) |
442 | 512 (let ((coding-system-for-write 'binary)) |
513 (write-file location))))))) | |
514 | |
428 | 515 ;;;###autoload |
516 (defun package-get-update-base (&optional db-file force-current) | |
517 "Update the package-get database file with entries from DB-FILE. | |
518 Unless FORCE-CURRENT is non-nil never try to update the database." | |
519 (interactive | |
520 (let ((dflt (package-get-locate-index-file nil))) | |
521 (list (read-file-name "Load package-get database: " | |
522 (file-name-directory dflt) | |
523 dflt | |
524 t | |
525 (file-name-nondirectory dflt))))) | |
526 (setq db-file (expand-file-name (or db-file | |
527 (package-get-locate-index-file | |
528 (not force-current))))) | |
529 (if (not (file-exists-p db-file)) | |
1410 | 530 (error 'file-error |
531 (format "Package-get database file `%s' does not exist" db-file))) | |
428 | 532 (if (not (file-readable-p db-file)) |
1410 | 533 (error 'file-error |
534 (format "Package-get database file `%s' not readable" db-file))) | |
428 | 535 (let ((buf (get-buffer-create "*package database*"))) |
536 (unwind-protect | |
537 (save-excursion | |
538 (set-buffer buf) | |
539 (erase-buffer buf) | |
442 | 540 (insert-file-contents-literally db-file) |
428 | 541 (package-get-update-base-from-buffer buf) |
542 (if (file-remote-p db-file) | |
543 (package-get-maybe-save-index db-file))) | |
544 (kill-buffer buf)))) | |
545 | |
546 ;;;###autoload | |
547 (defun package-get-update-base-from-buffer (&optional buf) | |
548 "Update the package-get database with entries from BUFFER. | |
549 BUFFER defaults to the current buffer. This command can be | |
550 used interactively, for example from a mail or news buffer." | |
551 (interactive) | |
552 (setq buf (or buf (current-buffer))) | |
1937 | 553 (let ((coding-system-for-read 'binary) |
554 (coding-system-for-write 'binary) | |
555 content-beg content-end) | |
428 | 556 (save-excursion |
557 (set-buffer buf) | |
558 (goto-char (point-min)) | |
559 (setq content-beg (point)) | |
560 (setq content-end (save-excursion (goto-char (point-max)) (point))) | |
4160 | 561 (package-get-update-base-entries content-beg content-end) |
562 (message "Updated package database")))) | |
428 | 563 |
444 | 564 (defun package-get-update-base-entries (start end) |
428 | 565 "Update the package-get database with the entries found between |
444 | 566 START and END in the current buffer." |
428 | 567 (save-excursion |
444 | 568 (goto-char start) |
428 | 569 (if (not (re-search-forward "^(package-get-update-base-entry" nil t)) |
1410 | 570 (error 'search-failed |
571 "Buffer does not contain package-get database entries")) | |
428 | 572 (beginning-of-line) |
573 (let ((count 0)) | |
574 (while (and (< (point) end) | |
575 (re-search-forward "^(package-get-update-base-entry" nil t)) | |
576 (beginning-of-line) | |
577 (let ((entry (read (current-buffer)))) | |
578 (if (or (not (consp entry)) | |
579 (not (eq (car entry) 'package-get-update-base-entry))) | |
1410 | 580 (error 'syntax-error |
581 "Invalid package-get database entry found")) | |
428 | 582 (package-get-update-base-entry |
583 (car (cdr (car (cdr entry))))) | |
584 (setq count (1+ count)))) | |
585 (message "Got %d package-get database entries" count)))) | |
586 | |
587 ;;;###autoload | |
588 (defun package-get-save-base (file) | |
589 "Write the package-get database to FILE. | |
590 | |
591 Note: This database will be unsigned of course." | |
592 (interactive "FSave package-get database to: ") | |
593 (package-get-require-base t) | |
594 (let ((buf (get-buffer-create "*package database*"))) | |
595 (unwind-protect | |
596 (save-excursion | |
597 (set-buffer buf) | |
598 (erase-buffer buf) | |
599 (goto-char (point-min)) | |
600 (let ((entries package-get-base) entry plist) | |
601 (insert ";; Package Index file -- Do not edit manually.\n") | |
602 (insert ";;;@@@\n") | |
603 (while entries | |
604 (setq entry (car entries)) | |
605 (setq plist (car (cdr entry))) | |
606 (insert "(package-get-update-base-entry (quote\n") | |
607 (insert (format "(%s\n" (symbol-name (car entry)))) | |
608 (while plist | |
609 (insert (format " %s%s %S\n" | |
610 (if (eq plist (car (cdr entry))) "(" " ") | |
611 (symbol-name (car plist)) | |
612 (car (cdr plist)))) | |
613 (setq plist (cdr (cdr plist)))) | |
614 (insert "))\n))\n;;;@@@\n") | |
615 (setq entries (cdr entries)))) | |
616 (insert ";; Package Index file ends here\n") | |
617 (write-region (point-min) (point-max) file)) | |
618 (kill-buffer buf)))) | |
619 | |
620 (defun package-get-interactive-package-query (get-version package-symbol) | |
621 "Perform interactive querying for package and optional version. | |
622 Query for a version if GET-VERSION is non-nil. Return package name as | |
623 a symbol instead of a string if PACKAGE-SYMBOL is non-nil. | |
624 The return value is suitable for direct passing to `interactive'." | |
625 (package-get-require-base t) | |
442 | 626 (let ((table (mapcar #'(lambda (item) |
627 (let ((name (symbol-name (car item)))) | |
628 (cons name name))) | |
629 package-get-base)) | |
630 package package-symbol default-version version) | |
428 | 631 (save-window-excursion |
632 (setq package (completing-read "Package: " table nil t)) | |
633 (setq package-symbol (intern package)) | |
634 (if get-version | |
635 (progn | |
442 | 636 (setq default-version |
637 (package-get-info-prop | |
428 | 638 (package-get-info-version |
639 (package-get-info-find-package package-get-base | |
640 package-symbol) nil) | |
641 'version)) | |
642 (while (string= | |
643 (setq version (read-string "Version: " default-version)) | |
1365 | 644 "")) |
428 | 645 (if package-symbol |
646 (list package-symbol version) | |
1365 | 647 (list package version))) |
428 | 648 (if package-symbol |
649 (list package-symbol) | |
442 | 650 (list package)))))) |
428 | 651 |
652 ;;;###autoload | |
653 (defun package-get-delete-package (package &optional pkg-topdir) | |
654 "Delete an installation of PACKAGE below directory PKG-TOPDIR. | |
655 PACKAGE is a symbol, not a string. | |
656 This is just an interactive wrapper for `package-admin-delete-binary-package'." | |
657 (interactive (package-get-interactive-package-query nil t)) | |
658 (package-admin-delete-binary-package package pkg-topdir)) | |
659 | |
660 ;;;###autoload | |
661 (defun package-get-update-all () | |
662 "Fetch and install the latest versions of all currently installed packages." | |
663 (interactive) | |
664 (package-get-require-base t) | |
665 ;; Load a fresh copy | |
666 (catch 'exit | |
4783
e29fcfd8df5f
Eliminate most core code byte-compile warnings.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4188
diff
changeset
|
667 (mapc (lambda (pkg) |
e29fcfd8df5f
Eliminate most core code byte-compile warnings.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4188
diff
changeset
|
668 (if (not (package-get (car pkg) nil 'never)) |
e29fcfd8df5f
Eliminate most core code byte-compile warnings.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4188
diff
changeset
|
669 (throw 'exit nil))) ;; Bail out if error detected |
e29fcfd8df5f
Eliminate most core code byte-compile warnings.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4188
diff
changeset
|
670 packages-package-list)) |
707 | 671 (package-net-update-installed-db)) |
428 | 672 |
673 ;;;###autoload | |
674 (defun package-get-all (package version &optional fetched-packages install-dir) | |
675 "Fetch PACKAGE with VERSION and all other required packages. | |
676 Uses `package-get-base' to determine just what is required and what | |
677 package provides that functionality. If VERSION is nil, retrieves | |
678 latest version. Optional argument FETCHED-PACKAGES is used to keep | |
679 track of packages already fetched. Optional argument INSTALL-DIR, | |
680 if non-nil, specifies the package directory where fetched packages | |
681 should be installed. | |
682 | |
683 Returns nil upon error." | |
684 (interactive (package-get-interactive-package-query t nil)) | |
685 (let* ((the-package (package-get-info-find-package package-get-base | |
686 package)) | |
687 (this-package (package-get-info-version | |
688 the-package version)) | |
1365 | 689 (this-requires (package-get-info-prop this-package 'requires))) |
428 | 690 (catch 'exit |
691 (setq version (package-get-info-prop this-package 'version)) | |
692 (unless (package-get-installedp package version) | |
693 (if (not (package-get package version nil install-dir)) | |
694 (progn | |
695 (setq fetched-packages nil) | |
696 (throw 'exit nil)))) | |
697 (setq fetched-packages | |
698 (append (list package) | |
699 (package-get-info-prop this-package 'provides) | |
700 fetched-packages)) | |
701 ;; grab everything that this package requires plus recursively | |
702 ;; grab everything that the requires require. Keep track | |
703 ;; in `fetched-packages' the list of things provided -- this | |
704 ;; keeps us from going into a loop | |
705 (while this-requires | |
706 (if (not (member (car this-requires) fetched-packages)) | |
707 (let* ((reqd-package (package-get-package-provider | |
708 (car this-requires) t)) | |
709 (reqd-version (cadr reqd-package)) | |
710 (reqd-name (car reqd-package))) | |
711 (if (null reqd-name) | |
1410 | 712 (error 'search-failed |
713 (format "Unable to find a provider for %s" | |
714 (car this-requires)))) | |
428 | 715 (if (not (setq fetched-packages |
716 (package-get-all reqd-name reqd-version | |
717 fetched-packages | |
718 install-dir))) | |
1365 | 719 (throw 'exit nil)))) |
720 (setq this-requires (cdr this-requires)))) | |
721 fetched-packages)) | |
428 | 722 |
723 ;;;###autoload | |
724 (defun package-get-dependencies (packages) | |
725 "Compute dependencies for PACKAGES. | |
726 Uses `package-get-base' to determine just what is required and what | |
727 package provides that functionality. Returns the list of packages | |
728 required by PACKAGES." | |
729 (package-get-require-base t) | |
730 (let ((orig-packages packages) | |
731 dependencies provided) | |
732 (while packages | |
733 (let* ((package (car packages)) | |
734 (the-package (package-get-info-find-package | |
735 package-get-base package)) | |
736 (this-package (package-get-info-version | |
737 the-package nil)) | |
738 (this-requires (package-get-info-prop this-package 'requires)) | |
739 (new-depends (set-difference | |
740 (mapcar | |
741 #'(lambda (reqd) | |
742 (let* ((reqd-package (package-get-package-provider reqd)) | |
743 (reqd-name (car reqd-package))) | |
744 (if (null reqd-name) | |
1410 | 745 (error 'search-failed |
746 (format "Unable to find a provider for %s" reqd))) | |
428 | 747 reqd-name)) |
748 this-requires) | |
749 dependencies)) | |
750 (this-provides (package-get-info-prop this-package 'provides))) | |
751 (setq dependencies | |
752 (union dependencies new-depends)) | |
753 (setq provided | |
754 (union provided (union (list package) this-provides))) | |
755 (setq packages | |
756 (union new-depends (cdr packages))))) | |
757 (set-difference dependencies orig-packages))) | |
758 | |
759 (defun package-get-load-package-file (lispdir file) | |
760 (let (pathname) | |
761 (setq pathname (expand-file-name file lispdir)) | |
793 | 762 (with-trapping-errors |
763 :operation (format "loading package file \"%s\"" pathname) | |
764 :error-form nil | |
765 (load pathname t) | |
766 t))) | |
428 | 767 |
768 (defun package-get-init-package (lispdir) | |
769 "Initialize the package. | |
770 This really assumes that the package has never been loaded. Updating | |
771 a newer package can cause problems, due to old, obsolete functions in | |
772 the old package. | |
773 | |
774 Return `t' upon complete success, `nil' if any errors occurred." | |
775 (progn | |
776 (if (and lispdir | |
777 (file-accessible-directory-p lispdir)) | |
778 (progn | |
779 ;; Add lispdir to load-path if it doesn't already exist. | |
780 ;; NOTE: this does not take symlinks, etc., into account. | |
2802 | 781 (add-to-list 'load-path (file-name-as-directory lispdir)) |
428 | 782 (if (not (package-get-load-package-file lispdir "auto-autoloads")) |
783 (package-get-load-package-file lispdir "_pkg")) | |
784 t) | |
1365 | 785 nil))) |
786 | |
2151 | 787 (defun package-get-info-name-array () |
788 "Internal, used by `package-get-info'." | |
789 (let ((pkgs package-get-base) | |
790 names) | |
791 (while pkgs | |
792 (setq names (let ((name (caar pkgs))) | |
793 (push (cons (format "%s" name) name) names))) | |
794 (setq pkgs (cdr pkgs))) | |
795 names)) | |
796 | |
797 (defconst package-get-info-info-array | |
798 '(("standards-version" . standards-version) | |
799 ("version" . version) | |
800 ("author-version" . author-version) | |
801 ("date" . date) | |
802 ("build-date" . build-date) | |
803 ("maintainer" . maintainer) | |
804 ("distribution" . distribution) | |
805 ("priority" . priority) | |
806 ("category" . category) | |
807 ("dump" . dump) | |
808 ("description" . description) | |
809 ("filename" . filename) | |
810 ("md5sum" . md5sum) | |
811 ("size" . size) | |
812 ("provides" . provides) | |
813 ("requires" . requires) | |
814 ("type" . type)) | |
815 "Internal, used by `package-get-info'.") | |
816 | |
1365 | 817 ;;;###autoload |
818 (defun package-get-info (package information &optional arg remote) | |
819 "Get information about a package. | |
820 | |
821 Quite similar to `package-get-info-prop', but can retrieve a lot more | |
822 information. | |
823 | |
824 Argument PACKAGE is the name of an XEmacs package (a symbol). It must | |
825 be a valid package, ie, a member of `package-get-base'. | |
826 | |
827 Argument INFORMATION is a symbol that can be any one of: | |
828 | |
829 standards-version Package system version (not used). | |
830 version Version of the XEmacs package. | |
831 author-version The upstream version of the package. | |
832 date The date the package was last modified. | |
833 build-date The date the package was last built. | |
834 maintainer The maintainer of the package. | |
835 distribution Will always be \"xemacs\" (not used). | |
836 priority \"low\", \"medium\", or \"high\" (not used). | |
837 category Either \"standard\", \"mule\", or \"unsupported\".. | |
838 dump Is the package dumped (not used). | |
839 description A description of the package. | |
840 filename The filename of the binary tarball of the package. | |
841 md5sum The md5sum of filename. | |
842 size The size in bytes of filename. | |
843 provides A list of symbols that this package provides. | |
844 requires A list of packages that this package requires. | |
845 type Can be either \"regular\" or \"single-file\". | |
846 | |
2151 | 847 Optional argument ARG is a prefix arg. Without a value, ie, just |
848 doing `C-u M-x package-get-info' will insert the information at point | |
849 in the current buffer using a local package list. | |
850 | |
851 ARG can also be given a value of 2 or 3. If 2, use a remote package | |
852 list, displaying the information in the minubuffer. If 3, use a remote | |
853 package list and insert the information at point in the current buffer. | |
1365 | 854 |
855 If optional argument REMOTE is non-nil use a package list from a | |
2151 | 856 remote site. |
857 | |
858 To use a remote package list, either via the prefix argument ARG or | |
859 via the REMOTE argument `package-get-remote' must be non-nil. If | |
860 `package-get-remote' is nil, the local package list will be used. | |
1365 | 861 |
862 If this function is called interactively it will display INFORMATION | |
863 in the minibuffer." | |
2151 | 864 (interactive "i\ni\np") |
865 (if (and package-get-remote | |
866 (or (eq arg 2) | |
867 (eq arg 3) | |
868 remote)) | |
869 (package-get-require-base t) | |
870 (package-get-require-base nil)) | |
871 (let ((all-pkgs package-get-base) | |
872 (package (or package | |
873 (intern (completing-read | |
874 "Package: " | |
875 (package-get-info-name-array) nil t)))) | |
876 (information (or information | |
877 (intern (completing-read | |
878 "Info: " | |
879 package-get-info-info-array nil t)))) | |
880 info) | |
1365 | 881 (loop until (equal package (caar all-pkgs)) |
882 do (setq all-pkgs (cdr all-pkgs)) | |
883 do (if (not all-pkgs) | |
1410 | 884 (error 'invalid-argument |
885 (format "%s is not a valid package" package)))) | |
1365 | 886 (setq info (plist-get (cadar all-pkgs) information)) |
887 (if (interactive-p) | |
2151 | 888 (if (or (eq arg 3) |
889 (eq arg 4)) | |
1365 | 890 (insert (format "%s" info)) |
891 (if (package-get-key package :version) | |
892 (message "%s" info) | |
893 (message "%s (Package: %s is not installed)" info package))) | |
2151 | 894 info))) |
428 | 895 |
896 ;;;###autoload | |
1832 | 897 (defun package-get-list-packages-where (item field &optional arg) |
898 "Return a list of packages that fulfill certain criteria. | |
899 | |
900 Argument ITEM, a symbol, is what you want to check for. ITEM must be a | |
901 symbol even when it doesn't make sense to be a symbol \(think, searching | |
902 maintainers, descriptions, etc\). The function will convert the symbol | |
903 to a string if a string is what is needed. The downside to this is that | |
904 ITEM can only ever be a single word. | |
905 | |
906 Argument FIELD, a symbol, is the field to check in. You can specify | |
907 any one of: | |
908 | |
909 Field Sane or Allowable Content | |
910 description any single word | |
911 category `standard' or `mule' | |
912 maintainer any single word | |
913 build-date yyyy-mm-dd | |
914 date yyyy-mm-dd | |
915 type `regular' or `single' | |
916 requires any package name | |
917 provides any symbol | |
918 priority `low', `medium', or `high' | |
919 | |
920 Optional Argument ARG, a prefix arg, insert output at point in the | |
921 current buffer." | |
2151 | 922 (interactive |
923 (list (intern (read-string "List packages that contain (text): ")) | |
924 (intern (completing-read "in their package-info field (completion available): " | |
925 '(("description" . description) | |
926 ("category" . category) | |
927 ("maintainer" . maintainer) | |
928 ("build-date" . build-date) | |
929 ("date" . date) | |
930 ("type" . type) | |
931 ("requires" . requires) | |
932 ("provides" . provides) | |
933 ("priority" . priority)) nil t)) | |
934 current-prefix-arg)) | |
1832 | 935 (package-get-require-base nil) |
936 (let ((pkgs package-get-base) | |
937 (strings '(description category maintainer build-date date)) | |
938 (symbols '(type requires provides priority)) | |
939 results) | |
940 (cond ((memq field strings) | |
941 (setq item (symbol-name item)) | |
942 (while pkgs | |
943 (when (string-match item (package-get-info (caar pkgs) field)) | |
944 (setq results (push (caar pkgs) results))) | |
945 (setq pkgs (cdr pkgs)))) | |
946 ((memq field symbols) | |
947 (if (or (eq field 'type) | |
948 (eq field 'priority)) | |
949 (while pkgs | |
950 (when (eq item (package-get-info (caar pkgs) field)) | |
951 (setq results (push (caar pkgs) results))) | |
952 (setq pkgs (cdr pkgs))) | |
953 (while pkgs | |
954 (when (memq item (package-get-info (caar pkgs) field)) | |
955 (setq results (push (caar pkgs) results))) | |
956 (setq pkgs (cdr pkgs))))) | |
957 (t | |
958 (error 'wrong-type-argument field))) | |
959 (if (interactive-p) | |
960 (if arg | |
961 (insert (format "%s" results)) | |
962 (message "%s" results))) | |
963 results)) | |
964 | |
965 ;;;###autoload | |
428 | 966 (defun package-get (package &optional version conflict install-dir) |
967 "Fetch PACKAGE from remote site. | |
968 Optional arguments VERSION indicates which version to retrieve, nil | |
969 means most recent version. CONFLICT indicates what happens if the | |
970 package is already installed. Valid values for CONFLICT are: | |
971 'always always retrieve the package even if it is already installed | |
972 'never do not retrieve the package if it is installed. | |
973 INSTALL-DIR, if non-nil, specifies the package directory where | |
974 fetched packages should be installed. | |
975 | |
442 | 976 The value of `package-get-base' is used to determine what files should |
428 | 977 be retrieved. The value of `package-get-remote' is used to determine |
1365 | 978 where a package should be retrieved from. |
428 | 979 |
980 Once the package is retrieved, its md5 checksum is computed. If that | |
981 sum does not match that stored in `package-get-base' for this version | |
982 of the package, an error is signalled. | |
983 | |
984 Returns `t' upon success, the symbol `error' if the package was | |
985 successfully installed but errors occurred during initialization, or | |
986 `nil' upon error." | |
987 (interactive (package-get-interactive-package-query nil t)) | |
988 (catch 'skip-update | |
989 (let* ((this-package | |
990 (package-get-info-version | |
991 (package-get-info-find-package package-get-base | |
992 package) version)) | |
993 (latest (package-get-info-prop this-package 'version)) | |
994 (installed (package-get-key package :version)) | |
995 (found nil) | |
1365 | 996 (search-dir package-get-remote) |
428 | 997 (base-filename (package-get-info-prop this-package 'filename)) |
998 (package-status t) | |
999 filenames full-package-filename) | |
1365 | 1000 (if (and (equal (package-get-info package 'category) "mule") |
1001 (not (featurep 'mule))) | |
1410 | 1002 (error 'invalid-state |
1003 "Mule packages can't be installed with a non-Mule XEmacs")) | |
428 | 1004 (if (null this-package) |
1005 (if package-get-remote | |
1410 | 1006 (error 'search-failed |
1007 (format "Couldn't find package %s with version %s" | |
1008 package version)) | |
1009 (error 'syntax-error | |
1010 "No download site or local package location specified."))) | |
428 | 1011 (if (null base-filename) |
1410 | 1012 (error 'syntax-error |
1013 (format "No filename associated with package %s, version %s" | |
1014 package version))) | |
1378 | 1015 (setq install-dir (package-admin-get-install-dir package install-dir)) |
428 | 1016 |
1017 ;; If they asked for the latest using version=nil, don't get an older | |
1018 ;; version than we already have. | |
1019 (if installed | |
1020 (if (> (if (stringp installed) | |
1021 (string-to-number installed) | |
1022 installed) | |
1023 (if (stringp latest) | |
1024 (string-to-number latest) | |
1025 latest)) | |
1026 (if (not (null version)) | |
825 | 1027 (warn "Installing %s package version %s, you had a newer version %s" |
793 | 1028 package latest installed) |
825 | 1029 (warn "Skipping %s package, you have a newer version %s" |
793 | 1030 package installed) |
428 | 1031 (throw 'skip-update t)))) |
1032 | |
1033 ;; Contrive a list of possible package filenames. | |
1034 ;; Ugly. Is there a better way to do this? | |
1035 (setq filenames (cons base-filename nil)) | |
1036 (if (string-match "^\\(..*\\)\.tar\.gz$" base-filename) | |
1037 (setq filenames (append filenames | |
1038 (list (concat (match-string 1 base-filename) | |
1039 ".tgz"))))) | |
1040 | |
1041 (setq version latest) | |
1042 (unless (and (eq conflict 'never) | |
1043 (package-get-installedp package version)) | |
1044 ;; Find the package from the search list in package-get-remote | |
1045 ;; and copy it into the staging directory. Then validate | |
1046 ;; the checksum. Finally, install the package. | |
1047 (catch 'done | |
1365 | 1048 (let (search-filenames host dir current-filename dest-filename) |
428 | 1049 ;; In each search directory ... |
1365 | 1050 (when search-dir |
1051 (setq host (car search-dir) | |
1052 dir (car (cdr search-dir)) | |
1053 search-filenames filenames) | |
428 | 1054 |
1055 ;; Look for one of the possible package filenames ... | |
1056 (while search-filenames | |
1057 (setq current-filename (car search-filenames) | |
1058 dest-filename (package-get-staging-dir current-filename)) | |
1059 (cond | |
1060 ;; No host means look on the current system. | |
1365 | 1061 ((null host) |
1062 (setq full-package-filename | |
1063 (substitute-in-file-name | |
1064 (expand-file-name current-filename | |
1065 (file-name-as-directory dir))))) | |
428 | 1066 |
1067 ;; If it's already on the disk locally, and the size is | |
1365 | 1068 ;; correct |
1069 ((and (file-exists-p dest-filename) | |
1070 (eq (nth 7 (file-attributes dest-filename)) | |
1071 (package-get-info package 'size))) | |
1072 (setq full-package-filename dest-filename)) | |
428 | 1073 |
1074 ;; If the file exists on the remote system ... | |
1365 | 1075 ((file-exists-p (package-get-remote-filename |
1076 search-dir current-filename)) | |
1077 ;; Get it | |
1078 (setq full-package-filename dest-filename) | |
1079 (message "Retrieving package `%s' ..." | |
1080 current-filename) | |
1081 (sit-for 0) | |
1082 (copy-file (package-get-remote-filename search-dir | |
1083 current-filename) | |
1084 full-package-filename t))) | |
428 | 1085 |
1086 ;; If we found it, we're done. | |
1087 (if (and full-package-filename | |
1088 (file-exists-p full-package-filename)) | |
1089 (throw 'done nil)) | |
1090 ;; Didn't find it. Try the next possible filename. | |
1365 | 1091 (setq search-filenames (cdr search-filenames)))))) |
428 | 1092 |
1093 (if (or (not full-package-filename) | |
1094 (not (file-exists-p full-package-filename))) | |
1095 (if package-get-remote | |
1410 | 1096 (error 'search-failed |
1097 (format "Unable to find file %s" base-filename)) | |
1098 (error 'syntax-error | |
1099 "No download sites or local package locations specified."))) | |
428 | 1100 ;; Validate the md5 checksum |
1101 ;; Doing it with XEmacs removes the need for an external md5 program | |
1102 (message "Validating checksum for `%s'..." package) (sit-for 0) | |
1103 (with-temp-buffer | |
442 | 1104 (insert-file-contents-literally full-package-filename) |
428 | 1105 (if (not (string= (md5 (current-buffer)) |
1106 (package-get-info-prop this-package | |
1107 'md5sum))) | |
1365 | 1108 (progn |
1109 (delete-file full-package-filename) | |
1410 | 1110 (error 'process-error |
1111 (format "Package %s does not match md5 checksum %s has been deleted" | |
1112 base-filename full-package-filename))))) | |
428 | 1113 |
1114 (package-admin-delete-binary-package package install-dir) | |
1115 | |
1116 (message "Installing package `%s' ..." package) (sit-for 0) | |
1117 (let ((status | |
1118 (package-admin-add-binary-package full-package-filename | |
1119 install-dir))) | |
1120 (if (= status 0) | |
1121 (progn | |
1122 ;; clear messages so that only messages from | |
1123 ;; package-get-init-package are seen, below. | |
1124 (clear-message) | |
1125 (if (package-get-init-package (package-admin-get-lispdir | |
1126 install-dir package)) | |
1127 (progn | |
628 | 1128 (run-hook-with-args 'package-install-hook package install-dir) |
428 | 1129 (message "Added package `%s'" package) |
1365 | 1130 (sit-for 0)) |
428 | 1131 (progn |
1132 ;; display message only if there isn't already one. | |
1133 (if (not (current-message)) | |
1134 (progn | |
1135 (message "Added package `%s' (errors occurred)" | |
1136 package) | |
1365 | 1137 (sit-for 0))) |
428 | 1138 (if package-status |
1365 | 1139 (setq package-status 'errors))))) |
428 | 1140 (message "Installation of package %s failed." base-filename) |
1141 (sit-for 0) | |
1142 (switch-to-buffer package-admin-temp-buffer) | |
1365 | 1143 (delete-file full-package-filename) |
1144 (setq package-status nil))) | |
428 | 1145 (setq found t)) |
1146 (if (and found package-get-remove-copy) | |
1147 (delete-file full-package-filename)) | |
1365 | 1148 package-status))) |
428 | 1149 |
1150 (defun package-get-info-find-package (which name) | |
1151 "Look in WHICH for the package called NAME and return all the info | |
1152 associated with it. See `package-get-base' for info on the format | |
1153 returned. | |
1154 | |
1155 To access fields returned from this, use | |
1156 `package-get-info-version' to return information about particular a | |
442 | 1157 version. Use `package-get-info-find-prop' to find particular property |
428 | 1158 from a version returned by `package-get-info-version'." |
1159 (interactive "xPackage list: \nsPackage Name: ") | |
1160 (if which | |
1161 (if (eq (caar which) name) | |
1162 (cdar which) | |
1163 (if (cdr which) | |
1164 (package-get-info-find-package (cdr which) name))))) | |
1165 | |
1166 (defun package-get-info-version (package version) | |
1167 "In PACKAGE, return the plist associated with a particular VERSION of the | |
1168 package. PACKAGE is typically as returned by | |
442 | 1169 `package-get-info-find-package'. If VERSION is nil, then return the |
428 | 1170 first (aka most recent) version. Use `package-get-info-find-prop' |
1171 to retrieve a particular property from the value returned by this." | |
1172 (interactive (package-get-interactive-package-query t t)) | |
1173 (while (and version package (not (string= (plist-get (car package) 'version) version))) | |
1174 (setq package (cdr package))) | |
1175 (if package (car package))) | |
1176 | |
1177 (defun package-get-info-prop (package-version property) | |
1178 "In PACKAGE-VERSION, return the value associated with PROPERTY. | |
1179 PACKAGE-VERSION is typically returned by `package-get-info-version' | |
1180 and PROPERTY is typically (although not limited to) one of the | |
1181 following: | |
1182 | |
1183 version - version of this package | |
1184 provides - list of symbols provided | |
1185 requires - list of symbols that are required. | |
1186 These in turn are provided by other packages. | |
1187 size - size of the bundled package | |
1188 md5sum - computed md5 checksum" | |
1189 (interactive "xPackage Version: \nSProperty") | |
1190 (plist-get package-version property)) | |
1191 | |
1192 (defun package-get-info-version-prop (package-list package version property) | |
1193 "In PACKAGE-LIST, search for PACKAGE with this VERSION and return | |
1194 PROPERTY value." | |
1195 (package-get-info-prop | |
1196 (package-get-info-version | |
1197 (package-get-info-find-package package-list package) version) property)) | |
1198 | |
1199 (defun package-get-staging-dir (filename) | |
1200 "Return a good place to stash FILENAME when it is retrieved. | |
1201 Use `package-get-dir' for directory to store stuff. | |
629 | 1202 Creates `package-get-dir' if it doesn't exist." |
428 | 1203 (interactive "FPackage filename: ") |
1204 (if (not (file-exists-p package-get-dir)) | |
1205 (make-directory package-get-dir)) | |
1206 (expand-file-name | |
776 | 1207 (file-name-nondirectory (or (and-fboundp 'efs-ftp-path |
1208 (nth 2 (efs-ftp-path filename))) | |
428 | 1209 filename)) |
1210 (file-name-as-directory package-get-dir))) | |
1211 | |
1212 (defun package-get-remote-filename (search filename) | |
1213 "Return FILENAME as a remote filename. | |
1214 It first checks if FILENAME already is a remote filename. If it is | |
1215 not, then it uses the (car search) as the remote site-name and the (cadr | |
1216 search) as the remote-directory and concatenates filename. In other | |
1217 words | |
1218 site-name:remote-directory/filename. | |
1219 | |
1220 If (car search) is nil, (cadr search is interpreted as a local directory). | |
1221 " | |
1222 (if (file-remote-p filename) | |
1223 filename | |
1224 (let ((dir (cadr search))) | |
1225 (concat (when (car search) | |
1226 (concat | |
1227 (if (string-match "@" (car search)) | |
1228 "/" | |
1229 "/anonymous@") | |
1230 (car search) ":")) | |
1231 (if (string-match "/$" dir) | |
1232 dir | |
1233 (concat dir "/")) | |
1234 filename)))) | |
1235 | |
1236 (defun package-get-installedp (package version) | |
1237 "Determine if PACKAGE with VERSION has already been installed. | |
442 | 1238 I'm not sure if I want to do this by searching directories or checking |
428 | 1239 some built in variables. For now, use packages-package-list." |
1240 ;; Use packages-package-list which contains name and version | |
1241 (equal (plist-get | |
1242 (package-get-info-find-package packages-package-list | |
1243 package) ':version) | |
1368 | 1244 (if (floatp version) |
1245 version | |
1365 | 1246 (string-to-number version)))) |
428 | 1247 |
1248 ;;;###autoload | |
1249 (defun package-get-package-provider (sym &optional force-current) | |
1250 "Search for a package that provides SYM and return the name and | |
1251 version. Searches in `package-get-base' for SYM. If SYM is a | |
442 | 1252 consp, then it must match a corresponding (provide (SYM VERSION)) from |
428 | 1253 the package. |
1254 | |
1255 If FORCE-CURRENT is non-nil make sure the database is up to date. This might | |
1256 lead to Emacs accessing remote sites." | |
1257 (interactive "SSymbol: ") | |
1258 (package-get-require-base force-current) | |
1259 (let ((packages package-get-base) | |
1260 (done nil) | |
1261 (found nil)) | |
1262 (while (and (not done) packages) | |
1263 (let* ((this-name (caar packages)) | |
1264 (this-package (cdr (car packages)))) ;strip off package name | |
1265 (while (and (not done) this-package) | |
1266 (if (or (eq this-name sym) | |
1267 (eq (cons this-name | |
1268 (package-get-info-prop (car this-package) 'version)) | |
1269 sym) | |
1270 (member sym | |
1271 (package-get-info-prop (car this-package) 'provides))) | |
1272 (progn (setq done t) | |
1273 (setq found | |
1274 (list (caar packages) | |
1275 (package-get-info-prop (car this-package) 'version)))) | |
1276 (setq this-package (cdr this-package))))) | |
1277 (setq packages (cdr packages))) | |
1278 (when (interactive-p) | |
1279 (if found | |
1280 (message "%S" found) | |
1281 (message "No appropriate package found"))) | |
1282 found)) | |
1283 | |
1284 (defun package-get-ever-installed-p (pkg &optional notused) | |
1285 (string-match "-package$" (symbol-name pkg)) | |
442 | 1286 (custom-initialize-set |
1287 pkg | |
1288 (if (package-get-info-find-package | |
1289 packages-package-list | |
428 | 1290 (intern (substring (symbol-name pkg) 0 (match-beginning 0)))) |
1291 t))) | |
1292 | |
1293 (provide 'package-get) | |
1294 ;;; package-get.el ends here |