summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--runtime/doc/eval.txt1
-rwxr-xr-xsrc/auto/configure46
-rw-r--r--src/bufwrite.c3
-rw-r--r--src/config.h.in3
-rw-r--r--src/configure.ac25
-rw-r--r--src/evalfunc.c7
-rw-r--r--src/fileio.c24
-rw-r--r--src/memline.c6
-rw-r--r--src/netbeans.c3
-rw-r--r--src/proto/fileio.pro2
-rw-r--r--src/structs.h2
-rw-r--r--src/testdir/test_stat.vim33
-rw-r--r--src/version.c2
13 files changed, 151 insertions, 6 deletions
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index b966fd9bbf..5a7e6ec31b 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -12236,6 +12236,7 @@ multi_byte_encoding 'encoding' is set to a multibyte encoding.
multi_byte_ime Compiled with support for IME input method.
multi_lang Compiled with support for multiple languages.
mzscheme Compiled with MzScheme interface |mzscheme|.
+nanotime Compiled with sub-second time stamp checks.
netbeans_enabled Compiled with support for |netbeans| and connected.
netbeans_intg Compiled with support for |netbeans|.
num64 Compiled with 64-bit |Number| support.
diff --git a/src/auto/configure b/src/auto/configure
index cab7bc9fca..cd5e59366e 100755
--- a/src/auto/configure
+++ b/src/auto/configure
@@ -13149,6 +13149,52 @@ if test "x$vim_cv_stat_ignores_slash" = "xyes" ; then
fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for nanoseconds field of struct stat" >&5
+$as_echo_n "checking for nanoseconds field of struct stat... " >&6; }
+if ${ac_cv_struct_st_mtim_nsec+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_save_CPPFLAGS="$CPPFLAGS"
+ ac_cv_struct_st_mtim_nsec=no
+ # st_mtim.tv_nsec -- the usual case
+ # st_mtim._tv_nsec -- Solaris 2.6, if
+ # (defined _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED == 1
+ # && !defined __EXTENSIONS__)
+ # st_mtim.st__tim.tv_nsec -- UnixWare 2.1.2
+ # st_mtime_n -- AIX 5.2 and above
+ # st_mtimespec.tv_nsec -- Darwin (Mac OSX)
+ for ac_val in st_mtim.tv_nsec st_mtim._tv_nsec st_mtim.st__tim.tv_nsec st_mtime_n st_mtimespec.tv_nsec; do
+ CPPFLAGS="$ac_save_CPPFLAGS -DST_MTIM_NSEC=$ac_val"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <sys/stat.h>
+int
+main ()
+{
+struct stat s; s.ST_MTIM_NSEC;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_struct_st_mtim_nsec=$ac_val; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ done
+ CPPFLAGS="$ac_save_CPPFLAGS"
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_struct_st_mtim_nsec" >&5
+$as_echo "$ac_cv_struct_st_mtim_nsec" >&6; }
+if test $ac_cv_struct_st_mtim_nsec != no; then
+
+cat >>confdefs.h <<_ACEOF
+#define ST_MTIM_NSEC $ac_cv_struct_st_mtim_nsec
+_ACEOF
+
+fi
+
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for iconv_open()" >&5
$as_echo_n "checking for iconv_open()... " >&6; }
save_LIBS="$LIBS"
diff --git a/src/bufwrite.c b/src/bufwrite.c
index a38fb1c0e8..772d707673 100644
--- a/src/bufwrite.c
+++ b/src/bufwrite.c
@@ -527,7 +527,7 @@ buf_write_bytes(struct bw_info *ip)
check_mtime(buf_T *buf, stat_T *st)
{
if (buf->b_mtime_read != 0
- && time_differs((long)st->st_mtime, buf->b_mtime_read))
+ && time_differs(st, buf->b_mtime_read, buf->b_mtime_read_ns))
{
msg_scroll = TRUE; // don't overwrite messages here
msg_silent = 0; // must give this prompt
@@ -2558,6 +2558,7 @@ nofail:
{
buf_store_time(buf, &st_old, fname);
buf->b_mtime_read = buf->b_mtime;
+ buf->b_mtime_read_ns = buf->b_mtime_ns;
}
}
}
diff --git a/src/config.h.in b/src/config.h.in
index 0808cc3587..61b8b76a54 100644
--- a/src/config.h.in
+++ b/src/config.h.in
@@ -144,6 +144,9 @@
/* Define if stat() ignores a trailing slash */
#undef STAT_IGNORES_SLASH
+/* Define to nanoseconds field of struct stat */
+#undef ST_MTIM_NSEC
+
/* Define if tgetstr() has a second argument that is (char *) */
#undef TGETSTR_CHAR_P
diff --git a/src/configure.ac b/src/configure.ac
index bb77485f31..3316f48242 100644
--- a/src/configure.ac
+++ b/src/configure.ac
@@ -3843,6 +3843,31 @@ main() {struct stat st; exit(stat("configure/", &st) != 0); }
if test "x$vim_cv_stat_ignores_slash" = "xyes" ; then
AC_DEFINE(STAT_IGNORES_SLASH)
fi
+
+dnl nanoseconds field of struct stat
+AC_CACHE_CHECK([for nanoseconds field of struct stat],
+ ac_cv_struct_st_mtim_nsec,
+ [ac_save_CPPFLAGS="$CPPFLAGS"
+ ac_cv_struct_st_mtim_nsec=no
+ # st_mtim.tv_nsec -- the usual case
+ # st_mtim._tv_nsec -- Solaris 2.6, if
+ # (defined _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED == 1
+ # && !defined __EXTENSIONS__)
+ # st_mtim.st__tim.tv_nsec -- UnixWare 2.1.2
+ # st_mtime_n -- AIX 5.2 and above
+ # st_mtimespec.tv_nsec -- Darwin (Mac OSX)
+ for ac_val in st_mtim.tv_nsec st_mtim._tv_nsec st_mtim.st__tim.tv_nsec st_mtime_n st_mtimespec.tv_nsec; do
+ CPPFLAGS="$ac_save_CPPFLAGS -DST_MTIM_NSEC=$ac_val"
+ AC_TRY_COMPILE([#include <sys/types.h>
+#include <sys/stat.h>], [struct stat s; s.ST_MTIM_NSEC;],
+ [ac_cv_struct_st_mtim_nsec=$ac_val; break])
+ done
+ CPPFLAGS="$ac_save_CPPFLAGS"
+])
+if test $ac_cv_struct_st_mtim_nsec != no; then
+ AC_DEFINE_UNQUOTED([ST_MTIM_NSEC], [$ac_cv_struct_st_mtim_nsec],
+ [Define if struct stat contains a nanoseconds field])
+fi
dnl Link with iconv for charset translation, if not found without library.
dnl check for iconv() requires including iconv.h
diff --git a/src/evalfunc.c b/src/evalfunc.c
index 8a06f757df..4abbdb90f6 100644
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -5479,6 +5479,13 @@ f_has(typval_T *argvars, typval_T *rettv)
0
#endif
},
+ {"nanotime",
+#ifdef ST_MTIM_NSEC
+ 1
+#else
+ 0
+#endif
+ },
{"num64", 1},
{"ole",
#ifdef FEAT_OLE
diff --git a/src/fileio.c b/src/fileio.c
index 1767e5e091..63d083e159 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -408,6 +408,7 @@ readfile(
{
buf_store_time(curbuf, &st, fname);
curbuf->b_mtime_read = curbuf->b_mtime;
+ curbuf->b_mtime_read_ns = curbuf->b_mtime_ns;
filesize_disk = st.st_size;
#ifdef UNIX
/*
@@ -432,7 +433,9 @@ readfile(
else
{
curbuf->b_mtime = 0;
+ curbuf->b_mtime_ns = 0;
curbuf->b_mtime_read = 0;
+ curbuf->b_mtime_read_ns = 0;
curbuf->b_orig_size = 0;
curbuf->b_orig_mode = 0;
}
@@ -2569,6 +2572,7 @@ failed:
{
buf_store_time(curbuf, &st, fname);
curbuf->b_mtime_read = curbuf->b_mtime;
+ curbuf->b_mtime_read_ns = curbuf->b_mtime_ns;
}
#endif
}
@@ -3115,15 +3119,19 @@ msg_add_eol(void)
}
int
-time_differs(long t1, long t2)
+time_differs(stat_T *st, long mtime, long mtime_ns UNUSED)
{
#if defined(__linux__) || defined(MSWIN)
// On a FAT filesystem, esp. under Linux, there are only 5 bits to store
// the seconds. Since the roundoff is done when flushing the inode, the
// time may change unexpectedly by one second!!!
- return (t1 - t2 > 1 || t2 - t1 > 1);
+ return (long)st->st_mtime - mtime > 1 || mtime - (long)st->st_mtime > 1
+# ifdef ST_MTIM_NSEC
+ || (long)st->ST_MTIM_NSEC != mtime_ns
+# endif
+ ;
#else
- return (t1 != t2);
+ return (long)st->st_mtime != mtime;
#endif
}
@@ -4072,7 +4080,7 @@ buf_check_timestamp(
if ( !(buf->b_flags & BF_NOTEDITED)
&& buf->b_mtime != 0
&& ((stat_res = mch_stat((char *)buf->b_ffname, &st)) < 0
- || time_differs((long)st.st_mtime, buf->b_mtime)
+ || time_differs(&st, buf->b_mtime, buf->b_mtime_ns)
|| st.st_size != buf->b_orig_size
#ifdef HAVE_ST_MODE
|| (int)st.st_mode != buf->b_orig_mode
@@ -4187,9 +4195,12 @@ buf_check_timestamp(
mesg2 = _("See \":help W16\" for more info.");
}
else
+ {
// Only timestamp changed, store it to avoid a warning
// in check_mtime() later.
buf->b_mtime_read = buf->b_mtime;
+ buf->b_mtime_read_ns = buf->b_mtime_ns;
+ }
}
}
}
@@ -4468,6 +4479,11 @@ buf_reload(buf_T *buf, int orig_mode)
buf_store_time(buf_T *buf, stat_T *st, char_u *fname UNUSED)
{
buf->b_mtime = (long)st->st_mtime;
+#ifdef ST_MTIM_NSEC
+ buf->b_mtime_ns = (long)st->ST_MTIM_NSEC;
+#else
+ buf->b_mtime_ns = 0;
+#endif
buf->b_orig_size = st->st_size;
#ifdef HAVE_ST_MODE
buf->b_orig_mode = (int)st->st_mode;
diff --git a/src/memline.c b/src/memline.c
index 6ea860d4fe..bfbf4e2807 100644
--- a/src/memline.c
+++ b/src/memline.c
@@ -1032,6 +1032,7 @@ set_b0_fname(ZERO_BL *b0p, buf_T *buf)
#endif
buf_store_time(buf, &st, buf->b_ffname);
buf->b_mtime_read = buf->b_mtime;
+ buf->b_mtime_read_ns = buf->b_mtime_ns;
}
else
{
@@ -1040,7 +1041,9 @@ set_b0_fname(ZERO_BL *b0p, buf_T *buf)
long_to_char(0L, b0p->b0_ino);
#endif
buf->b_mtime = 0;
+ buf->b_mtime_ns = 0;
buf->b_mtime_read = 0;
+ buf->b_mtime_read_ns = 0;
buf->b_orig_size = 0;
buf->b_orig_mode = 0;
}
@@ -2436,6 +2439,9 @@ ml_sync_all(int check_file, int check_char)
*/
if (mch_stat((char *)buf->b_ffname, &st) == -1
|| st.st_mtime != buf->b_mtime_read
+#ifdef ST_MTIM_NSEC
+ || st.ST_MTIM_NSEC != buf->b_mtime_read_ns
+#endif
|| st.st_size != buf->b_orig_size)
{
ml_preserve(buf, FALSE);
diff --git a/src/netbeans.c b/src/netbeans.c
index bf47df713c..5bd36a4ddd 100644
--- a/src/netbeans.c
+++ b/src/netbeans.c
@@ -1760,7 +1760,10 @@ nb_do_cmd(
if (buf == NULL || buf->bufp == NULL)
nbdebug((" invalid buffer identifier in setModtime\n"));
else
+ {
buf->bufp->b_mtime = atoi((char *)args);
+ buf->bufp->b_mtime_ns = 0;
+ }
// =====================================================================
}
else if (streq((char *)cmd, "setReadOnly"))
diff --git a/src/proto/fileio.pro b/src/proto/fileio.pro
index cdf92743b5..da6054b509 100644
--- a/src/proto/fileio.pro
+++ b/src/proto/fileio.pro
@@ -12,7 +12,7 @@ void msg_add_fname(buf_T *buf, char_u *fname);
int msg_add_fileformat(int eol_type);
void msg_add_lines(int insert_space, long lnum, off_T nchars);
void msg_add_eol(void);
-int time_differs(long t1, long t2);
+int time_differs(stat_T *st, long mtime, long mtime_ns);
int need_conversion(char_u *fenc);
int get_fio_flags(char_u *ptr);
int get_win_fio_flags(char_u *ptr);
diff --git a/src/structs.h b/src/structs.h
index 0715686f7f..7dac95b30e 100644
--- a/src/structs.h
+++ b/src/structs.h
@@ -2724,7 +2724,9 @@ struct file_buffer
wininfo_T *b_wininfo; // list of last used info for each window
long b_mtime; // last change time of original file
+ long b_mtime_ns; // nanoseconds of last change time
long b_mtime_read; // last change time when reading
+ long b_mtime_read_ns; // nanoseconds of last read time
off_T b_orig_size; // size of original file in bytes
int b_orig_mode; // mode of original file
#ifdef FEAT_VIMINFO
diff --git a/src/testdir/test_stat.vim b/src/testdir/test_stat.vim
index 5cd82b8e2f..b56528192a 100644
--- a/src/testdir/test_stat.vim
+++ b/src/testdir/test_stat.vim
@@ -76,6 +76,39 @@ func Test_checktime()
call delete(fname)
endfunc
+func Test_checktime_fast()
+ CheckFeature nanotime
+
+ let fname = 'Xtest.tmp'
+
+ let fl = ['Hello World!']
+ call writefile(fl, fname)
+ set autoread
+ exec 'e' fname
+ let fl = readfile(fname)
+ let fl[0] .= ' - checktime'
+ call writefile(fl, fname)
+ checktime
+ call assert_equal(fl[0], getline(1))
+
+ call delete(fname)
+endfunc
+
+func Test_autoread_fast()
+ CheckFeature nanotime
+
+ new Xautoread
+ set autoread
+ call setline(1, 'foo')
+
+ w!
+ silent !echo bar > Xautoread
+ checktime
+
+ call assert_equal('bar', trim(getline(1)))
+ call delete('Xautoread')
+endfunc
+
func Test_autoread_file_deleted()
new Xautoread
set autoread
diff --git a/src/version.c b/src/version.c
index 31f00157b3..d1f079cb28 100644
--- a/src/version.c
+++ b/src/version.c
@@ -758,6 +758,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 3510,
+/**/
3509,
/**/
3508,