Add load-prefer-newer option, to load .el if newer than .elc

* src/lread.c (Fload): Pass load_prefer_newer to openp.
Don't bother checking mtime if openp already did it.
(openp): Add `newer' argument, to check all suffixes
and find the newest file.
(syms_of_lread) <load_prefer_newer>: New option. 

* src/callproc.c (call_process):
* src/charset.c (load_charset_map_from_file):
* src/emacs.c (init_cmdargs):
* src/image.c (x_create_bitmap_from_file, x_find_image_file):
* src/lisp.h (openp):
* lread.c (Flocate_file_internal):
* src/process.c (Fformat_network_address):
* src/sound.c (Fplay_sound_internal):
* src/w32.c (check_windows_init_file):
* src/w32proc.c (sys_spawnve): Update for new arg spec of openp.

* lisp/Makefile.in (BYTE_COMPILE_FLAGS): Set load-prefer-newer to t.

* etc/NEWS: Mention this.

Fixes: debbugs:2061
This commit is contained in:
Glenn Morris 2013-12-17 19:21:48 -08:00
parent e82134b1e4
commit 1f41ee56ac
15 changed files with 138 additions and 58 deletions

View file

@ -807,6 +807,11 @@ for something (not just adding elements to it), it ought not to affect you.
* Lisp Changes in Emacs 24.4
** New option `load-prefer-newer', if non-nil, means that when both
.el and .elc versions of a file exist, rather than `load' always
choosing the .elc version, it will choose whichever is newer
(unless you explicitly specify one or the other).
** New function get-pos-property.
** New hook `pre-redisplay-function'.

View file

@ -1,3 +1,7 @@
2013-12-18 Glenn Morris <rgm@gnu.org>
* Makefile.in (BYTE_COMPILE_FLAGS): Set load-prefer-newer to t.
2013-12-18 Le Wang <l26wang@gmail.com>
* comint.el (comint-previous-matching-input-from-input): Retain
@ -9,6 +13,8 @@
2013-12-18 Glenn Morris <rgm@gnu.org>
* cus-start.el (load-prefer-newer): New option.
* mail/emacsbug.el (report-emacs-bug):
Only mention enable-multibyte-characters if non-standard.

View file

@ -88,7 +88,8 @@ AUTOGEN_VCS = \
BIG_STACK_DEPTH = 2200
BIG_STACK_OPTS = --eval "(setq max-lisp-eval-depth $(BIG_STACK_DEPTH))"
BYTE_COMPILE_FLAGS = $(BIG_STACK_OPTS) $(BYTE_COMPILE_EXTRA_FLAGS)
# Set load-prefer-newer for the benefit of the non-bootstrappers.
BYTE_COMPILE_FLAGS = $(BIG_STACK_OPTS) --eval '(setq load-prefer-newer t)' $(BYTE_COMPILE_EXTRA_FLAGS)
# Files to compile before others during a bootstrap. This is done to
# speed up the bootstrap process. They're ordered by size, so we use

View file

@ -312,6 +312,7 @@ Leaving \"Default\" unchecked is equivalent with specifying a default of
;; :format "%[Current dir?%] %v"
;; (const :tag " current dir" nil)
;; (directory :format "%v"))))
(load-prefer-newer lisp boolean "24.4")
;; minibuf.c
(enable-recursive-minibuffers minibuffer boolean)
(history-length minibuffer

View file

@ -1,5 +1,21 @@
2013-12-18 Glenn Morris <rgm@gnu.org>
* lread.c (Fload): Pass load_prefer_newer to openp.
Don't bother checking mtime if openp already did it.
(openp): Add `newer' argument, to check all suffixes
and find the newest file.
(syms_of_lread) <load_prefer_newer>: New option. (Bug#2061)
* callproc.c (call_process):
* charset.c (load_charset_map_from_file):
* emacs.c (init_cmdargs):
* image.c (x_create_bitmap_from_file, x_find_image_file):
* lisp.h (openp):
* lread.c (Flocate_file_internal):
* process.c (Fformat_network_address):
* sound.c (Fplay_sound_internal):
* w32.c (check_windows_init_file):
* w32proc.c (sys_spawnve): Update for new arg spec of openp.
* emacs.c (standard_args) [HAVE_NS]: Remove -disable-font-backend.
2013-12-17 Eli Zaretskii <eliz@gnu.org>

View file

@ -465,7 +465,7 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
int ok;
GCPRO3 (buffer, current_dir, error_file);
ok = openp (Vexec_path, args[0], Vexec_suffixes, &path, make_number (X_OK));
ok = openp (Vexec_path, args[0], Vexec_suffixes, &path, make_number (X_OK), 0);
UNGCPRO;
if (ok < 0)
report_file_error ("Searching for program", args[0]);

View file

@ -1,13 +1,15 @@
/* Basic character set support.
Copyright (C) 2001-2013 Free Software Foundation, Inc.
Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
2005, 2006, 2007, 2008, 2009, 2010, 2011
National Institute of Advanced Industrial Science and Technology (AIST)
Registration Number H14PRO021
Copyright (C) 2003, 2004
National Institute of Advanced Industrial Science and Technology (AIST)
Registration Number H13PRO009
Copyright (C) 2001-2013 Free Software Foundation, Inc.
Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
2005, 2006, 2007, 2008, 2009, 2010, 2011
National Institute of Advanced Industrial Science and Technology (AIST)
Registration Number H14PRO021
Copyright (C) 2003, 2004
National Institute of Advanced Industrial Science and Technology (AIST)
Registration Number H13PRO009
This file is part of GNU Emacs.
@ -493,7 +495,7 @@ load_charset_map_from_file (struct charset *charset, Lisp_Object mapfile,
count = SPECPDL_INDEX ();
record_unwind_protect_nothing ();
specbind (Qfile_name_handler_alist, Qnil);
fd = openp (Vcharset_map_path, mapfile, suffixes, NULL, Qnil);
fd = openp (Vcharset_map_path, mapfile, suffixes, NULL, Qnil, 0);
fp = fd < 0 ? 0 : fdopen (fd, "r");
if (!fp)
{

View file

@ -424,7 +424,7 @@ init_cmdargs (int argc, char **argv, int skip_args, char *original_pwd)
{
Lisp_Object found;
int yes = openp (Vexec_path, Vinvocation_name,
Vexec_suffixes, &found, make_number (X_OK));
Vexec_suffixes, &found, make_number (X_OK), 0);
if (yes == 1)
{
/* Add /: to the front of the name

View file

@ -327,7 +327,7 @@ x_create_bitmap_from_file (struct frame *f, Lisp_Object file)
}
/* Search bitmap-file-path for the file, if appropriate. */
if (openp (Vx_bitmap_file_path, file, Qnil, &found, make_number (R_OK)) < 0)
if (openp (Vx_bitmap_file_path, file, Qnil, &found, make_number (R_OK), 0) < 0)
return -1;
filename = SSDATA (found);
@ -2242,7 +2242,7 @@ x_find_image_file (Lisp_Object file)
Vx_bitmap_file_path);
/* Try to find FILE in data-directory/images, then x-bitmap-file-path. */
fd = openp (search_path, file, Qnil, &file_found, Qnil);
fd = openp (search_path, file, Qnil, &file_found, Qnil, 0);
if (fd == -1)
file_found = Qnil;

View file

@ -3791,7 +3791,7 @@ LOADHIST_ATTACH (Lisp_Object x)
Vcurrent_load_list = Fcons (x, Vcurrent_load_list);
}
extern int openp (Lisp_Object, Lisp_Object, Lisp_Object,
Lisp_Object *, Lisp_Object);
Lisp_Object *, Lisp_Object, int);
extern Lisp_Object string_to_number (char const *, int, bool);
extern void map_obarray (Lisp_Object, void (*) (Lisp_Object, Lisp_Object),
Lisp_Object);

View file

@ -1129,7 +1129,7 @@ Return t if the file exists and loads successfully. */)
}
}
fd = openp (Vload_path, file, suffixes, &found, Qnil);
fd = openp (Vload_path, file, suffixes, &found, Qnil, load_prefer_newer);
UNGCPRO;
}
@ -1252,29 +1252,36 @@ Return t if the file exists and loads successfully. */)
#ifdef DOS_NT
fmode = "rb";
#endif /* DOS_NT */
result = stat (SSDATA (efound), &s1);
if (result == 0)
{
SSET (efound, SBYTES (efound) - 1, 0);
result = stat (SSDATA (efound), &s2);
SSET (efound, SBYTES (efound) - 1, 'c');
}
if (result == 0
&& timespec_cmp (get_stat_mtime (&s1), get_stat_mtime (&s2)) < 0)
{
/* Make the progress messages mention that source is newer. */
newer = 1;
/* openp already checked for newness, no point doing it again.
FIXME would be nice to get a message when openp
ignores suffix order due to load_prefer_newer. */
if (!load_prefer_newer)
{
result = stat (SSDATA (efound), &s1);
if (result == 0)
{
SSET (efound, SBYTES (efound) - 1, 0);
result = stat (SSDATA (efound), &s2);
SSET (efound, SBYTES (efound) - 1, 'c');
}
/* If we won't print another message, mention this anyway. */
if (!NILP (nomessage) && !force_load_messages)
{
Lisp_Object msg_file;
msg_file = Fsubstring (found, make_number (0), make_number (-1));
message_with_string ("Source file `%s' newer than byte-compiled file",
msg_file, 1);
}
}
if (result == 0
&& timespec_cmp (get_stat_mtime (&s1), get_stat_mtime (&s2)) < 0)
{
/* Make the progress messages mention that source is newer. */
newer = 1;
/* If we won't print another message, mention this anyway. */
if (!NILP (nomessage) && !force_load_messages)
{
Lisp_Object msg_file;
msg_file = Fsubstring (found, make_number (0), make_number (-1));
message_with_string ("Source file `%s' newer than byte-compiled file",
msg_file, 1);
}
}
} /* !load_prefer_newer */
UNGCPRO;
}
}
@ -1413,7 +1420,7 @@ directories, make sure the PREDICATE function returns `dir-ok' for them. */)
(Lisp_Object filename, Lisp_Object path, Lisp_Object suffixes, Lisp_Object predicate)
{
Lisp_Object file;
int fd = openp (path, filename, suffixes, &file, predicate);
int fd = openp (path, filename, suffixes, &file, predicate, 0);
if (NILP (predicate) && fd >= 0)
emacs_close (fd);
return file;
@ -1440,11 +1447,14 @@ static Lisp_Object Qdir_ok;
nil is stored there on failure.
If the file we find is remote, return -2
but store the found remote file name in *STOREPTR. */
but store the found remote file name in *STOREPTR.
If NEWER is true, try all SUFFIXes and return the result for the
newest file that exists. Does not apply to remote files. */
int
openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes,
Lisp_Object *storeptr, Lisp_Object predicate)
Lisp_Object *storeptr, Lisp_Object predicate, int newer)
{
ptrdiff_t fn_size = 100;
char buf[100];
@ -1453,9 +1463,11 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes,
ptrdiff_t want_length;
Lisp_Object filename;
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6;
Lisp_Object string, tail, encoded_fn;
Lisp_Object string, tail, encoded_fn, save_string;
ptrdiff_t max_suffix_len = 0;
int last_errno = ENOENT;
struct timespec save_mtime;
int save_fd = 0;
CHECK_STRING (str);
@ -1556,17 +1568,18 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes,
if (exists)
{
/* We succeeded; return this descriptor and filename. */
if (storeptr)
*storeptr = string;
UNGCPRO;
return -2;
/* We succeeded; return this descriptor and filename. */
if (storeptr)
*storeptr = string;
UNGCPRO;
return -2;
}
}
else
{
int fd;
const char *pfn;
struct stat st;
encoded_fn = ENCODE_FILE (string);
pfn = SSDATA (encoded_fn);
@ -1597,7 +1610,6 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes,
}
else
{
struct stat st;
int err = (fstat (fd, &st) != 0 ? errno
: S_ISDIR (st.st_mode) ? EISDIR : 0);
if (err)
@ -1611,12 +1623,36 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes,
if (fd >= 0)
{
/* We succeeded; return this descriptor and filename. */
if (storeptr)
*storeptr = string;
UNGCPRO;
return fd;
if (newer)
{
struct timespec mtime = get_stat_mtime (&st);
if (!save_fd || timespec_cmp (save_mtime, mtime) < 0)
{
if (save_fd) emacs_close (save_fd);
save_fd = fd;
save_mtime = mtime;
save_string = string;
}
}
else
{
/* We succeeded; return this descriptor and filename. */
if (storeptr)
*storeptr = string;
UNGCPRO;
return fd;
}
}
/* No more suffixes. Return the newest. */
if (newer && save_fd && ! CONSP (XCDR (tail)))
{
if (storeptr)
*storeptr = save_string;
UNGCPRO;
return save_fd;
}
}
}
if (absolute)
@ -4632,6 +4668,17 @@ variables, this must be set in the first line of a file. */);
Vold_style_backquotes = Qnil;
DEFSYM (Qold_style_backquotes, "old-style-backquotes");
DEFVAR_BOOL ("load-prefer-newer", load_prefer_newer,
doc: /* Non-nil means `load' prefers the newest version of a file.
This applies when a filename suffix is not explicitly specified and
`load' is trying various possible suffixes (see `load-suffixes' and
`load-file-rep-suffixes'). Normally, it stops at the first file
that exists. If this option is non-nil, it checks all suffixes and
uses whichever file is newest.
Note that if you customize this, obviously it will not affect files
that are loaded before your customizations are read! */);
load_prefer_newer = 0;
/* Vsource_directory was initialized in init_lread. */
DEFSYM (Qcurrent_load_list, "current-load-list");

View file

@ -1530,7 +1530,7 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */)
tem = Qnil;
GCPRO4 (name, program, buffer, current_dir);
openp (Vexec_path, program, Vexec_suffixes, &tem, make_number (X_OK));
openp (Vexec_path, program, Vexec_suffixes, &tem, make_number (X_OK), 0);
UNGCPRO;
if (NILP (tem))
report_file_error ("Searching for program", program);

View file

@ -1332,7 +1332,7 @@ Internal use only, use `play-sound' instead. */)
{
/* Open the sound file. */
current_sound->fd = openp (list1 (Vdata_directory),
attrs[SOUND_FILE], Qnil, &file, Qnil);
attrs[SOUND_FILE], Qnil, &file, Qnil, 0);
if (current_sound->fd < 0)
sound_perror ("Could not open sound file");

View file

@ -1,5 +1,6 @@
/* Utility and Unix shadow routines for GNU Emacs on the Microsoft Windows API.
Copyright (C) 1994-1995, 2000-2013 Free Software Foundation, Inc.
Copyright (C) 1994-1995, 2000-2013 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@ -8602,7 +8603,7 @@ check_windows_init_file (void)
need to ENCODE_FILE here, but we do need to convert the file
names from UTF-8 to ANSI. */
init_file = build_string ("term/w32-win");
fd = openp (Vload_path, init_file, Fget_load_suffixes (), NULL, Qnil);
fd = openp (Vload_path, init_file, Fget_load_suffixes (), NULL, Qnil, 0);
if (fd < 0)
{
Lisp_Object load_path_print = Fprin1_to_string (Vload_path, Qnil);

View file

@ -1,5 +1,6 @@
/* Process support for GNU Emacs on the Microsoft Windows API.
Copyright (C) 1992, 1995, 1999-2013 Free Software Foundation, Inc.
Copyright (C) 1992, 1995, 1999-2013 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@ -1592,7 +1593,7 @@ sys_spawnve (int mode, char *cmdname, char **argv, char **envp)
program = build_string (cmdname);
full = Qnil;
GCPRO1 (program);
openp (Vexec_path, program, Vexec_suffixes, &full, make_number (X_OK));
openp (Vexec_path, program, Vexec_suffixes, &full, make_number (X_OK), 0);
UNGCPRO;
if (NILP (full))
{