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