# HG changeset patch # User Bruno Haible # Date 1550173857 -3600 # Node ID 7f0ac0398fae959a717dced84eb5052b760657d1 # Parent 9301e0f7fe60cce7fbe3049ccad614c5effc5814 gnulib-tool: Improve handling of multiple --local-dir options. * doc/gnulib.texi (Extending Gnulib): Explain how multiple --local-dir options work. * gnulib-tool (func_path_prepend): Remove function. (func_path_foreach): Make IFS handling more robust. (local_gnulib_path): Collect --local-dir values using func_path_append, not func_path_prepend. (func_determine_path_separator): Make IFS handling more robust. (func_lookup_file_cb): New function. (func_lookup_file): Rewritten to use func_lookup_file_cb instead of func_lookup_local_file. Apply the patches in the reverse order of their origin in $local_gnulib_path. (func_count_relative_local_gnulib_path): Make IFS handling more robust. * NEWS: Mention that the first --local-dir option is the one with highest priority. diff -r 9301e0f7fe60 -r 7f0ac0398fae ChangeLog --- a/ChangeLog Sun Feb 10 12:49:39 2019 +0100 +++ b/ChangeLog Thu Feb 14 20:50:57 2019 +0100 @@ -1,3 +1,21 @@ +2019-02-14 Bruno Haible + + gnulib-tool: Improve handling of multiple --local-dir options. + * doc/gnulib.texi (Extending Gnulib): Explain how multiple --local-dir + options work. + * gnulib-tool (func_path_prepend): Remove function. + (func_path_foreach): Make IFS handling more robust. + (local_gnulib_path): Collect --local-dir values using func_path_append, + not func_path_prepend. + (func_determine_path_separator): Make IFS handling more robust. + (func_lookup_file_cb): New function. + (func_lookup_file): Rewritten to use func_lookup_file_cb instead of + func_lookup_local_file. Apply the patches in the reverse order of their + origin in $local_gnulib_path. + (func_count_relative_local_gnulib_path): Make IFS handling more robust. + * NEWS: Mention that the first --local-dir option is the one with + highest priority. + 2019-02-10 Bruno Haible libtextstyle: New module. diff -r 9301e0f7fe60 -r 7f0ac0398fae NEWS --- a/NEWS Sun Feb 10 12:49:39 2019 +0100 +++ b/NEWS Thu Feb 14 20:50:57 2019 +0100 @@ -3,6 +3,10 @@ Date Modules Changes +2019-02-14 gnulib-tool If you use multiple --local-dir options at once: + The first one now has the highest priority, not the + last one. + 2019-01-04 (all) The meaning of the 'Link' section in the module descriptions has been clarified: It overrides the combined 'Link' sections from the dependencies. diff -r 9301e0f7fe60 -r 7f0ac0398fae doc/gnulib.texi --- a/doc/gnulib.texi Sun Feb 10 12:49:39 2019 +0100 +++ b/doc/gnulib.texi Thu Feb 14 20:50:57 2019 +0100 @@ -714,6 +714,15 @@ Otherwise, @command{gnulib-tool} uses the file included in Gnulib. @end itemize +You can specify the @option{--local-dir} multiple times. In this case, +the first specified directory has the highest precedence. That is, a +@file{@var{file}} found in one directory will shadow any @file{@var{file}} +and @file{@var{file}.diff} in the later directories and in the Gnulib +directory. And a file @file{@var{file}.diff} found in one directory will +be applied on top of the combination of @file{@var{file}} and +@file{@var{file}.diff} files found in the later directories and in the +Gnulib directory. + Please make wise use of this option. It also allows you to easily hold back modifications you make to Gnulib macros in cases it may be better to share them. diff -r 9301e0f7fe60 -r 7f0ac0398fae gnulib-tool --- a/gnulib-tool Sun Feb 10 12:49:39 2019 +0100 +++ b/gnulib-tool Thu Feb 14 20:50:57 2019 +0100 @@ -556,21 +556,8 @@ fi } -# func_path_prepend pathvar directory -# puts directory before pathvar, delimiting directories by PATH_SEPARATOR. -# Newly added directory into pathvar has the highest priority. -func_path_prepend () -{ - if eval "test -n \"\$$1\""; then - eval "$1=\$2\$PATH_SEPARATOR\$$1" - else - eval "$1=\$2" - fi -} - # func_path_append pathvar directory -# Similar to func_path_prepend except that the newest directory has the lowest -# priority. +# appends directory to pathvar, delimiting directories by PATH_SEPARATOR. func_path_append () { if eval "test -n \"\$$1\""; then @@ -590,7 +577,7 @@ set %start% "$@" for _fpf_arg do - case $_fpf_arg in + case "$_fpf_arg" in %start%) set dummy ;; @@ -613,17 +600,18 @@ # with processed directory from path. func_path_foreach () { - fpf_save_IFS=$IFS - fpf_dirs=$1 ; shift - fpf_cb=$1 ; shift + fpf_dirs="$1"; shift + fpf_cb="$1"; shift fpf_rc=false - IFS=$PATH_SEPARATOR + fpf_save_IFS="$IFS" + IFS="$PATH_SEPARATOR" for fpf_dir in $fpf_dirs do + IFS="$fpf_save_IFS" func_path_foreach_inner "$@" && fpf_rc=: done - IFS=$fpf_save_IFS + IFS="$fpf_save_IFS" $fpf_rc } @@ -1049,7 +1037,7 @@ # update, create-testdir, create-megatestdir, test, megatest, # copy-file # - destdir from --dir -# - local_gnulib_path from --local-dir +# - local_gnulib_path from --local-dir, highest priority dir comes first # - modcache true or false, from --cache-modules/--no-cache-modules # - verbose integer, default 0, inc/decremented by --verbose/--quiet # - libname, supplied_libname from --lib @@ -1197,11 +1185,11 @@ if test $# = 0; then func_fatal_error "missing argument for --local-dir" fi - func_path_prepend local_gnulib_path "$1" + func_path_append local_gnulib_path "$1" shift ;; --local-dir=* ) local_dir=`echo "X$1" | sed -e 's/^X--local-dir=//'` - func_path_prepend local_gnulib_path "$local_dir" + func_path_append local_gnulib_path "$local_dir" shift ;; --cache-modules | --cache-module | --cache-modul | --cache-modu | --cache-mod | --cache-mo | --cache-m | --cache- | --cache | --cach | --cac | --ca ) modcache=true @@ -1575,18 +1563,19 @@ # Remove trailing slashes from the directory names. This is necessary for # m4base (to avoid an error in func_import) and optional for the others. sed_trimtrailingslashes='s,\([^/]\)//*$,\1,' - old_local_gnulib_path=$local_gnulib_path - save_IFS=$IFS + old_local_gnulib_path="$local_gnulib_path" + local_gnulib_path= + save_IFS="$IFS" IFS=: - local_gnulib_path= for dir in $old_local_gnulib_path do + IFS="$save_IFS" case "$dir" in */ ) dir=`echo "$dir" | sed -e "$sed_trimtrailingslashes"` ;; esac func_path_append local_gnulib_path "$dir" done - IFS=$save_IFS + IFS="$save_IFS" case "$sourcebase" in */ ) sourcebase=`echo "$sourcebase" | sed -e "$sed_trimtrailingslashes"` ;; esac @@ -1630,8 +1619,8 @@ fi # func_lookup_local_file_cb dir file -# return true and set func_lookup_local_file_result if the file 'dir/file' -# exists +# returns true and sets func_lookup_local_file_result if the file $dir/$file +# exists. func_lookup_local_file_cb () { test -n "$func_lookup_local_file_result" && return 1 # already found? @@ -1653,6 +1642,25 @@ func_path_foreach "$local_gnulib_path" func_lookup_local_file_cb %dir% "$1" } +# func_lookup_file_cb dir +# does one step in processing the $local_gnulib_path, looking for $dir/$lkfile +# and $dir/$lkfile.diff. +func_lookup_file_cb () +{ + # If we found the file already in a --local-dir of higher priority, nothing + # more to do. + if test -z "$lookedup_file"; then + # Otherwise, look for $dir/$lkfile and $dir/$lkfile.diff. + if test -f "$1/$lkfile"; then + lookedup_file="$1/$lkfile" + else + if test -f "$1/$lkfile.diff"; then + lkpatches="$1/$lkfile.diff${lkpatches:+$PATH_SEPARATOR$lkpatches}" + fi + fi + fi +} + # func_lookup_file file # looks up a file in $local_gnulib_path or $gnulib_dir, or combines it through # 'patch'. @@ -1664,27 +1672,39 @@ func_lookup_file () { lkfile="$1" - if func_lookup_local_file "$lkfile"; then - lookedup_file=$func_lookup_local_file_result - lookedup_tmp= - else + # Each element in $local_gnulib_path is a directory whose contents overrides + # or amends the result of the lookup in the rest of $local_gnulib_path and + # $gnulib_dir. So, the first element of $local_gnulib_path is the highest + # priority one. + lookedup_file= + lkpatches= + func_path_foreach "$local_gnulib_path" func_lookup_file_cb %dir% + # Treat $gnulib_dir like a lowest-priority --local-dir, except that here we + # don't look for .diff files. + if test -z "$lookedup_file"; then if test -f "$gnulib_dir/$lkfile"; then - if func_lookup_local_file "$lkfile.diff"; then - lkbase=`echo "$lkfile" | sed -e 's,^.*/,,'` - rm -f "$tmp/$lkbase" - cp "$gnulib_dir/$lkfile" "$tmp/$lkbase" - patch -s "$tmp/$lkbase" < "$func_lookup_local_file_result" >&2 \ - || func_fatal_error "patch file $func_lookup_local_file_result didn't apply cleanly" - lookedup_file="$tmp/$lkbase" - lookedup_tmp=true - else - lookedup_file="$gnulib_dir/$lkfile" - lookedup_tmp= - fi + lookedup_file="$gnulib_dir/$lkfile" else func_fatal_error "file $gnulib_dir/$lkfile not found" fi fi + # Now apply the patches, from lowest-priority to highest-priority. + lookedup_tmp= + if test -n "$lkpatches"; then + lkbase=`echo "$lkfile" | sed -e 's,^.*/,,'` + rm -f "$tmp/$lkbase" + cp "$lookedup_file" "$tmp/$lkbase" + save_IFS="$IFS" + IFS="$PATH_SEPARATOR" + for patchfile in $lkpatches; do + IFS="$save_IFS" + patch -s "$tmp/$lkbase" < "$patchfile" >&2 \ + || func_fatal_error "patch file $patchfile didn't apply cleanly" + done + IFS="$save_IFS" + lookedup_file="$tmp/$lkbase" + lookedup_tmp=true + fi } # func_sanitize_modulelist @@ -5562,11 +5582,12 @@ # - relative_local_dir path to be stored into gl_LOCAL_DIR func_count_relative_local_gnulib_path () { - save_IFS=$IFS - IFS=$PATH_SEPARATOR relative_local_gnulib_path= + save_IFS="$IFS" + IFS="$PATH_SEPARATOR" for local_dir in $local_gnulib_path do + IFS="$save_IFS" # Store the local_dir relative to destdir. case "$local_dir" in "" | /*) @@ -5582,7 +5603,7 @@ esac func_path_append relative_local_gnulib_path "$relative_local_dir" done - IFS=$save_IFS + IFS="$save_IFS" } # Create m4/gnulib-cache.m4.