[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Proposal: emacsen and add-on package handling (1.1)



I think this version's pretty close to final, especially for an
initial implementation.  The infrastructure's all finished and tested
(to the extent that I can without other add-on packages), and the
emacs20 and emacsen-common packages are ready to go.

I'm posting this again to both debian-devel and debian-policy because
I'm fairly certain that I won't catch all the relevant people if I
just post it to debian-policy where it belongs.  Please redirect *all*
replies to debian-policy.  I've set the "Repy-to" to reflect this.


I've changed several things.  This is not a complete change list, but
it covers most of the changes:

1) /usr/share is the preferred prefix for a number of things that were
   in /usr/lib.

2) Also, there's now only packages/instal/foo and packages/remove/foo rather
   than the various <flavors> I had before.  Add-on maintainers just
   write one script.  The arguments to the script tell which flavor's
   currently being affected.

3) Suggest that maintainers use autoload in site-start.d

4) Clarify that a package should depend on "emacsen" unless it's
   specific to a particular flavor or flavors in which case it should
   depend on those flavors.

5) Sample code and clearer examples for add-on package maintainers.

5) Numerous typo/thinko's corrected, some severe.  I'm sure there are
   others.



First, some terminology: when I say <emacs> below I mean
{emacs,xemacs20,emacs19,emacs20}.  When I say <flavor>, I mean just
one of (xemacs20 emacs19 emacs20).

1) New common package.

   There will be a new package, emacsen-common, which all of the
   various flavors of emacs will depend on, and which will contain
   emacs flavor independent files like debian-rundir and all the
   infrastructure implementing our mechanism for dealing with all the
   various emacsen.

2) Flavor indication

   Each emacs binary will set the variable debian-flavor to be the
   same as the name of the debian-package.  For example, the emacs20
   package would do this in startup.el: (setq debian-flavor 'emacs20).

3) Emacs startup strategy

  We'll have the following startup files/directories:

  emacsen-common: /etc/emacs/site-start.{el,d}
  xemacs20:       /etc/xemacs20/site-start.d
  emacs19:        /etc/emacs19/site-start.d
  emacs20:        /etc/emacs20/site-start.d

  /etc/emacs/site-start.el will now be a conffile, and will be owned
  by a new package emacsen-common.  It will no longer have anything in
  it at all by default, and the local admin can use it for whatever.

  The load-path for a given emacs flavor will include /etc/<flavor>
  and /etc/emacs in that order, and on startup each emacsen will call
  (debian-startup) and then load "site-start".  This means that
  /etc/emacs/site-start.el will be loaded if it exists, unless there's
  an /etc/<flavor>/site-start.el{,c} or /etc/emacs/site-start.elc
  which will take precedence.

  debian-startup will, for now, just turn into a call to
  debian-run-directories whose behavior is slightly different from the
  current debian-run-directory.

  debian-run-directories will take the union of all the file base
  names (i.e. without any .el or .elc extension, and without the
  directory component: i.e. /etc/xemacs/site-start.d/50foo.elc =>
  foo).  Then then emacs load-path will be temporarily augmented to
  include /etc/<flavor>/site-start.d and /etc/emacs/site-start.d in
  that order.  Once the list of file base names has been determined,
  emacs will call (load base-name) on each of them in alphabetical
  order.  This means that .elc files will take precedence over .el
  files in a given directory, and files in the <flavor> site-start.d
  directory will take precedence over those in the emacs common
  directory.

4) Code locations

  In addition to the /etc/<emacs>/site-start* directories, we'll have
  the following directories (their use will be described shortly).

  emacsen-common: /usr/share/emacs/site-lisp/
  xemacs20:       /usr/share/xemacs20/site-lisp/
  emacs19:        /usr/share/emacs19/site-lisp/
  emacs20:        /usr/share/emacs20/site-lisp/

  These will be treated as part of the normal emacsen load path with
  the <flavor> dir taking precedence over the emacs (common) dir.

  /usr/share/<flavor>/site-lisp will be a symlink to the normal
  site-lisp directory for that flavor of emacs.  For example:

    /usr/share/emacs20/site-lisp -> ../../emacs/20.2/site-lisp

5) add-on package support (there are examples later which make this
   much clearer)

  A) Each package may place a file named the same as the package into

       /usr/lib/emacsen-common/packages/install/
       /usr/lib/emacsen-common/packages/remove/

     and the package must call
  
       /usr/lib/emacsen-common/emacs-package-install foo

     in the postinst and 

       /usr/lib/emacsen-common/emacs-package-remove foo

     in the prerm.

     For now, "emacs-package-install foo" will conceptually just turn
     into a call for the common package emacs, and for each installed
     flavor to

       /usr/lib/emacsen-common/packages/install/foo

     The arguments to these scripts will be the flavor being installed
     (or just the common name "emacs") followed by a list of other
     flavors already installed, potentially including the current one.

     So if emacs20 and xemacs20 were installed, installing foo would
     result in calls to:

       /usr/lib/emacsen-common/packages/install/foo emacs emacs20 xemacs20
       /usr/lib/emacsen-common/packages/install/foo emacs20 emacs20 xemacs20
       /usr/lib/emacsen-common/packages/install/foo xemacs20 emacs20 xemacs20

     emacs-package remove would do the symmetric thing.

  B) Each emacsen main package will have a call to 
     "/usr/lib/emacsen-common/emacs-install <flavor> in its postinst
     and a call to "/usr/lib/emacsen-common/emacs-remove <flavor> in
     it's prerm.

     The emacs-install script (for now) will be conceptually similar to

       /usr/lib/emacsen-common/emacs-package-install <pkg>

     for each installed <pkg>, but might do more later.  Similarly,
     emacs-remove would just be the same as

       /usr/lib/emacsen-common/emacs-package-install <pkg>

     for now.  Don't forget that the argument list to the add-on
     package install scripts will indicate both the flavor being
     installed, and the flavors already installed.  In this case,
     since we're actually installing a flavor, the first argument
     won't appear in the subsequent arguments.

     emacs-remove will just do the reverse of emacs-install.

  C) Each add-on package has the right to place files into the
     following directories:

       /etc/<emacs>/site-start.d
       /usr/share/<emacs>/site-lisp/<package-name>

6) Mandatory binary symlink

   Each emacsen main package will have a symlink
   /usr/bin/<package-name> to /usr/bin/<emacs-binary> so that when
   add-on package install/remove scripts are called, they can just use
   /usr/bin/$ARGV[0] to get the right binary for byte-compilation.

7) Virtual package

   Each emacsen main package will "Provides: emacsen".  It would be
   nice to use "emacs", but for historical reasons, and given the
   nature of the packaging system, we can't.

   Packages that just need to make sure some flavor of emacs is
   installed should just "Depends: emacsen".  If they depend on
   specific flavors of emacs, then they should list those dependencies
   explicitly instead.

8) Emacs lisp load path.

   At a minimum, each emacs will have the following in the given order
   in their load path:

     /etc/<flavor>
     /etc/emacs
     /usr/local/share/emacs/<upstream>/site-lisp
     /usr/local/share/emacs/site-lisp
     /usr/share/emacs/<upstream>/site-lisp
     /usr/share/emacs/site-lisp

   where <upstream> is the normal emacs upstream version number for
   the relevant flavor like 20.2 or 19.34.  The symlink mentioned in
   (4) will also effectively add

     /usr/local/share/emacs/<flavor>/site-lisp

   in the same position as

     /usr/local/share/emacs/<upstream>/site-lisp

9) Usage of autoload instead of load in the site-start.d files.

   It's been suggested, and is probably a good idea that maintainers
   switch to using autoload rather than load when possible in their
   site-start.d files.

   For example, instead of (load "some-package), you should use
   autoloads for all the top level, user visible functions.  Currently
   the calc package has a good example of this.

That's it.  I think this gives the add-on package maintainers the
flexibility they need to be able to DTRT, and I think the common case
won't be all that difficult.

Examples:

1) Xemacs20 and the add-on packages tm and auctex are already installed,
   and now someone installs emacs20.

   In it's postinst, emacs20 would make this call:

     /usr/lib/emacsen-common/emacs-install emacs20

   which would result in calls to

     /usr/lib/emacsen-common/packages/install/auctex emacs xemacs20
     /usr/lib/emacsen-common/packages/install/auctex emacs20 xemacs20
     /usr/lib/emacsen-common/packages/emacs20/install/tm emacs xemacs20
     /usr/lib/emacsen-common/packages/emacs/install/tm emacs20 xemacs20
    
2) Now, given (1), assume that someone removes xemacs20.

   In it's postinst, xemacs20 would make this call:

     /usr/lib/emacsen-common/emacs-remove xemacs20

   which would result in calls to

     /usr/lib/emacsen-common/packages/remove/auctex emacs emacs20 xemacs20
     /usr/lib/emacsen-common/packages/remove/auctex xemacs20 emacs20 xemacs20
     /usr/lib/emacsen-common/packages/remove/tm emacs emacs20 xemacs20
     /usr/lib/emacsen-common/packages/remove/tm xemacs20 emacs20 xemacs20

3) Now assume emacs20 and xemacs20 are installed, and that someone removes
   tm.

   The call to emacsen-package-remove in tm's prerm will result in
   the following calls:

     /usr/lib/emacsen-common/packages/remove/tm emacs emacs20 xemacs20
     /usr/lib/emacsen-common/packages/remove/tm emacs20 emacs20 xemacs20
     /usr/lib/emacsen-common/packages/remove/tm xemacs20 emacs20 xemacs20

   In the remove/tm file, tm is responsible for cleaning up any files
   it put into it's allowed locations:

     /etc/<emacs>/site-start.d/
     /usr/share/<emacs>/site-lisp/tm

4) Finally, here are sample install and remove scripts for a
   hypothetical package "foo" that only needs to byte compile a list
   of files for each flavor:

     #!/bin/sh
     # /usr/lib/emacsen-common/packages/install/foo
     # [ This particular script hasn't been tested, so be careful. ]
     set -e

     FLAVOR=$1
     echo install/foo: Handling install of emacsen flavor ${FLAVOR}

     byte_compile_options="-batch -f batch-byte-compile"
     el_files="some-file.el some-other-file.el etc.el" 
     el_dir=/usr/share/emacs/site-lisp/foo/
     elc_dir=/usr/share/${FLAVOR}/site-lisp/foo/
     el_path_list=`echo ${el_files} | perl -pe 's|^|${el_dir}|o'`
     elc_path_list=`echo ${el_files} | perl -pe 's|^|${elc_dir}|o'`

     if [ ${FLAVOR} != emacs ]
     then
       echo install/foo: byte-compiling for ${FLAVOR}

       # Copy the temp .el files
       cp ${el_path_list} ${elc_dir}

       # Byte compile them
       ${FLAVOR} ${byte_compile_options} ${el_path_list}

       # remove the redundant .el files
       # presumes that any .el files in the <flavor> dir are trash.
       rm ${elc_dir}/*.el
     fi
     exit 0;

     #!/bin/sh
     # /usr/lib/emacsen-common/packages/remove/foo
     # [ This particular script hasn't been tested either, so be careful. ]
     set -e

     FLAVOR=$1
     echo remove/foo: Handling removal of emacsen flavor ${FLAVOR}

     if [ ${FLAVOR} != emacs ]
     then
       echo emacsen-common: purging byte-compiled files for ${FLAVOR}
       rm -f /usr/share/${FLAVOR}/site-lisp/foo/*.elc
     fi
     exit 0;

That's it, thanks again for your patience.

-- 
Rob Browning <rlb@cs.utexas.edu>
PGP fingerprint = E8 0E 0D 04 F5 21 A0 94  53 2B 97 F5 D6 4E 39 30


Reply to: