emacs-devel
[Top][All Lists]
Advanced

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

Re: Problem mit symlinks, locate-library and load-history [PATCH]


From: Alan Mackenzie
Subject: Re: Problem mit symlinks, locate-library and load-history [PATCH]
Date: Wed, 10 May 2006 11:18:27 +0000 (GMT)

Hi, Richard!

On Mon, 27 Mar 2006, Richard Stallman wrote:

>Your new function seems like a good idea.  For full reliability, the
>regexps should use \\` and \\' rather than ^ and $.  And I think it
>would be good for load-history-filename-element to use
>save-match-data.
>

I updated my Emacs copy yesterday.  It is in ~acm/emacs/emacs, where
~acm/emacs is a symbolic link to /mnt/hda7.

I do: emacs-22.0.50.1 -Q
      M-x load-file <ret> ~acm/emacs/emacs/lisp/progmodes/cc-mode.elc
      C-h v load-history.

Then:
      M-: (eval-after-load "cc-mode" '(beep))  fails.
      M-: (eval-after-load "cc-fonts" '(beep))  beeps.
      M-: (eval-after-load "english" '(beep))  fails.

Here are these file names as they appear in load-history:

1. "/home/acm/emacs/emacs/lisp/progmodes/cc-mode.elc"
2. "/mnt/hda7/emacs/lisp/progmodes/cc-fonts.elc"
3. "/mnt/hda7/emacs/lisp/language/english.elc"

1 and 2 are incompatible.  3 is plain wrong - the actual file is
english.el (english.elc doesn't exist; you can't compile english).

The reason this happens is that in Fload (lread.c):
(i) "language/english" is passed to openp, which returns the full file
  name, including the extension ".el".

(ii) At preload time (`purify-flag'), the extension (".el" or ".elc")
  is stripped from the filename before it's either:
  o - (".elc") loaded; or
  o - (".el") passed to load-with-code-conversion
    (.../international/mule.el).

(iii) At this stage I get too confused to delve further.  The
  (preloaded) file names (relative file names based on ..../emacs/lisp)
  get stored into load-history.  Some of these names have the extension
  ".el", some have no extension, but I don't think any have ".elc".

(iv) When Emacs is started, command-line (startup.el) attempts to restore
  the extensions.  ".el" is left as is, otherwise ".elc" is appended.

This is chaotic - here is a fix:

#########################################################################

The patch here rationalizes load-history.  It (probably) isn't enough on
its own to fix the eval-after-load bugs.  For this I will also need the
function load-history-filename-element and so on, which I proposed on Wed
22 March, and you (RMS) tentatively approved on Mon, 27 Mar 2006 03:36:26
-0500.

With this patch, the names in load-history now look like this:   

1. "/mnt/hda7/emacs/lisp/progmodes/cc-mode.elc"
2. "/mnt/hda7/emacs/lisp/progmodes/cc-fonts.elc"
3. "/mnt/hda7/emacs/lisp/language/english.el"


2006-05-10  Alan Mackenzie  <address@hidden>

        * lread.c (Vload_history): Enhance doc-string to say that the file
        name is the absolute truename of the loaded file.

        * lread.c (readevalloop): Call file-truename on the name for
        load-history, except at preloading time.

        * lread.c (Fload): At preloading time, preserve the extension of
        the filename which goes into load-history.  New variable
        hist_file_name.


Index: src/lread.c
===================================================================
RCS file: /cvsroot/emacs/emacs/src/lread.c,v
retrieving revision 1.350
diff -c -r1.350 lread.c
*** src/lread.c 27 Feb 2006 02:04:35 -0000      1.350
--- src/lread.c 10 May 2006 10:50:59 -0000
***************
*** 718,725 ****
    register int fd = -1;
    int count = SPECPDL_INDEX ();
    Lisp_Object temp;
!   struct gcpro gcpro1, gcpro2;
!   Lisp_Object found, efound;
    /* 1 means we printed the ".el is newer" message.  */
    int newer = 0;
    /* 1 means we are loading a compiled file.  */
--- 718,725 ----
    register int fd = -1;
    int count = SPECPDL_INDEX ();
    Lisp_Object temp;
!   struct gcpro gcpro1, gcpro2, gcpro3;
!   Lisp_Object found, efound, hist_file_name;
    /* 1 means we printed the ".el is newer" message.  */
    int newer = 0;
    /* 1 means we are loading a compiled file.  */
***************
*** 727,732 ****
--- 727,733 ----
    Lisp_Object handler;
    int safe_p = 1;
    char *fmode = "r";
+   Lisp_Object tmp[2];
  #ifdef DOS_NT
    fmode = "rt";
  #endif /* DOS_NT */
***************
*** 743,749 ****
       the need to gcpro noerror, nomessage and nosuffix.
       (Below here, we care only whether they are nil or not.)
       The presence of this call is the result of a historical accident:
!      it used to be in every file-operations and when it got removed
       everywhere, it accidentally stayed here.  Since then, enough people
       supposedly have things like (load "$PROJECT/foo.el") in their .emacs
       that it seemed risky to remove.  */
--- 744,750 ----
       the need to gcpro noerror, nomessage and nosuffix.
       (Below here, we care only whether they are nil or not.)
       The presence of this call is the result of a historical accident:
!      it used to be in every file-operation and when it got removed
       everywhere, it accidentally stayed here.  Since then, enough people
       supposedly have things like (load "$PROJECT/foo.el") in their .emacs
       that it seemed risky to remove.  */
***************
*** 763,769 ****
    if (SCHARS (file) > 0)
      {
        int size = SBYTES (file);
-       Lisp_Object tmp[2];
  
        found = Qnil;
        GCPRO2 (file, found);
--- 764,769 ----
***************
*** 847,852 ****
--- 847,859 ----
      Vloads_in_progress = Fcons (found, Vloads_in_progress);
    }
  
+   /* Get the name for load-history. */
+   hist_file_name = (! NILP (Vpurify_flag)
+                     ? Fconcat (2, (tmp[0] = Ffile_name_directory (file),
+                                    tmp[1] = Ffile_name_nondirectory (found),
+                                    tmp))
+                     : found) ;
+ 
    if (!bcmp (SDATA (found) + SBYTES (found) - 4,
             ".elc", 4))
      /* Load .elc files directly, but not when they are
***************
*** 857,863 ****
          struct stat s1, s2;
          int result;
  
!         GCPRO2 (file, found);
  
          if (!safe_to_load_p (fd))
            {
--- 864,870 ----
          struct stat s1, s2;
          int result;
  
!         GCPRO3 (file, found, hist_file_name);
  
          if (!safe_to_load_p (fd))
            {
***************
*** 911,924 ****
  
          if (fd >= 0)
            emacs_close (fd);
!         val = call4 (Vload_source_file_function, found, file,
                       NILP (noerror) ? Qnil : Qt,
                       NILP (nomessage) ? Qnil : Qt);
          return unbind_to (count, val);
        }
      }
  
!   GCPRO2 (file, found);
  
  #ifdef WINDOWSNT
    emacs_close (fd);
--- 918,931 ----
  
          if (fd >= 0)
            emacs_close (fd);
!         val = call4 (Vload_source_file_function, found, hist_file_name,
                       NILP (noerror) ? Qnil : Qt,
                       NILP (nomessage) ? Qnil : Qt);
          return unbind_to (count, val);
        }
      }
  
!   GCPRO3 (file, found, hist_file_name);
  
  #ifdef WINDOWSNT
    emacs_close (fd);
***************
*** 957,963 ****
    load_descriptor_list
      = Fcons (make_number (fileno (stream)), load_descriptor_list);
    load_in_progress++;
!   readevalloop (Qget_file_char, stream, (! NILP (Vpurify_flag) ? file : 
found),
                Feval, 0, Qnil, Qnil, Qnil, Qnil);
    unbind_to (count, Qnil);
  
--- 964,970 ----
    load_descriptor_list
      = Fcons (make_number (fileno (stream)), load_descriptor_list);
    load_in_progress++;
!   readevalloop (Qget_file_char, stream, hist_file_name,
                Feval, 0, Qnil, Qnil, Qnil, Qnil);
    unbind_to (count, Qnil);
  
***************
*** 1385,1390 ****
--- 1392,1405 ----
  
    GCPRO4 (sourcename, readfun, start, end);
  
+   /* Try to ensure sourcename is a truename, except whilst preloading. */
+   if (NILP (Vpurify_flag) && !NILP (sourcename)
+       && Ffile_name_absolute_p (sourcename))
+     {
+       Lisp_Object Qfile_truename = intern ("file-truename") ;
+       if (!NILP (Ffboundp (Qfile_truename)))
+         sourcename = call1 (Qfile_truename, sourcename) ;
+     }
    LOADHIST_ATTACH (sourcename);
  
    continue_reading_p = 1;
***************
*** 3982,3987 ****
--- 3997,4006 ----
  Each alist element is a list that starts with a file name,
  except for one element (optional) that starts with nil and describes
  definitions evaluated from buffers not visiting files.
+ 
+ The file name is absolute and is the true file name (i.e. it doesn't
+ contain symbolic links) of the loaded file.
+ 
  The remaining elements of each list are symbols defined as variables
  and cons cells of the form `(provide . FEATURE)', `(require . FEATURE)',
  `(defun . FUNCTION)', `(autoload . SYMBOL)', and `(t . SYMBOL)'.



2006-05-10  Alan Mackenzie  <address@hidden>

        * startup.el (command-line): For names of preloaded files, don't
        append ".elc" (now done in Fload), and call file-truename on the
        lisp directory.


Index: lisp/startup.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/startup.el,v
retrieving revision 1.407
diff -c -r1.407 startup.el
*** lisp/startup.el     5 May 2006 14:05:54 -0000       1.407
--- lisp/startup.el     10 May 2006 10:51:05 -0000
***************
*** 644,661 ****
  
    ;; Convert preloaded file names to absolute.
    (let ((lisp-dir
!        (file-name-directory
!         (locate-file "simple" load-path
!                      (get-load-suffixes)))))
  
      (setq load-history
          (mapcar (lambda (elt)
                    (if (and (stringp (car elt))
                             (not (file-name-absolute-p (car elt))))
                        (cons (concat lisp-dir
!                                     (car elt)
!                                     (if (string-match "[.]el$" (car elt))
!                                         "" ".elc"))
                              (cdr elt))
                      elt))
                  load-history)))
--- 644,660 ----
  
    ;; Convert preloaded file names to absolute.
    (let ((lisp-dir
!        (file-truename
!         (file-name-directory
!          (locate-file "simple" load-path
!                       (get-load-suffixes))))))
  
      (setq load-history
          (mapcar (lambda (elt)
                    (if (and (stringp (car elt))
                             (not (file-name-absolute-p (car elt))))
                        (cons (concat lisp-dir
!                                     (car elt))
                              (cdr elt))
                      elt))
                  load-history)))

#########################################################################

-- 
Alan.






reply via email to

[Prev in Thread] Current Thread [Next in Thread]