[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
working with locally modified or augmented gnulib repositories
From: |
Bruno Haible |
Subject: |
working with locally modified or augmented gnulib repositories |
Date: |
Sat, 29 Jul 2006 15:25:52 +0200 |
User-agent: |
KMail/1.9.1 |
Hi all,
So far, it was easy for users of gnulib-tool to use the modules unmodified,
but difficult to experiment with modifications of gnulib modules, and even
harder to keep modified versions of gnulib modules for a long time.
Multi-level source control versioning systems (SCMs) like mercurial,
monotone, git/cogito, bzr would help a lot doing so during the development
process, but
1) they are not yet widely supported, e.g. in savannah,
2) they don't address the distribution issue. When a package foobar
needs a modified version of, say, stdint_.h, it either has to
put a comment into foobar/autogen.sh saying "Attention! This doesn't
work with a pristine gnulib, you need this and that patch after
checking out gnulib", or it has to use the --avoid=stdint option
and provide the modified stdint module in a different directory
and use libtool convenience libraries.
To solve this problem, I'm adding a --local-dir option to gnulib. It allows
the package to override or augment gnulib. This means:
- You can store files that are to override gnulib files.
For example, I can add comments to my copy of xalloc.h although Paul
and Jim don't run after comments in .h files.
- You can likewise override a module description.
For example, I use a completely different 'closeout' implementation
than Jim.
- You can store context diffs to be applied to gnulib files.
For example, I patch the variable declarations in error.h, adding a
DLL_VARIABLE marker, that is needed for portability to mingw and cygwin
under certain circumstances.
- You can add modules of your own, that are not (yet) in gnulib.
- You can also add unstructured amounts of code to the library, by grouping
the non-gnulib files of the library in a single kitchen-sink "module".
And in a release tarball, you can distribute the contents of this --local-dir
directory that - barring incompatible changes in gnulib - will be combinable
with newer versions of gnulib.
Please make wise use of this option. It allows you to easily hold back
modifications you make to gnulib macros (where it may be better to share
them). On the other hand, it allows you to create your own pool of modules
in a "staging area" for gnulib.
Bruno
2006-07-29 Bruno Haible <address@hidden>
Make it possible for gnulib-tool to work with locally modified or
augmented gnulib repositories.
* gnulib-tool (func_usage): Document --local-dir option.
(local_gnulib_dir): New variable.
Handle --local-dir option.
(func_lookup_file): New function.
(func_all_modules, func_verify_module): Look also in $local_gnulib_dir.
(func_get_description, func_get_filelist, func_get_description,
func_get_filelist, func_get_dependencies, func_get_autoconf_snippet,
func_get_automake_snippet, func_get_include_directive,
func_get_license, func_get_maintainer): Use func_lookup_file.
(func_import, func_create_testdir): Use func_lookup_file.
*** gnulib-tool 29 Jul 2006 13:18:04 -0000 1.126
--- gnulib-tool 29 Jul 2006 13:21:19 -0000
***************
*** 111,116 ****
--- 111,118 ----
For --import, this specifies where your
configure.ac can be found. Defaults to current
directory.
+ --local-dir=DIRECTORY Specify a local override directory where to look
+ up files before looking in gnulib's directory.
Options for --import:
--lib=LIBRARY Specify the library name. Defaults to 'libgnu'.
***************
*** 261,266 ****
--- 263,270 ----
# - autoconf_minversion minimum supported autoconf version
# - do_changelog false if --no-changelog was given, : otherwise
# - doit : if actions shall be executed, false if only to be
printed
+ # - local_gnulib_dir from --local-dir
+ # - symbolic true if --symbolic was given, blank otherwise
{
mode=
destdir=
***************
*** 279,284 ****
--- 283,289 ----
autoconf_minversion=
do_changelog=:
doit=:
+ local_gnulib_dir=
symbolic=
supplied_opts="$@"
***************
*** 416,421 ****
--- 421,436 ----
--dry-run )
doit=false
shift ;;
+ --local-dir )
+ shift
+ if test $# = 0; then
+ func_fatal_error "missing argument for --local-dir"
+ fi
+ local_gnulib_dir=$1
+ shift ;;
+ --local-dir=* )
+ local_gnulib_dir=`echo "X$1" | sed -e 's/^X--local-dir=//'`
+ shift ;;
-s | --symbolic | --symboli | --symbol | --symbo | --symb | --symlink |
--symlin | --symli | --syml | --sym | --sy )
symbolic=true
shift ;;
***************
*** 518,540 ****
done
gnulib_dir=`echo "$self_abspathname" | sed -e 's,/[^/]*$,,'`
# func_all_modules
func_all_modules ()
{
# Filter out metainformation files like README, which are not modules.
# Filter out unit test modules; they can be retrieved through
# --extract-tests-module if desired.
! (cd "$gnulib_dir/modules" && ls -1) \
| sed -e '/^CVS$/d' -e '/^ChangeLog$/d' -e '/^README$/d' -e
'/^TEMPLATE$/d' -e '/^TEMPLATE-TESTS$/d' -e '/~$/d' \
| sed -e '/-tests$/d' \
! | LC_ALL=C sort
}
# func_verify_module
# verifies a module name
func_verify_module ()
{
! if test ! -f "$gnulib_dir/modules/$module" \
|| test "CVS" = "$module" \
|| test "ChangeLog" = "$module" \
|| test "README" = "$module" \
--- 533,598 ----
done
gnulib_dir=`echo "$self_abspathname" | sed -e 's,/[^/]*$,,'`
+ func_tmpdir
+ trap 'rm -rf "$tmp"' 0 1 2 3 15
+
+ # func_lookup_file file
+ # looks up a file in $local_gnulib_dir or $gnulib_dir, or combines it through
+ # 'patch'.
+ # Output:
+ # - lookedup_file name of the merged (combined) file
+ # - lookedup_tmp true if it is located in the tmp directory, blank
otherwise
+ func_lookup_file ()
+ {
+ lkfile="$1"
+ if test -n "$local_gnulib_dir" && test -f "$local_gnulib_dir/$lkfile"; then
+ lookedup_file="$local_gnulib_dir/$lkfile"
+ lookedup_tmp=
+ else
+ if test -f "$gnulib_dir/$lkfile"; then
+ if test -n "$local_gnulib_dir" && test -f
"$local_gnulib_dir/$lkfile.diff"; then
+ lkbase=`echo "$lkfile" | sed -e 's,^.*/,,'`
+ rm -f "$tmp/$lkbase"
+ cp "$gnulib_dir/$lkfile" "$tmp/$lkbase"
+ patch -s "$tmp/$lkbase" < "$local_gnulib_dir/$lkfile.diff" \
+ || func_fatal_error "patch file $local_gnulib_dir/$lkfile.diff
didn't apply cleanly"
+ lookedup_file="$tmp/$lkbase"
+ lookedup_tmp=true
+ else
+ lookedup_file="$gnulib_dir/$lkfile"
+ lookedup_tmp=
+ fi
+ else
+ func_fatal_error "file $gnulib_dir/$lkfile not found"
+ fi
+ fi
+ }
+
# func_all_modules
func_all_modules ()
{
# Filter out metainformation files like README, which are not modules.
# Filter out unit test modules; they can be retrieved through
# --extract-tests-module if desired.
! {
! (cd "$gnulib_dir/modules" && ls -1)
! if test -n "$local_gnulib_dir" && test -d "$local_gnulib_dir/modules";
then
! (cd "$local_gnulib_dir/modules" && ls -1 | sed -e 's,\.diff$,,')
! fi
! } \
| sed -e '/^CVS$/d' -e '/^ChangeLog$/d' -e '/^README$/d' -e
'/^TEMPLATE$/d' -e '/^TEMPLATE-TESTS$/d' -e '/~$/d' \
| sed -e '/-tests$/d' \
! | LC_ALL=C sort \
! | LC_ALL=C uniq
}
# func_verify_module
# verifies a module name
func_verify_module ()
{
! if ! { test -f "$gnulib_dir/modules/$module" \
! || { test -n "$local_gnulib_dir" && test -d
"$local_gnulib_dir/modules" \
! && test -f "$local_gnulib_dir/modules/$module"; }; } \
|| test "CVS" = "$module" \
|| test "ChangeLog" = "$module" \
|| test "README" = "$module" \
***************
*** 585,597 ****
# func_get_description module
func_get_description ()
{
! sed -n -e "/^Description$sed_extract_prog" < "$gnulib_dir/modules/$1"
}
# func_get_filelist module
func_get_filelist ()
{
! sed -n -e "/^Files$sed_extract_prog" < "$gnulib_dir/modules/$1"
case "$autoconf_minversion" in
2.59)
#echo m4/onceonly.m4
--- 643,657 ----
# func_get_description module
func_get_description ()
{
! func_lookup_file "modules/$1"
! sed -n -e "/^Description$sed_extract_prog" < "$lookedup_file"
}
# func_get_filelist module
func_get_filelist ()
{
! func_lookup_file "modules/$1"
! sed -n -e "/^Files$sed_extract_prog" < "$lookedup_file"
case "$autoconf_minversion" in
2.59)
#echo m4/onceonly.m4
***************
*** 606,643 ****
# ${module}-tests always implicitly depends on ${module}.
echo "$1" | sed -n -e 's/-tests//p'
# Then the explicit dependencies listed in the module description.
! sed -n -e "/^Depends-on$sed_extract_prog" < "$gnulib_dir/modules/$1"
}
# func_get_autoconf_snippet module
func_get_autoconf_snippet ()
{
! sed -n -e "/^configure\.ac$sed_extract_prog" < "$gnulib_dir/modules/$1"
}
# func_get_automake_snippet module
func_get_automake_snippet ()
{
! sed -n -e "/^Makefile\.am$sed_extract_prog" < "$gnulib_dir/modules/$1"
}
# func_get_include_directive module
func_get_include_directive ()
{
! sed -n -e "/^Include$sed_extract_prog" < "$gnulib_dir/modules/$1" | \
sed -e 's/^\(["<]\)/#include \1/'
}
# func_get_license module
func_get_license ()
{
! sed -n -e "/^License$sed_extract_prog" < "$gnulib_dir/modules/$1"
}
# func_get_maintainer module
func_get_maintainer ()
{
! sed -n -e "/^Maintainer$sed_extract_prog" < "$gnulib_dir/modules/$1"
}
# func_get_tests_module module
--- 666,709 ----
# ${module}-tests always implicitly depends on ${module}.
echo "$1" | sed -n -e 's/-tests//p'
# Then the explicit dependencies listed in the module description.
! func_lookup_file "modules/$1"
! sed -n -e "/^Depends-on$sed_extract_prog" < "$lookedup_file"
}
# func_get_autoconf_snippet module
func_get_autoconf_snippet ()
{
! func_lookup_file "modules/$1"
! sed -n -e "/^configure\.ac$sed_extract_prog" < "$lookedup_file"
}
# func_get_automake_snippet module
func_get_automake_snippet ()
{
! func_lookup_file "modules/$1"
! sed -n -e "/^Makefile\.am$sed_extract_prog" < "$lookedup_file"
}
# func_get_include_directive module
func_get_include_directive ()
{
! func_lookup_file "modules/$1"
! sed -n -e "/^Include$sed_extract_prog" < "$lookedup_file" | \
sed -e 's/^\(["<]\)/#include \1/'
}
# func_get_license module
func_get_license ()
{
! func_lookup_file "modules/$1"
! sed -n -e "/^License$sed_extract_prog" < "$lookedup_file"
}
# func_get_maintainer module
func_get_maintainer ()
{
! func_lookup_file "modules/$1"
! sed -n -e "/^Maintainer$sed_extract_prog" < "$lookedup_file"
}
# func_get_tests_module module
***************
*** 1152,1159 ****
fi
fi
- func_tmpdir
- trap 'rm -rf "$tmp"' 0 1 2 3 15
# func_dest_tmpfilename file
# determines the name of a temporary file (file is relative to destdir).
# Sets variable:
--- 1218,1223 ----
***************
*** 1213,1226 ****
func_add_or_update ()
{
func_dest_tmpfilename "$g"
! cp "$gnulib_dir/$f" "$tmpfile" || func_fatal_error "failed"
if test -n "$lgpl"; then
# Update license.
case "$f" in
lib/*)
sed -e 's/GNU General/GNU Lesser General/g' \
-e 's/version 2\([ ,]\)/version 2.1\1/g' \
! < "$gnulib_dir/$f" > "$tmpfile" || func_fatal_error "failed"
;;
esac
fi
--- 1277,1291 ----
func_add_or_update ()
{
func_dest_tmpfilename "$g"
! func_lookup_file "$f"
! cp "$lookedup_file" "$tmpfile" || func_fatal_error "failed"
if test -n "$lgpl"; then
# Update license.
case "$f" in
lib/*)
sed -e 's/GNU General/GNU Lesser General/g' \
-e 's/version 2\([ ,]\)/version 2.1\1/g' \
! < "$lookedup_file" > "$tmpfile" || func_fatal_error "failed"
;;
esac
fi
***************
*** 1237,1244 ****
echo "Replacing file $g (non-gnulib code backuped in ${g}~) !!"
fi
mv -f "$destdir/$g" "$destdir/${g}~" || func_fatal_error "failed"
! if test -n "$symbolic" && cmp "$gnulib_dir/$f" "$tmpfile" >
/dev/null; then
! func_ln_if_changed "$gnulib_dir/$f" "$destdir/$g"
else
mv -f "$tmpfile" "$destdir/${g}" || func_fatal_error "failed"
fi
--- 1302,1310 ----
echo "Replacing file $g (non-gnulib code backuped in ${g}~) !!"
fi
mv -f "$destdir/$g" "$destdir/${g}~" || func_fatal_error "failed"
! if test -n "$symbolic" && test -z "$lookedup_tmp" \
! && cmp "$lookedup_file" "$tmpfile" > /dev/null; then
! func_ln_if_changed "$lookedup_file" "$destdir/$g"
else
mv -f "$tmpfile" "$destdir/${g}" || func_fatal_error "failed"
fi
***************
*** 1256,1263 ****
# frequently that developers don't put autogenerated files into CVS.
if $doit; then
echo "Copying file $g"
! if test -n "$symbolic" && cmp "$gnulib_dir/$f" "$tmpfile" >
/dev/null; then
! func_ln_if_changed "$gnulib_dir/$f" "$destdir/$g"
else
mv -f "$tmpfile" "$destdir/${g}" || func_fatal_error "failed"
fi
--- 1322,1330 ----
# frequently that developers don't put autogenerated files into CVS.
if $doit; then
echo "Copying file $g"
! if test -n "$symbolic" && test -z "$lookedup_tmp" \
! && cmp "$lookedup_file" "$tmpfile" > /dev/null; then
! func_ln_if_changed "$lookedup_file" "$destdir/$g"
else
mv -f "$tmpfile" "$destdir/${g}" || func_fatal_error "failed"
fi
***************
*** 1524,1538 ****
fi
fi
- rm -rf "$tmp"
- # Undo the effect of the previous 'trap' command. Some shellology:
- # We cannot use "trap - 0 1 2 3 15", because Solaris sh would attempt to
- # execute the command "-". "trap '' ..." is fine only for signal 0 (= normal
- # exit); for the others we need to call 'exit' explicitly. The value of $?
is
- # 128 + signal number and is set before the trap-registered command is run.
- trap '' 0
- trap 'exit $?' 1 2 3 15
-
echo "Finished."
echo
echo "You may need to add #include directives for the following .h files."
--- 1591,1596 ----
***************
*** 1612,1626 ****
# Copy files or make symbolic links.
for f in $files; do
case "$f" in
build-aux/*) g=`echo "$f" | sed -e "s,^build-aux/,$auxdir/,"` ;;
*) g="$f" ;;
esac
! ln "$gnulib_dir/$f" "$testdir/$g" 2>/dev/null ||
! if test -z "$symbolic"; then
! cp -p "$gnulib_dir/$f" "$testdir/$g"
else
! ln -s "$gnulib_dir/$f" "$testdir/$g"
fi
done
--- 1670,1689 ----
# Copy files or make symbolic links.
for f in $files; do
+ func_lookup_file "$f"
case "$f" in
build-aux/*) g=`echo "$f" | sed -e "s,^build-aux/,$auxdir/,"` ;;
*) g="$f" ;;
esac
! if test -n "$lookedup_tmp"; then
! cp -p "$lookedup_file" "$testdir/$g"
else
! ln "$lookedup_file" "$testdir/$g" 2>/dev/null ||
! if test -z "$symbolic"; then
! cp -p "$lookedup_file" "$testdir/$g"
! else
! ln -s "$lookedup_file" "$testdir/$g"
! fi
fi
done
***************
*** 2176,2179 ****
--- 2239,2251 ----
func_fatal_error "unknown operation mode --$mode" ;;
esac
+ rm -rf "$tmp"
+ # Undo the effect of the previous 'trap' command. Some shellology:
+ # We cannot use "trap - 0 1 2 3 15", because Solaris sh would attempt to
+ # execute the command "-". "trap '' ..." is fine only for signal 0 (= normal
+ # exit); for the others we need to call 'exit' explicitly. The value of $? is
+ # 128 + signal number and is set before the trap-registered command is run.
+ trap '' 0
+ trap 'exit $?' 1 2 3 15
+
exit 0
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- working with locally modified or augmented gnulib repositories,
Bruno Haible <=