To: vim_dev@googlegroups.com Subject: Patch 8.2.3510 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.3510 Problem: Changes are only detected with one second accuracy. Solution: Use the nanosecond time if possible. (Leah Neukirchen, closes #8873, closes #8875) Files: runtime/doc/eval.txt, src/auto/configure, src/bufwrite.c, src/config.h.in, src/configure.ac, src/fileio.c, src/proto/fileio.pro, src/memline.c, src/netbeans.c, src/structs.h, src/evalfunc.c, src/testdir/test_stat.vim *** ../vim-8.2.3509/runtime/doc/eval.txt 2021-10-03 15:19:09.821731156 +0100 --- runtime/doc/eval.txt 2021-10-14 21:21:28.989308890 +0100 *************** *** 12126,12131 **** --- 12236,12242 ---- 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. *** ../vim-8.2.3509/src/auto/configure 2021-10-06 11:27:17.766745946 +0100 --- src/auto/configure 2021-10-14 20:48:16.658560510 +0100 *************** *** 13149,13154 **** --- 13149,13200 ---- 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 + #include + 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" *** ../vim-8.2.3509/src/bufwrite.c 2021-07-25 13:36:01.565551200 +0100 --- src/bufwrite.c 2021-10-14 21:11:12.884960869 +0100 *************** *** 527,533 **** check_mtime(buf_T *buf, stat_T *st) { if (buf->b_mtime_read != 0 ! && time_differs((long)st->st_mtime, buf->b_mtime_read)) { msg_scroll = TRUE; // don't overwrite messages here msg_silent = 0; // must give this prompt --- 527,533 ---- check_mtime(buf_T *buf, stat_T *st) { if (buf->b_mtime_read != 0 ! && 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,2563 **** --- 2558,2564 ---- { buf_store_time(buf, &st_old, fname); buf->b_mtime_read = buf->b_mtime; + buf->b_mtime_read_ns = buf->b_mtime_ns; } } } *** ../vim-8.2.3509/src/config.h.in 2021-06-20 13:01:25.980924619 +0100 --- src/config.h.in 2021-10-14 20:43:53.623758080 +0100 *************** *** 144,149 **** --- 144,152 ---- /* 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 *** ../vim-8.2.3509/src/configure.ac 2021-10-06 11:27:17.766745946 +0100 --- src/configure.ac 2021-10-14 20:43:53.627758121 +0100 *************** *** 3843,3848 **** --- 3843,3873 ---- 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 + #include ], [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 *** ../vim-8.2.3509/src/fileio.c 2021-09-22 13:18:09.313222517 +0100 --- src/fileio.c 2021-10-14 21:26:43.421387665 +0100 *************** *** 408,413 **** --- 408,414 ---- { 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,438 **** --- 433,441 ---- 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,2574 **** --- 2572,2578 ---- { buf_store_time(curbuf, &st, fname); curbuf->b_mtime_read = curbuf->b_mtime; + curbuf->b_mtime_read_ns = curbuf->b_mtime_ns; } #endif } *************** *** 3115,3129 **** } int ! time_differs(long t1, long t2) { #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); #else ! return (t1 != t2); #endif } --- 3119,3137 ---- } int ! 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 (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 (long)st->st_mtime != mtime; #endif } *************** *** 4072,4078 **** 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) || st.st_size != buf->b_orig_size #ifdef HAVE_ST_MODE || (int)st.st_mode != buf->b_orig_mode --- 4080,4086 ---- if ( !(buf->b_flags & BF_NOTEDITED) && buf->b_mtime != 0 && ((stat_res = mch_stat((char *)buf->b_ffname, &st)) < 0 ! || 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,4195 **** --- 4195,4206 ---- 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,4473 **** --- 4479,4489 ---- 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; *** ../vim-8.2.3509/src/proto/fileio.pro 2020-06-16 19:03:38.747351038 +0100 --- src/proto/fileio.pro 2021-10-14 21:10:48.108607390 +0100 *************** *** 12,18 **** 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 need_conversion(char_u *fenc); int get_fio_flags(char_u *ptr); int get_win_fio_flags(char_u *ptr); --- 12,18 ---- 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(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); *** ../vim-8.2.3509/src/memline.c 2021-10-09 15:39:20.459884353 +0100 --- src/memline.c 2021-10-14 20:43:53.627758121 +0100 *************** *** 1032,1037 **** --- 1032,1038 ---- #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,1046 **** --- 1041,1049 ---- 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,2441 **** --- 2439,2447 ---- */ 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); *** ../vim-8.2.3509/src/netbeans.c 2021-08-02 17:07:15.186473836 +0100 --- src/netbeans.c 2021-10-14 20:43:53.627758121 +0100 *************** *** 1760,1766 **** --- 1760,1769 ---- 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")) *** ../vim-8.2.3509/src/structs.h 2021-10-05 19:44:00.859799210 +0100 --- src/structs.h 2021-10-14 20:43:53.627758121 +0100 *************** *** 2724,2730 **** --- 2724,2732 ---- 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 *** ../vim-8.2.3509/src/evalfunc.c 2021-09-26 19:03:59.662298673 +0100 --- src/evalfunc.c 2021-10-14 21:18:54.039267277 +0100 *************** *** 5479,5484 **** --- 5479,5491 ---- 0 #endif }, + {"nanotime", + #ifdef ST_MTIM_NSEC + 1 + #else + 0 + #endif + }, {"num64", 1}, {"ole", #ifdef FEAT_OLE *** ../vim-8.2.3509/src/testdir/test_stat.vim 2020-08-12 17:50:31.887655765 +0100 --- src/testdir/test_stat.vim 2021-10-14 21:20:10.928283676 +0100 *************** *** 76,81 **** --- 76,114 ---- 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 *** ../vim-8.2.3509/src/version.c 2021-10-14 17:52:19.016102283 +0100 --- src/version.c 2021-10-14 20:47:59.966381260 +0100 *************** *** 759,760 **** --- 759,762 ---- { /* Add new patch number below this line */ + /**/ + 3510, /**/ -- hundred-and-one symptoms of being an internet addict: 153. You find yourself staring at your "inbox" waiting for new e-mail to arrive. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// \\\ \\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///