diff options
Diffstat (limited to 'tools')
45 files changed, 2187 insertions, 566 deletions
diff --git a/tools/backup/hot-backup.py.in b/tools/backup/hot-backup.py.in index 76bc91d..3a6d811 100755 --- a/tools/backup/hot-backup.py.in +++ b/tools/backup/hot-backup.py.in @@ -28,7 +28,7 @@ # under the License. # ==================================================================== -# $HeadURL: https://svn.apache.org/repos/asf/subversion/branches/1.10.x/tools/backup/hot-backup.py.in $ +# $HeadURL: https://svn.apache.org/repos/asf/subversion/branches/1.11.x/tools/backup/hot-backup.py.in $ # $LastChangedDate: 2015-12-21 15:02:31 +0000 (Mon, 21 Dec 2015) $ # $LastChangedBy: danielsh $ # $LastChangedRevision: 1721179 $ diff --git a/tools/buildbot/slaves/bb-openbsd/svnbuild.sh b/tools/buildbot/slaves/bb-openbsd/svnbuild.sh index 42c3260..e735465 100755 --- a/tools/buildbot/slaves/bb-openbsd/svnbuild.sh +++ b/tools/buildbot/slaves/bb-openbsd/svnbuild.sh @@ -22,7 +22,8 @@ set -e set -x -export JAVA_HOME=/usr/local/jdk-1.7.0 - -branch="$(basename $(svn info . | grep ^URL | cut -d' ' -f2))" -(cd .. && gmake BRANCH="$branch" THREADING="no") +url="$(svn info --show-item url)" +branch="${url##*/}" +(test -h ../GNUmakefile || ln -s ../unix-build/Makefile.svn ../GNUmakefile) +touch ../objdir/svn-${branch}/.retrieved +(cd .. && gmake BRANCH="$branch" THREADING="no" JAVA="no" MAKE_JOBS=8) diff --git a/tools/buildbot/slaves/bb-openbsd/svncheck-bindings.sh b/tools/buildbot/slaves/bb-openbsd/svncheck-bindings.sh index 9d47b1f..e68775b 100755 --- a/tools/buildbot/slaves/bb-openbsd/svncheck-bindings.sh +++ b/tools/buildbot/slaves/bb-openbsd/svncheck-bindings.sh @@ -22,11 +22,11 @@ set -e set -x -branch="$(basename $(svn info . | grep ^URL | cut -d' ' -f2))" +url="$(svn info --show-item url)" +branch="${url##*/}" export MALLOC_OPTIONS=S -(cd .. && gmake BRANCH="$branch" THREADING="no" svn-check-bindings) +(cd .. && gmake BRANCH="$branch" THREADING="no" JAVA="no" svn-check-bindings) grep -q "^Result: PASS$" tests.log.bindings.pl || exit 1 grep -q "^OK$" tests.log.bindings.py || exit 1 grep -q ", 0 failures, 0 errors" tests.log.bindings.rb || exit 1 -#TODO javahl exit 0 diff --git a/tools/buildbot/slaves/bb-openbsd/svncheck.sh b/tools/buildbot/slaves/bb-openbsd/svncheck.sh index 7d50d98..4bac2bd 100755 --- a/tools/buildbot/slaves/bb-openbsd/svncheck.sh +++ b/tools/buildbot/slaves/bb-openbsd/svncheck.sh @@ -22,10 +22,10 @@ set -e set -x -branch="$(basename $(svn info . | grep ^URL | cut -d' ' -f2))" +url="$(svn info --show-item url)" +branch="${url##*/}" export MALLOC_OPTIONS=S -(cd .. && gmake BRANCH="$branch" PARALLEL="" THREADING="no" \ - MEMCACHED_SERVER="127.0.0.1:11211" \ +(cd .. && gmake BRANCH="$branch" PARALLEL="4" THREADING="no" JAVA="no" \ EXCLUSIVE_WC_LOCKS=1 \ svn-check-local \ svn-check-svn \ diff --git a/tools/buildbot/slaves/bb-openbsd/svnclean.sh b/tools/buildbot/slaves/bb-openbsd/svnclean.sh index 063f4dd..3fd8278 100755 --- a/tools/buildbot/slaves/bb-openbsd/svnclean.sh +++ b/tools/buildbot/slaves/bb-openbsd/svnclean.sh @@ -22,12 +22,20 @@ set -e set -x -branch="$(basename $(svn info . | grep ^URL | cut -d' ' -f2))" +url="$(svn info --show-item url)" +branch="${url##*/}" (test -h ../svn-trunk || ln -s build ../svn-trunk) -for i in 6 7 8 9 10; do +for i in $(jot - 6 12); do (test -h ../svn-1.${i}.x || ln -s build ../svn-1.${i}.x) done +lastchangedrev="$(svn info --show-item=last-changed-revision ../../unix-build/Makefile.svn)" svn update ../../unix-build +newlastchangedrev="$(svn info --show-item=last-changed-revision ../../unix-build/Makefile.svn)" (test -h ../GNUmakefile || ln -s ../unix-build/Makefile.svn ../GNUmakefile) -(cd .. && gmake BRANCH="$branch" reset clean) +# always rebuild svn, but only rebuild dependencies if Makefile.svn has changed +if [ "$lastchangedrev" != "$newlastchangedrev" ]; then + (cd .. && gmake BRANCH="$branch" reset clean) +else + (cd .. && gmake BRANCH="$branch" svn-reset svn-bindings-reset svn-clean) +fi rm -f tests.log* fails.log* diff --git a/tools/buildbot/slaves/xp-vc60-ia32/config.bat.tmpl b/tools/buildbot/slaves/xp-vc60-ia32/config.bat.tmpl deleted file mode 100644 index 1221b7a..0000000 --- a/tools/buildbot/slaves/xp-vc60-ia32/config.bat.tmpl +++ /dev/null @@ -1,44 +0,0 @@ -REM Licensed to the Apache Software Foundation (ASF) under one
-REM or more contributor license agreements. See the NOTICE file
-REM distributed with this work for additional information
-REM regarding copyright ownership. The ASF licenses this file
-REM to you under the Apache License, Version 2.0 (the
-REM "License"); you may not use this file except in compliance
-REM with the License. You may obtain a copy of the License at
-REM
-REM http://www.apache.org/licenses/LICENSE-2.0
-REM
-REM Unless required by applicable law or agreed to in writing,
-REM software distributed under the License is distributed on an
-REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-REM KIND, either express or implied. See the License for the
-REM specific language governing permissions and limitations
-REM under the License.
-
-set MSDEV=C:\Program Files\VS6.0
-set HTTPD_BIN_DIR=C:\Program Files\Apache2
-set TEST_DIR=C:\tmp\svn-auto-test
-set SDK_DIR=C:\Program Files\VS.NET\Vc7\PlatformSDK\
-
-set HTTPD_SRC_DIR=..\httpd
-set BDB_DIR=..\db4-win32
-set NEON_DIR=..\neon
-set ZLIB_DIR=..\zlib
-set OPENSSL_DIR=..\openssl
-set INTL_DIR=..\svn-win32-libintl
-
-REM Uncomment this if you want clean subversion build, after testing
-REM set CLEAN_SVN=1
-
-REM Uncomment this if you want disable ra_svn tests
-REM set NO_RA_SVN=1
-
-REM Uncomment this if you want disable ra_dav tests
-REM set NO_RA_HTTP=1
-
-set SDKINC=%SDK_DIR%\include
-set SDKLIB=%SDK_DIR%\lib
-
-set PATH=%MSDEV%\VC98\Bin;%MSDEV%\Common\MSDev98\Bin\;%PATH%
-set INCLUDE=%SDKINC%;%MSDEV%\VC98\ATL\INCLUDE;%MSDEV%\VC98\INCLUDE;%MSDEV%\VC98\MFC\INCLUDE
-set LIB=%SDKLIB%;%MSDEV%\VC98\LIB;%MSDEV%\VC98\MFC\LIB
diff --git a/tools/buildbot/slaves/xp-vc60-ia32/svnbuild.bat b/tools/buildbot/slaves/xp-vc60-ia32/svnbuild.bat deleted file mode 100644 index 2d5a671..0000000 --- a/tools/buildbot/slaves/xp-vc60-ia32/svnbuild.bat +++ /dev/null @@ -1,77 +0,0 @@ -REM Licensed to the Apache Software Foundation (ASF) under one -REM or more contributor license agreements. See the NOTICE file -REM distributed with this work for additional information -REM regarding copyright ownership. The ASF licenses this file -REM to you under the Apache License, Version 2.0 (the -REM "License"); you may not use this file except in compliance -REM with the License. You may obtain a copy of the License at -REM -REM http://www.apache.org/licenses/LICENSE-2.0 -REM -REM Unless required by applicable law or agreed to in writing, -REM software distributed under the License is distributed on an -REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -REM KIND, either express or implied. See the License for the -REM specific language governing permissions and limitations -REM under the License. - -IF NOT EXIST ..\config.bat GOTO noconfig -call ..\config.bat - -IF NOT "%OPENSSL_DIR%"=="" call :openssl -IF ERRORLEVEL 1 GOTO ERROR - -set PARAMS=-t dsp --with-berkeley-db=%BDB_DIR% --with-libintl=%INTL_DIR% --with-zlib=%ZLIB_DIR% --with-httpd=%HTTPD_SRC_DIR% --with-neon=%NEON_DIR% --enable-bdb-in-apr-util -IF NOT "%OPENSSL_DIR%"=="" set PARAMS=%PARAMS% --with-openssl=%OPENSSL_DIR% - -python gen-make.py %PARAMS% -IF ERRORLEVEL 1 GOTO ERROR - -MSDEV.COM %HTTPD_SRC_DIR%\apache.dsw /MAKE "BuildBin - Win32 Release" -IF ERRORLEVEL 1 GOTO ERROR - -MSDEV.COM subversion_msvc.dsw /USEENV /MAKE "__ALL_TESTS__ - Win32 Release" -IF ERRORLEVEL 1 GOTO ERROR - - -EXIT 0 - -REM ---------------------------------------------------- -:ERROR -ECHO. -ECHO *** Whoops, something choked. -ECHO. -CD .. -EXIT 1 - - -:openssl -rem ====== Build openssl. -pushd %OPENSSL_DIR% -perl Configure VC-WIN32 -IF ERRORLEVEL 1 goto openssl-err1 - -call ms\do_ms -IF ERRORLEVEL 1 goto openssl-err1 - -nmake -f ms\ntdll.mak /NOLOGO /S -IF ERRORLEVEL 1 goto openssl-err1 - -pushd out32dll -call ..\ms\test -IF ERRORLEVEL 1 goto openssl-err2 - -popd -popd -EXIT /B 0 - -:openssl-err2 -popd - -:openssl-err1 -popd -EXIT 1 - -:noconfig -echo File config.bat not found. Please copy it from config.bat.tmpl and tweak for you. -EXIT 2 diff --git a/tools/buildbot/slaves/xp-vc60-ia32/svncheck.bat b/tools/buildbot/slaves/xp-vc60-ia32/svncheck.bat deleted file mode 100644 index 70e8768..0000000 --- a/tools/buildbot/slaves/xp-vc60-ia32/svncheck.bat +++ /dev/null @@ -1,51 +0,0 @@ -REM Licensed to the Apache Software Foundation (ASF) under one -REM or more contributor license agreements. See the NOTICE file -REM distributed with this work for additional information -REM regarding copyright ownership. The ASF licenses this file -REM to you under the Apache License, Version 2.0 (the -REM "License"); you may not use this file except in compliance -REM with the License. You may obtain a copy of the License at -REM -REM http://www.apache.org/licenses/LICENSE-2.0 -REM -REM Unless required by applicable law or agreed to in writing, -REM software distributed under the License is distributed on an -REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -REM KIND, either express or implied. See the License for the -REM specific language governing permissions and limitations -REM under the License. - -IF NOT EXIST ..\config.bat GOTO noconfig -call ..\config.bat - -set FS_TYPE=%1 -set RA_TYPE=%2 - -REM By default, return zero -set ERR=0 - -if "%RA_TYPE%"=="ra_local" goto ra_local -if "%RA_TYPE%"=="ra_svn" goto ra_svn -if "%RA_TYPE%"=="ra_dav" goto ra_dav - -echo Unknown ra method '%RA_TYPE%' -EXIT 3 - -:ra_local -python win-tests.py %TEST_DIR% -f %FS_TYPE% -c -r -if ERRORLEVEL 1 set ERR=1 -EXIT %ERR% - -:ra_svn -python win-tests.py %TEST_DIR% -f %FS_TYPE% -c -r -u svn://localhost -if ERRORLEVEL 1 set ERR=1 -EXIT %ERR% - -:ra_dav -python win-tests.py %TEST_DIR% -f %FS_TYPE% -c -r --httpd-dir="%HTTPD_BIN_DIR%" --httpd-port 1234 -if ERRORLEVEL 1 set ERR=1 -EXIT %ERR% - -:noconfig -echo File config.bat not found. Please copy it from config.bat.tmpl and tweak for you. -EXIT 2 diff --git a/tools/buildbot/slaves/xp-vc60-ia32/svnclean.bat b/tools/buildbot/slaves/xp-vc60-ia32/svnclean.bat deleted file mode 100644 index 64df9b8..0000000 --- a/tools/buildbot/slaves/xp-vc60-ia32/svnclean.bat +++ /dev/null @@ -1,28 +0,0 @@ -REM Licensed to the Apache Software Foundation (ASF) under one -REM or more contributor license agreements. See the NOTICE file -REM distributed with this work for additional information -REM regarding copyright ownership. The ASF licenses this file -REM to you under the Apache License, Version 2.0 (the -REM "License"); you may not use this file except in compliance -REM with the License. You may obtain a copy of the License at -REM -REM http://www.apache.org/licenses/LICENSE-2.0 -REM -REM Unless required by applicable law or agreed to in writing, -REM software distributed under the License is distributed on an -REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -REM KIND, either express or implied. See the License for the -REM specific language governing permissions and limitations -REM under the License. - -IF NOT EXIST ..\config.bat GOTO noconfig -call ..\config.bat - -if NOT "%CLEAN_SVN%"=="" MSDEV.COM subversion_msvc.dsw /MAKE "__ALL_TESTS__ - Win32 Release" /CLEAN -if ERRORLEVEL 1 EXIT 1 - -EXIT 0 - -:noconfig -echo File config.bat not found. Please copy it from config.bat.tmpl and tweak for you. -EXIT 2 diff --git a/tools/buildbot/slaves/xp-vc60-ia32/svnlog.bat b/tools/buildbot/slaves/xp-vc60-ia32/svnlog.bat deleted file mode 100644 index bb0d872..0000000 --- a/tools/buildbot/slaves/xp-vc60-ia32/svnlog.bat +++ /dev/null @@ -1,25 +0,0 @@ -REM Licensed to the Apache Software Foundation (ASF) under one -REM or more contributor license agreements. See the NOTICE file -REM distributed with this work for additional information -REM regarding copyright ownership. The ASF licenses this file -REM to you under the Apache License, Version 2.0 (the -REM "License"); you may not use this file except in compliance -REM with the License. You may obtain a copy of the License at -REM -REM http://www.apache.org/licenses/LICENSE-2.0 -REM -REM Unless required by applicable law or agreed to in writing, -REM software distributed under the License is distributed on an -REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -REM KIND, either express or implied. See the License for the -REM specific language governing permissions and limitations -REM under the License. - -IF NOT EXIST ..\config.bat GOTO noconfig -call ..\config.bat - -EXIT 0 - -:noconfig -echo File config.bat not found. Please copy it from config.bat.tmpl and tweak for you. -EXIT 2 diff --git a/tools/client-side/bash_completion b/tools/client-side/bash_completion index 53632fb..d2095ca 100644 --- a/tools/client-side/bash_completion +++ b/tools/client-side/bash_completion @@ -248,7 +248,8 @@ _svn() cmds="$cmds patch propdel pdel propedit pedit propget pget proplist" cmds="$cmds plist propset pset relocate resolve resolved revert status" cmds="$cmds switch unlock update upgrade" - cmds="$cmds shelve shelves unshelve" + cmds="$cmds x-shelf-diff x-shelf-drop x-shelf-list x-shelf-list-by-paths" + cmds="$cmds x-shelf-log x-shelf-save x-shelve x-shelves x-unshelve" # help options have a strange command status... local helpOpts='--help -h' @@ -845,9 +846,11 @@ _svn() # otherwise build possible options for the command pOpts="--username --password --no-auth-cache --non-interactive \ + --password-from-stdin \ --trust-server-cert-failures \ --force-interactive" - mOpts="-m --message -F --file --encoding --force-log --with-revprop" + mOpts="-m --message -F --file --encoding --force-log --with-revprop \ + --editor-cmd" rOpts="-r --revision" qOpts="-q --quiet" nOpts="-N --non-recursive --depth" @@ -886,16 +889,16 @@ _svn() --remove-ignored --remove-unversioned --vacuum-pristines" ;; commit|ci) - cmdOpts="$mOpts $qOpts $nOpts --targets --editor-cmd $pOpts \ + cmdOpts="$mOpts $qOpts $nOpts --targets $pOpts \ --no-unlock $cOpts --keep-changelists \ --include-externals" ;; copy|cp) - cmdOpts="$mOpts $rOpts $qOpts --editor-cmd $pOpts --parents \ + cmdOpts="$mOpts $rOpts $qOpts $pOpts --parents \ --ignore-externals --pin-externals" ;; delete|del|remove|rm) - cmdOpts="--force $mOpts $qOpts --targets --editor-cmd $pOpts \ + cmdOpts="--force $mOpts $qOpts --targets $pOpts \ --keep-local" ;; diff|di) @@ -915,7 +918,7 @@ _svn() ;; import) cmdOpts="--auto-props --no-auto-props $mOpts $qOpts $nOpts \ - --no-ignore --editor-cmd $pOpts --force" + --no-ignore $pOpts --force" ;; info) cmdOpts="$pOpts $rOpts --targets -R --recursive --depth \ @@ -949,10 +952,10 @@ _svn() $qOpts -v --verbose --incremental --log" ;; mkdir) - cmdOpts="$mOpts $qOpts --editor-cmd $pOpts --parents" + cmdOpts="$mOpts $qOpts $pOpts --parents" ;; move|mv|rename|ren) - cmdOpts="$mOpts $qOpts --force --editor-cmd $pOpts \ + cmdOpts="$mOpts $qOpts --force $pOpts \ --parents --allow-mixed-revisions" ;; patch) @@ -965,7 +968,7 @@ _svn() [[ $isRevProp || ! $prop ]] && cmdOpts="$cmdOpts --revprop" ;; propedit|pedit|pe) - cmdOpts="--editor-cmd $pOpts $mOpts --force" + cmdOpts="$pOpts $mOpts --force" [[ $isRevProp || ! $prop ]] && \ cmdOpts="$cmdOpts --revprop $rOpts" ;; @@ -1021,15 +1024,37 @@ _svn() upgrade) cmdOpts="$qOpts $pOpts" ;; - shelve) - cmdOpts="$qOpts --keep-local --delete --list -m --message -F --file --encoding --force-log --editor-cmd --dry-run --depth --targets $cOpts $pOpts" + x-shelf-list-by-paths) + cmdOpts="$pOpts" ;; - unshelve) - cmdOpts="$qOpts --keep-shelved --list --dry-run $pOpts" + x-shelf-diff) + cmdOpts="$pOpts --summarize" ;; - shelves) + x-shelf-drop) + cmdOpts="$pOpts" + ;; + x-shelf-list|x-shelves) + cmdOpts="$qOpts $pOpts" + ;; + x-shelf-log) cmdOpts="$qOpts $pOpts" ;; + x-shelf-save) + cmdOpts="--dry-run \ + --depth --targets $cOpts \ + $mOpts \ + $qOpts $pOpts" + ;; + x-shelve) + cmdOpts="--keep-local --dry-run \ + --depth --targets $cOpts \ + $mOpts \ + $qOpts $pOpts" + ;; + x-unshelve) + cmdOpts="--drop --dry-run \ + $qOpts $pOpts" + ;; *) ;; esac diff --git a/tools/client-side/svn-mergeinfo-normalizer/help-cmd.c b/tools/client-side/svn-mergeinfo-normalizer/help-cmd.c index d2f1731..09e611e 100644 --- a/tools/client-side/svn-mergeinfo-normalizer/help-cmd.c +++ b/tools/client-side/svn-mergeinfo-normalizer/help-cmd.c @@ -176,7 +176,7 @@ svn_min__help(apr_getopt_t *os, svn_stringbuf_appendcstr(version_footer, "* KWallet (KDE)\n"); #endif - return svn_opt_print_help4(os, + return svn_opt_print_help5(os, "svn-mergeinfo-normalizer", opt_state ? opt_state->version : FALSE, opt_state ? opt_state->quiet : FALSE, diff --git a/tools/client-side/svn-mergeinfo-normalizer/mergeinfo-normalizer.h b/tools/client-side/svn-mergeinfo-normalizer/mergeinfo-normalizer.h index 8afff31..9112f05 100644 --- a/tools/client-side/svn-mergeinfo-normalizer/mergeinfo-normalizer.h +++ b/tools/client-side/svn-mergeinfo-normalizer/mergeinfo-normalizer.h @@ -117,7 +117,7 @@ svn_opt_subcommand_t svn_min__remove_branches; /* See definition in svn.c for documentation. */ -extern const svn_opt_subcommand_desc2_t svn_min__cmd_table[]; +extern const svn_opt_subcommand_desc3_t svn_min__cmd_table[]; /* See definition in svn.c for documentation. */ extern const int svn_min__global_options[]; diff --git a/tools/client-side/svn-mergeinfo-normalizer/svn-mergeinfo-normalizer.c b/tools/client-side/svn-mergeinfo-normalizer/svn-mergeinfo-normalizer.c index c0c7fc3..fd12cc6 100644 --- a/tools/client-side/svn-mergeinfo-normalizer/svn-mergeinfo-normalizer.c +++ b/tools/client-side/svn-mergeinfo-normalizer/svn-mergeinfo-normalizer.c @@ -221,43 +221,44 @@ const int svn_min__global_options[] = opt_config_dir, opt_config_options, 0 }; -const svn_opt_subcommand_desc2_t svn_min__cmd_table[] = +const svn_opt_subcommand_desc3_t svn_min__cmd_table[] = { - { "help", svn_min__help, {"?", "h"}, N_ - ("Describe the usage of this program or its subcommands.\n" - "usage: help [SUBCOMMAND...]\n"), + { "help", svn_min__help, {"?", "h"}, {N_( + "Describe the usage of this program or its subcommands.\n" + "usage: help [SUBCOMMAND...]\n" + )}, {0} }, /* This command is also invoked if we see option "--help", "-h" or "-?". */ - { "analyze", svn_min__analyze, { "analyse" }, N_ - ("Generate a report of which part of the sub-tree mergeinfo can be\n" + { "analyze", svn_min__analyze, { "analyse" }, {N_( + "Generate a report of which part of the sub-tree mergeinfo can be\n" "removed and which part can't.\n" "usage: analyze [WCPATH...]\n" - "\n" + "\n"), N_( " If neither --remove-obsoletes, --remove-redundant nor --combine-ranges\n" " option is given, all three will be used implicitly.\n" - "\n" + "\n"), N_( " In verbose mode, the command will behave just like 'normalize --dry-run'\n" " but will show an additional summary of all deleted branches that were\n" " encountered plus the revision of their latest deletion (if available).\n" - "\n" + "\n"), N_( " In non-verbose mode, the per-node output does not give the parent path,\n" " no successful elisions and branch removals nor the list of remaining\n" " branches.\n" - ), + )}, {opt_targets, opt_depth, 'v', opt_remove_obsoletes, opt_remove_redundant, opt_remove_redundant_misaligned, opt_combine_ranges} }, - { "normalize", svn_min__normalize, { 0 }, N_ - ("Normalize / reduce the mergeinfo throughout the working copy sub-tree.\n" + { "normalize", svn_min__normalize, { 0 }, {N_( + "Normalize / reduce the mergeinfo throughout the working copy sub-tree.\n" "usage: normalize [WCPATH...]\n" - "\n" + "\n"), N_( " If neither --remove-obsoletes, --remove-redundant, --combine-ranges\n" " nor --remove-redundant-misaligned option is given, --remove-redundant\n" " will be used implicitly.\n" - "\n" + "\n"), N_( " In non-verbose mode, only general progress as well as a summary before\n" " and after the normalization process will be shown. Note that sub-node\n" " mergeinfo which could be removed entirely does not contribute to the\n" @@ -265,12 +266,12 @@ const svn_opt_subcommand_desc2_t svn_min__cmd_table[] = " ranges combined only refers to the mergeinfo lines still present after\n" " the normalization process. To get total numbers, compare the initial\n" " with the final mergeinfo statistics.\n" - "\n" + "\n"), N_( " The detailed operation log in verbose mode replaces the progress display.\n" " For each node with mergeinfo, the nearest parent node with mergeinfo is\n" " given - if there is one and the result of trying to remove the mergeinfo\n" " is shown for each branch. The various outputs are:\n" - "\n" + "\n"), N_( " elide redundant branch - Revision ranges are the same as in the parent.\n" " Mergeinfo for this branch can be elided.\n" " elide branch - Not an exact match with the parent but the\n" @@ -324,32 +325,34 @@ const svn_opt_subcommand_desc2_t svn_min__cmd_table[] = " The sub-tree mergeinfo cannot be elided.\n" " REVERSE RANGE(S) found - The mergeinfo contains illegal reverse ranges.\n" " The sub-tree mergeinfo cannot be elided.\n" - "\n" + "\n"), N_( " If all branches have been removed from a nodes' mergeinfo, the whole\n" " svn:mergeinfo property will be removed. Otherwise, only obsolete\n" " branches will be removed. In verbose mode, a list of branches that\n" - " could not be removed will be shown per node.\n"), + " could not be removed will be shown per node.\n" + )}, {opt_targets, opt_depth, opt_dry_run, 'q', 'v', opt_remove_obsoletes, opt_remove_redundant, opt_remove_redundant_misaligned, opt_combine_ranges} }, - { "remove-branches", svn_min__remove_branches, { 0 }, N_ - ("Read a list of branch names from the given file and remove all\n" + { "remove-branches", svn_min__remove_branches, { 0 }, {N_( + "Read a list of branch names from the given file and remove all\n" "mergeinfo referring to these branches from the given targets.\n" "usage: remove-branches [WCPATH...] --file FILE\n" - "\n" + "\n"), N_( " The command will behave just like 'normalize --remove-obsoletes' but\n" " will never actually contact the repository. Instead, it assumes any\n" " path given in FILE is a deleted branch.\n" - "\n" + "\n"), N_( " Compared to a simple 'normalize --remove-obsoletes' run, this command\n" " allows for selective removal of obsolete branches. It may therefore be\n" " better suited for large deployments with complex branch structures.\n" " You may also use this to remove mergeinfo that refers to still existing\n" - " branches.\n"), + " branches.\n" + )}, {opt_targets, opt_depth, opt_dry_run, 'q', 'v', 'F'} }, - { NULL, NULL, {0}, NULL, {0} } + { NULL, NULL, {0}, {NULL}, {0} } }; @@ -414,7 +417,7 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) svn_client_ctx_t *ctx; apr_array_header_t *received_opts; int i; - const svn_opt_subcommand_desc2_t *subcommand = NULL; + const svn_opt_subcommand_desc3_t *subcommand = NULL; svn_min__cmd_baton_t command_baton = { 0 }; svn_auth_baton_t *ab; svn_config_t *cfg_config; @@ -639,7 +642,7 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) just typos/mistakes. Whatever the case, the subcommand to actually run is svn_cl__help(). */ if (opt_state.help) - subcommand = svn_opt_get_canonical_subcommand2(svn_min__cmd_table, "help"); + subcommand = svn_opt_get_canonical_subcommand3(svn_min__cmd_table, "help"); /* If we're not running the `help' subcommand, then look for a subcommand in the first argument. */ @@ -650,8 +653,8 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) if (opt_state.version) { /* Use the "help" subcommand to handle the "--version" option. */ - static const svn_opt_subcommand_desc2_t pseudo_cmd = - { "--version", svn_min__help, {0}, "", + static const svn_opt_subcommand_desc3_t pseudo_cmd = + { "--version", svn_min__help, {0}, {""}, {opt_version, /* must accept its own option */ 'q', /* brief output */ 'v', /* verbose output */ @@ -676,7 +679,7 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) SVN_ERR(svn_utf_cstring_to_utf8(&first_arg, os->argv[os->ind++], pool)); - subcommand = svn_opt_get_canonical_subcommand2(svn_min__cmd_table, + subcommand = svn_opt_get_canonical_subcommand3(svn_min__cmd_table, first_arg); if (subcommand == NULL) { @@ -704,12 +707,12 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) if (opt_id == 'h' || opt_id == '?') continue; - if (! svn_opt_subcommand_takes_option3(subcommand, opt_id, + if (! svn_opt_subcommand_takes_option4(subcommand, opt_id, svn_min__global_options)) { const char *optstr; const apr_getopt_option_t *badopt = - svn_opt_get_option_from_code2(opt_id, svn_min__options, + svn_opt_get_option_from_code3(opt_id, svn_min__options, subcommand, pool); svn_opt_format_option(&optstr, badopt, FALSE, pool); if (subcommand->name[0] == '-') diff --git a/tools/client-side/svn-mergeinfo-normalizer/wc_mergeinfo.c b/tools/client-side/svn-mergeinfo-normalizer/wc_mergeinfo.c index 6d7b841..edc2208 100644 --- a/tools/client-side/svn-mergeinfo-normalizer/wc_mergeinfo.c +++ b/tools/client-side/svn-mergeinfo-normalizer/wc_mergeinfo.c @@ -112,8 +112,8 @@ static int compare_mergeinfo(const void *lhs, const void *rhs) { - const mergeinfo_t *lhs_mi = *(const mergeinfo_t **)lhs; - const mergeinfo_t *rhs_mi = *(const mergeinfo_t **)rhs; + const mergeinfo_t *lhs_mi = *(const mergeinfo_t *const *)lhs; + const mergeinfo_t *rhs_mi = *(const mergeinfo_t *const *)rhs; return strcmp(lhs_mi->local_path, rhs_mi->local_path); } diff --git a/tools/client-side/svn-viewspec.py b/tools/client-side/svn-viewspec.py index cdcd495..0f9ddf4 100755 --- a/tools/client-side/svn-viewspec.py +++ b/tools/client-side/svn-viewspec.py @@ -121,6 +121,8 @@ DEPTH_FILES = 'files' DEPTH_IMMEDIATES = 'immediates' DEPTH_INFINITY = 'infinity' +os_system = None +args = None class TreeNode: """A representation of a single node in a Subversion sparse @@ -159,8 +161,8 @@ def svn_path_compare_paths(path1, path2): NOTE: Stolen unapologetically from Subversion's Python bindings module svn.core.""" - path1_len = len(path1); - path2_len = len(path2); + path1_len = len(path1) + path2_len = len(path2) min_len = min(path1_len, path2_len) i = 0 @@ -280,10 +282,10 @@ def checkout_tree(base_url, revision, tree_node, target_dir, is_top=True): if revision != -1: revision_str = "--revision=%d " % (revision) if is_top: - os.system('svn checkout "%s" "%s" --depth=%s %s' + os_system('svn checkout "%s" "%s" --depth=%s %s' % (base_url, target_dir, depth, revision_str)) else: - os.system('svn update "%s" --set-depth=%s %s' + os_system('svn update "%s" --set-depth=%s %s' % (target_dir, depth, revision_str)) child_names = tree_node.children.keys() child_names.sort(svn_path_compare_paths) @@ -304,27 +306,34 @@ def checkout_spec(viewspec, target_dir): def usage_and_exit(errmsg=None): stream = errmsg and sys.stderr or sys.stdout - msg = __doc__.replace("__SCRIPTNAME__", os.path.basename(sys.argv[0])) + msg = __doc__.replace("__SCRIPTNAME__", os.path.basename(args[0])) stream.write(msg) if errmsg: stream.write("ERROR: %s\n" % (errmsg)) - sys.exit(errmsg and 1 or 0) + return 1 + return 0 + +def main(os_sys, args_in): + global os_system + global args + os_system = os_sys + args = args_in -def main(): - argc = len(sys.argv) + argc = len(args) if argc < 2: - usage_and_exit('Not enough arguments.') - subcommand = sys.argv[1] + return usage_and_exit('Not enough arguments.') + subcommand = args[1] if subcommand == 'help': - usage_and_exit() + return usage_and_exit() elif subcommand == 'help-format': msg = FORMAT_HELP.replace("__SCRIPTNAME__", - os.path.basename(sys.argv[0])) + os.path.basename(args[0])) sys.stdout.write(msg) + return 1 elif subcommand == 'examine': if argc < 3: - usage_and_exit('No viewspec file specified.') - fp = (sys.argv[2] == '-') and sys.stdin or open(sys.argv[2], 'r') + return usage_and_exit('No viewspec file specified.') + fp = (args[2] == '-') and sys.stdin or open(args[2], 'r') viewspec = parse_viewspec(fp) sys.stdout.write("Url: %s\n" % (viewspec.base_url)) revision = viewspec.revision @@ -336,13 +345,14 @@ def main(): viewspec.tree.dump(True) elif subcommand == 'checkout': if argc < 3: - usage_and_exit('No viewspec file specified.') + return usage_and_exit('No viewspec file specified.') if argc < 4: - usage_and_exit('No target directory specified.') - fp = (sys.argv[2] == '-') and sys.stdin or open(sys.argv[2], 'r') - checkout_spec(parse_viewspec(fp), sys.argv[3]) + return usage_and_exit('No target directory specified.') + fp = (args[2] == '-') and sys.stdin or open(args[2], 'r') + checkout_spec(parse_viewspec(fp), args[3]) else: - usage_and_exit('Unknown subcommand "%s".' % (subcommand)) + return usage_and_exit('Unknown subcommand "%s".' % (subcommand)) if __name__ == "__main__": - main() + if main(os.system, sys.argv): + sys.exit(1) diff --git a/tools/client-side/svnconflict/svnconflict.c b/tools/client-side/svnconflict/svnconflict.c index 3ee149b..d7b1242 100644 --- a/tools/client-side/svnconflict/svnconflict.c +++ b/tools/client-side/svnconflict/svnconflict.c @@ -148,18 +148,19 @@ static const int svnconflict_global_options[] = { opt_auth_username, opt_auth_password, opt_auth_password_from_stdin, opt_config_dir, opt_config_options, 0 }; -static const svn_opt_subcommand_desc2_t svnconflict_cmd_table[] = +static const svn_opt_subcommand_desc3_t svnconflict_cmd_table[] = { /* This command is also invoked if we see option "--help", "-h" or "-?". */ - { "help", svnconflict_help, {"?", "h"}, N_ - ("Describe the usage of this program or its subcommands.\n" - "usage: help [SUBCOMMAND...]\n"), + { "help", svnconflict_help, {"?", "h"}, {N_( + "Describe the usage of this program or its subcommands.\n" + "usage: help [SUBCOMMAND...]\n" + )}, {0} }, - { "list", svnconflict_list, {"ls"}, N_ - ("List conflicts at a conflicted path.\n" + { "list", svnconflict_list, {"ls"}, {N_( + "List conflicts at a conflicted path.\n" "usage: list PATH\n" - "\n" + "\n"), N_( " List conflicts at PATH, one per line. Possible conflicts are:\n" " \n" " text-conflict\n" @@ -176,67 +177,67 @@ static const svn_opt_subcommand_desc2_t svnconflict_cmd_table[] = " If a tree conflict exists, no text or property conflicts exist.\n" " \n" " If PATH is not in conflict, the exit code will be 1, and 0 otherwise.\n" - ""), + )}, {0}, }, - { "options-text", svnconflict_options_text, {0}, N_ - ("List options for resolving a text conflict at path.\n" + { "options-text", svnconflict_options_text, {0}, {N_( + "List options for resolving a text conflict at path.\n" "usage: options-text PATH\n" - "\n" + "\n"), N_( " List text conflict resolution options at PATH, one per line.\n" " Each line contains a numeric option ID, a colon, and a description.\n" " If PATH is not in conflict, the exit code will be 1, and 0 otherwise.\n" - ""), + )}, {0}, }, - { "options-prop", svnconflict_options_prop, {0}, N_ - ("List options for resolving a property conflict at path.\n" + { "options-prop", svnconflict_options_prop, {0}, {N_( + "List options for resolving a property conflict at path.\n" "usage: options-prop PATH\n" - "\n" + "\n"), N_( " List property conflict resolution options at PATH, one per line.\n" " Each line contains a numeric option ID, a colon, and a description.\n" " If PATH is not in conflict, the exit code will be 1, and 0 otherwise.\n" - ""), + )}, {0}, }, - { "options-tree", svnconflict_options_tree, {0}, N_ - ("List options for resolving a tree conflict at path.\n" + { "options-tree", svnconflict_options_tree, {0}, {N_( + "List options for resolving a tree conflict at path.\n" "usage: options-tree PATH\n" - "\n" + "\n"), N_( " List tree conflict resolution options at PATH, one per line.\n" " Each line contains a numeric option ID, a colon, and a description.\n" " If PATH is not in conflict, the exit code will be 1, and 0 otherwise.\n" - ""), + )}, {0}, }, - { "resolve-text", svnconflict_resolve_text, {0}, N_ - ("Resolve the text conflict at path.\n" + { "resolve-text", svnconflict_resolve_text, {0}, {N_( + "Resolve the text conflict at path.\n" "usage: resolve-text OPTION_ID PATH\n" - "\n" + "\n"), N_( " Resolve the text conflict at PATH with a given resolution option.\n" " If PATH is not in conflict, the exit code will be 1, and 0 otherwise.\n" - ""), + )}, {0}, }, - { "resolve-prop", svnconflict_resolve_prop, {0}, N_ - ("Resolve the property conflict at path.\n" + { "resolve-prop", svnconflict_resolve_prop, {0}, {N_( + "Resolve the property conflict at path.\n" "usage: resolve-prop PROPNAME OPTION_ID PATH\n" - "\n" + "\n"), N_( " Resolve conflicted property PROPNAME at PATH with a given resolution option.\n" " If PATH is not in conflict, the exit code will be 1, and 0 otherwise.\n" - ""), + )}, {0}, }, - { "resolve-tree", svnconflict_resolve_tree, {0}, N_ - ("Resolve the tree conflict at path.\n" + { "resolve-tree", svnconflict_resolve_tree, {0}, {N_( + "Resolve the tree conflict at path.\n" "usage: resolve-tree OPTION_ID PATH\n" - "\n" + "\n"), N_( " Resolve the tree conflict at PATH with a given resolution option.\n" " If PATH is not in conflict, the exit code will be 1, and 0 otherwise.\n" - ""), + )}, {0}, }, - { NULL, NULL, {0}, NULL, {0} } + { NULL, NULL, {0}, {NULL}, {0} } }; /* Version compatibility check */ @@ -297,7 +298,7 @@ svnconflict_help(apr_getopt_t *os, void *baton, apr_pool_t *pool) SVN_ERR(svn_ra_print_modules(version_footer, pool)); } - SVN_ERR(svn_opt_print_help4(os, + SVN_ERR(svn_opt_print_help5(os, "svnconflict", /* ### erm, derive somehow? */ opt_state ? opt_state->version : FALSE, FALSE, /* quiet */ @@ -368,12 +369,12 @@ svnconflict_list(apr_getopt_t *os, void *baton, apr_pool_t *pool) &conflict, local_abspath, ctx, pool)); if (text_conflicted) - svn_cmdline_printf(pool, "text-conflict\n"); + SVN_ERR(svn_cmdline_printf(pool, "text-conflict\n")); for (i = 0; i < props_conflicted->nelts; i++) { const char *propname = APR_ARRAY_IDX(props_conflicted, i, const char *); - svn_cmdline_printf(pool, "prop-conflict: %s\n", propname); + SVN_ERR(svn_cmdline_printf(pool, "prop-conflict: %s\n", propname)); } if (tree_conflicted) @@ -385,14 +386,14 @@ svnconflict_list(apr_getopt_t *os, void *baton, apr_pool_t *pool) &local_change, conflict, ctx, pool, pool)); - svn_cmdline_printf(pool, "tree-conflict: %s %s\n", - incoming_change, local_change); + SVN_ERR(svn_cmdline_printf(pool, "tree-conflict: %s %s\n", + incoming_change, local_change)); } return SVN_NO_ERROR; } -static void +static svn_error_t * print_conflict_options(apr_array_header_t *options, apr_pool_t *pool) { int i; @@ -406,8 +407,9 @@ print_conflict_options(apr_array_header_t *options, apr_pool_t *pool) option = APR_ARRAY_IDX(options, i, svn_client_conflict_option_t *); id = svn_client_conflict_option_get_id(option); label = svn_client_conflict_option_get_label(option, pool); - svn_cmdline_printf(pool, "%d: %s\n", id, label); + SVN_ERR(svn_cmdline_printf(pool, "%d: %s\n", id, label)); } + return SVN_NO_ERROR; } /* This implements the `svn_opt_subcommand_t' interface. */ @@ -438,7 +440,7 @@ svnconflict_options_text(apr_getopt_t *os, void *baton, apr_pool_t *pool) SVN_ERR(svn_client_conflict_text_get_resolution_options(&options, conflict, ctx, pool, pool)); - print_conflict_options(options, pool); + SVN_ERR(print_conflict_options(options, pool)); return SVN_NO_ERROR; } @@ -471,7 +473,7 @@ svnconflict_options_prop(apr_getopt_t *os, void *baton, apr_pool_t *pool) SVN_ERR(svn_client_conflict_prop_get_resolution_options(&options, conflict, ctx, pool, pool)); - print_conflict_options(options, pool); + SVN_ERR(print_conflict_options(options, pool)); return SVN_NO_ERROR; } @@ -505,7 +507,7 @@ svnconflict_options_tree(apr_getopt_t *os, void *baton, apr_pool_t *pool) SVN_ERR(svn_client_conflict_tree_get_resolution_options(&options, conflict, ctx, pool, pool)); - print_conflict_options(options, pool); + SVN_ERR(print_conflict_options(options, pool)); return SVN_NO_ERROR; } @@ -640,7 +642,7 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) apr_array_header_t *received_opts; svnconflict_cmd_baton_t command_baton; int i; - const svn_opt_subcommand_desc2_t *subcommand = NULL; + const svn_opt_subcommand_desc3_t *subcommand = NULL; svn_auth_baton_t *ab; svn_config_t *cfg_config; apr_hash_t *cfg_hash; @@ -741,7 +743,7 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) just typos/mistakes. Whatever the case, the subcommand to actually run is svnconflict_help(). */ if (opt_state.help) - subcommand = svn_opt_get_canonical_subcommand2(svnconflict_cmd_table, + subcommand = svn_opt_get_canonical_subcommand3(svnconflict_cmd_table, "help"); /* If we're not running the `help' subcommand, then look for a @@ -753,8 +755,8 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) if (opt_state.version) { /* Use the "help" subcommand to handle the "--version" option. */ - static const svn_opt_subcommand_desc2_t pseudo_cmd = - { "--version", svnconflict_help, {0}, "", + static const svn_opt_subcommand_desc3_t pseudo_cmd = + { "--version", svnconflict_help, {0}, {""}, {opt_version, /* must accept its own option */ opt_config_dir /* all commands accept this */ } }; @@ -777,7 +779,7 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) SVN_ERR(svn_utf_cstring_to_utf8(&first_arg, os->argv[os->ind++], pool)); - subcommand = svn_opt_get_canonical_subcommand2(svnconflict_cmd_table, + subcommand = svn_opt_get_canonical_subcommand3(svnconflict_cmd_table, first_arg); if (subcommand == NULL) { @@ -804,12 +806,12 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) if (opt_id == 'h' || opt_id == '?') continue; - if (! svn_opt_subcommand_takes_option3(subcommand, opt_id, + if (! svn_opt_subcommand_takes_option4(subcommand, opt_id, svnconflict_global_options)) { const char *optstr; const apr_getopt_option_t *badopt = - svn_opt_get_option_from_code2(opt_id, svnconflict_options, + svn_opt_get_option_from_code3(opt_id, svnconflict_options, subcommand, pool); svn_opt_format_option(&optstr, badopt, FALSE, pool); if (subcommand->name[0] == '-') diff --git a/tools/client-side/svnviewspec_test.py b/tools/client-side/svnviewspec_test.py new file mode 100755 index 0000000..ad98b15 --- /dev/null +++ b/tools/client-side/svnviewspec_test.py @@ -0,0 +1,428 @@ +#!/usr/bin/env python +# +# svnviewspec_test.py: testing the 'svn-viewspec.py' tool. +# +# Execute these tests using 'pytest' (pytest.org): +# py.test svnviewspec_test.py +# +# Subversion is a tool for revision control. +# See http://subversion.apache.org for more information. +# +# ==================================================================== +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +###################################################################### + + +import sys +import os.path +import tempfile + +sys.path.append(os.path.abspath(os.path.realpath(__file__))) + +svn_viewspec = __import__("svn-viewspec") +__SCRIPTNAME__ = 'svn-viewspec.py' + + +######################################################################### +# mock the 'system' call +os_system_lines = [] + +def my_os_system(str): + os_system_lines.append(str) + +def setup_function(function): + global os_system_lines + os_system_lines = [] + +######################################################################### + +def perform_viewspec(args): + return svn_viewspec.main(my_os_system, [__SCRIPTNAME__] + args) + +def test_that_viewspec_does_checkout_for_its_own_inline_example(capsys): + + spec = """Format: 1 +Url: http://svn.apache.org/r/a/s +Revision: 36 + +trunk/** +branches/1.5.x/** +branches/1.6.x/** +README +branches/1.4.x/STATUS +branches/1.4.x/s/tests/cmdline/~ +""" + + perform_viewspec( + ["checkout", (make_temp_file_containing(spec)), "a/b"]) + sys_out_lines, sys_err_lines = capsys.readouterr() + + expected = \ +"""svn checkout "http://svn.apache.org/r/a/s" "a/b" --depth=empty --revision=36 +svn update "a/b/README" --set-depth=empty --revision=36 +svn update "a/b/branches" --set-depth=empty --revision=36 +svn update "a/b/branches/1.4.x" --set-depth=empty --revision=36 +svn update "a/b/branches/1.4.x/STATUS" --set-depth=empty --revision=36 +svn update "a/b/branches/1.4.x/s" --set-depth=empty --revision=36 +svn update "a/b/branches/1.4.x/s/tests" --set-depth=empty --revision=36 +svn update "a/b/branches/1.4.x/s/tests/cmdline" --set-depth=files --revision=36 +svn update "a/b/branches/1.5.x" --set-depth=infinity --revision=36 +svn update "a/b/branches/1.6.x" --set-depth=infinity --revision=36 +svn update "a/b/trunk" --set-depth=infinity --revision=36""" + + all_the_lines_should_be_the_same(expected, os_system_lines) + + all_the_lines_should_be_the_same([], sys_err_lines) + all_the_lines_should_be_the_same([], sys_out_lines) + + +def test_that_viewspec_does_checkout_for_a_tilde_at_root_case(capsys): + + spec = """Format: 1 +Url: http://svn.apache.org/repos/asf/svn + +~ +""" + + perform_viewspec( + ["checkout", (make_temp_file_containing(spec)), "a/b"]) + sys_out_lines, sys_err_lines = capsys.readouterr() + + expected = \ +"""svn checkout "http://svn.apache.org/repos/asf/svn" "a/b" --depth=files""" + + # print ">>>" + "\n".join(os_system_lines) + "<<<" + + all_the_lines_should_be_the_same(expected, os_system_lines) + + all_the_lines_should_be_the_same([], sys_err_lines) + all_the_lines_should_be_the_same([], sys_out_lines) + + +def test_that_viewspec_does_checkout_a_splat_at_root_case(capsys): + + spec = """Format: 1 +Url: http://svn.apache.org/r/a/svn + +* +""" + + perform_viewspec( + ["checkout", (make_temp_file_containing(spec)), "a/b"]) + sys_out_lines, sys_err_lines = capsys.readouterr() + + expected = \ +"""svn checkout "http://svn.apache.org/r/a/svn" "a/b" --depth=immediates""" + + # print ">>>" + "\n".join(os_system_lines) + "<<<" + + all_the_lines_should_be_the_same(expected, os_system_lines) + + all_the_lines_should_be_the_same([], sys_err_lines) + all_the_lines_should_be_the_same([], sys_out_lines) + + +def test_that_viewspec_does_checkout_an_infinity_from_root_case(capsys): + + spec = """Format: 1 +Url: http://svn.apache.org/r/a/s + +** +""" + + perform_viewspec( + ["checkout", (make_temp_file_containing(spec)), "a/b"]) + sys_out_lines, sys_err_lines = capsys.readouterr() + + expected = \ +"""svn checkout "http://svn.apache.org/r/a/s" "a/b" --depth=infinity""" + + # print ">>>" + "\n".join(os_system_lines) + "<<<" + + all_the_lines_should_be_the_same(expected, os_system_lines) + + all_the_lines_should_be_the_same([], sys_err_lines) + all_the_lines_should_be_the_same([], sys_out_lines) + + +def test_that_viewspec_does_checkout_for_a_splat_n_tilde_in_a_subdir_case(capsys): + spec = """Format: 1 +Url: http://svn.apache.org/repos/asf/svn + +branches/foo/* +branches/bar/~ +""" + + perform_viewspec( + ["checkout", (make_temp_file_containing(spec)), "a/b"]) + sys_out_lines, sys_err_lines = capsys.readouterr() + + expected = \ +"""svn checkout "http://svn.apache.org/repos/asf/svn" "a/b" --depth=empty +svn update "a/b/branches" --set-depth=empty +svn update "a/b/branches/bar" --set-depth=files +svn update "a/b/branches/foo" --set-depth=immediates""" + + all_the_lines_should_be_the_same(expected, os_system_lines) + + all_the_lines_should_be_the_same([], sys_err_lines) + all_the_lines_should_be_the_same([], sys_out_lines) + + +def test_that_viewspec_does_examine_for_its_own_inline_example2(capsys): + + spec = """Format: 1 +Url: http://svn.apache.org/repos/asf/subversion +Revision: 36366 + +trunk/** +branches/1.5.x/** +branches/1.6.x/** +README +branches/1.4.x/STATUS +branches/1.4.x/subversion/tests/cmdline/~ +""" + + perform_viewspec( + ["examine", (make_temp_file_containing(spec)), "a/b"]) + sys_out_lines, sys_err_lines = capsys.readouterr() + + all_the_lines_should_be_the_same([], os_system_lines) + + expected = \ + """Path: (depth=empty) + Path: README (depth=empty) + Path: branches (depth=empty) + Path: 1.4.x (depth=empty) + Path: STATUS (depth=empty) + Path: subversion (depth=empty) + Path: tests (depth=empty) + Path: cmdline (depth=files) + Path: 1.5.x (depth=infinity) + Path: 1.6.x (depth=infinity) + Path: trunk (depth=infinity)""" + + all_the_lines_should_be_the_same(expected, sys_err_lines) + + expected = \ + """Url: http://svn.apache.org/repos/asf/subversion +Revision: 36366 + +""" + + all_the_lines_should_be_the_same(expected, sys_out_lines) + + +def test_that_viewspec_prints_help(capsys): + + rc = perform_viewspec(["help"]) + sys_out_lines, sys_err_lines = capsys.readouterr() + + assert 0 == rc + + all_the_lines_should_be_the_same([], sys_err_lines) + + expected = \ + """__SCRIPTNAME__: checkout utility for sparse Subversion working copies + +Usage: 1. __SCRIPTNAME__ checkout VIEWSPEC-FILE TARGET-DIR + 2. __SCRIPTNAME__ examine VIEWSPEC-FILE + 3. __SCRIPTNAME__ help + 4. __SCRIPTNAME__ help-format + +VIEWSPEC-FILE is the path of a file whose contents describe a +Subversion sparse checkouts layout, or '-' if that description should +be read from stdin. TARGET-DIR is the working copy directory created +by this script as it checks out the specified layout. + +1. Parse VIEWSPEC-FILE and execute the necessary 'svn' command-line + operations to build out a working copy tree at TARGET-DIR. + +2. Parse VIEWSPEC-FILE and dump out a human-readable representation of + the tree described in the specification. + +3. Show this usage message. + +4. Show information about the file format this program expects. + """.replace("__SCRIPTNAME__", __SCRIPTNAME__) + + all_the_lines_should_be_the_same(expected, sys_out_lines) + + +def test_that_viewspec_prints_unknown_subcommand(capsys): + + rc = perform_viewspec(["helppppppppp"]) + sys_out_lines, sys_err_lines = capsys.readouterr() + + assert 1 == rc + + all_the_lines_should_be_the_same([], sys_out_lines) + + expected = \ + """__SCRIPTNAME__: checkout utility for sparse Subversion working copies + +Usage: 1. __SCRIPTNAME__ checkout VIEWSPEC-FILE TARGET-DIR + 2. __SCRIPTNAME__ examine VIEWSPEC-FILE + 3. __SCRIPTNAME__ help + 4. __SCRIPTNAME__ help-format + +VIEWSPEC-FILE is the path of a file whose contents describe a +Subversion sparse checkouts layout, or '-' if that description should +be read from stdin. TARGET-DIR is the working copy directory created +by this script as it checks out the specified layout. + +1. Parse VIEWSPEC-FILE and execute the necessary 'svn' command-line + operations to build out a working copy tree at TARGET-DIR. + +2. Parse VIEWSPEC-FILE and dump out a human-readable representation of + the tree described in the specification. + +3. Show this usage message. + +4. Show information about the file format this program expects. + +ERROR: Unknown subcommand "helppppppppp".""".replace("__SCRIPTNAME__", __SCRIPTNAME__) + + all_the_lines_should_be_the_same(expected, sys_err_lines) + + +def test_that_viewspec_prints_help_format(capsys): + + rc = perform_viewspec(["help-format"]) + sys_out_lines, sys_err_lines = capsys.readouterr() + + assert 1 == rc + + # print ">>>" + "\n".join(sys_out_lines) + "<<<<" + + expected = \ + """Viewspec File Format +==================== + +The viewspec file format used by this tool is a collection of headers +(using the typical one-per-line name:value syntax), followed by an +empty line, followed by a set of one-per-line rules. + +The headers must contain at least the following: + + Format - version of the viewspec format used throughout the file + Url - base URL applied to all rules; tree checkout location + +The following headers are optional: + + Revision - version of the tree items to checkout + +Following the headers and blank line separator are the path rules. +The rules are list of URLs -- relative to the base URL stated in the +headers -- with optional annotations to specify the desired working +copy depth of each item: + + PATH/** - checkout PATH and all its children to infinite depth + PATH/* - checkout PATH and its immediate children + PATH/~ - checkout PATH and its file children + PATH - checkout PATH non-recursively + +By default, the top-level directory (associated with the base URL) is +checked out with empty depth. You can override this using the special +rules '**', '*', and '~' as appropriate. + +It is not necessary to explicitly list the parent directories of each +path associated with a rule. If the parent directory of a given path +is not "covered" by a previous rule, it will be checked out with empty +depth. + +Examples +======== + +Here's a sample viewspec file: + + Format: 1 + Url: http://svn.apache.org/repos/asf/subversion + Revision: 36366 + + trunk/** + branches/1.5.x/** + branches/1.6.x/** + README + branches/1.4.x/STATUS + branches/1.4.x/subversion/tests/cmdline/~ + +You may wish to version your viewspec files. If so, you can use this +script in conjunction with 'svn cat' to fetch, parse, and act on a +versioned viewspec file: + + $ svn cat http://svn.example.com/specs/dev-spec.txt | + __SCRIPTNAME__ checkout - /path/to/target/directory + """.replace("__SCRIPTNAME__", __SCRIPTNAME__) + + all_the_lines_should_be_the_same(expected, sys_out_lines) + + all_the_lines_should_be_the_same([], sys_err_lines) + + +def test_that_viewspec_does_checkout_with_no_revision_specified(capsys): + + spec = """Format: 1 +Url: http://svn.apache.org/repos/asf/svn + +trunk/** +branches/1.5.x/** +branches/1.6.x/** +README +branches/1.4.x/STATUS +branches/1.4.x/s/tests/cmdline/~ +""" + + perform_viewspec( + ["checkout", (make_temp_file_containing(spec)), "a/b"]) + sys_out_lines, sys_err_lines = capsys.readouterr() + + expected = \ + """svn checkout "http://svn.apache.org/repos/asf/svn" "a/b" --depth=empty + svn update "a/b/README" --set-depth=empty + svn update "a/b/branches" --set-depth=empty + svn update "a/b/branches/1.4.x" --set-depth=empty + svn update "a/b/branches/1.4.x/STATUS" --set-depth=empty + svn update "a/b/branches/1.4.x/s" --set-depth=empty + svn update "a/b/branches/1.4.x/s/tests" --set-depth=empty + svn update "a/b/branches/1.4.x/s/tests/cmdline" --set-depth=files + svn update "a/b/branches/1.5.x" --set-depth=infinity + svn update "a/b/branches/1.6.x" --set-depth=infinity + svn update "a/b/trunk" --set-depth=infinity """ + + all_the_lines_should_be_the_same(expected, os_system_lines) + all_the_lines_should_be_the_same([], sys_err_lines) + all_the_lines_should_be_the_same([], sys_out_lines) + + +def all_the_lines_should_be_the_same(expected_lines, + actual_lines): + if not isinstance(expected_lines, list): + expected_lines = expected_lines.splitlines() + if not isinstance(actual_lines, list): + actual_lines = actual_lines.splitlines() + assert len(actual_lines) == len(expected_lines) + for i, line in enumerate(actual_lines): + assert line.strip() == expected_lines[i].strip() + + +def make_temp_file_containing(spec): + new_file, filename = tempfile.mkstemp() + os.write(new_file, spec) + os.close(new_file) + return filename diff --git a/tools/dev/svnmover/svnmover.c b/tools/dev/svnmover/svnmover.c index 8bc8b65..a7cffd7 100644 --- a/tools/dev/svnmover/svnmover.c +++ b/tools/dev/svnmover/svnmover.c @@ -2436,7 +2436,7 @@ do_put_file(svn_branch__txn_t *txn, else SVN_ERR(svn_stream_for_stdin2(&src, FALSE, scratch_pool)); - svn_stringbuf_from_stream(&text, src, 0, scratch_pool); + SVN_ERR(svn_stringbuf_from_stream(&text, src, 0, scratch_pool)); } payload = svn_element__payload_create_file(props, text, scratch_pool); @@ -4042,7 +4042,7 @@ display_version(apr_getopt_t *os, svn_boolean_t _quiet, apr_pool_t *pool) version_footer = svn_stringbuf_create(ra_desc_start, pool); SVN_ERR(svn_ra_print_modules(version_footer, pool)); - SVN_ERR(svn_opt_print_help4(NULL, "svnmover", TRUE, _quiet, FALSE, + SVN_ERR(svn_opt_print_help5(NULL, "svnmover", TRUE, _quiet, FALSE, version_footer->data, NULL, NULL, NULL, NULL, NULL, pool)); diff --git a/tools/dev/svnraisetreeconflict/svnraisetreeconflict.c b/tools/dev/svnraisetreeconflict/svnraisetreeconflict.c index 65825d5..a68b5d2 100644 --- a/tools/dev/svnraisetreeconflict/svnraisetreeconflict.c +++ b/tools/dev/svnraisetreeconflict/svnraisetreeconflict.c @@ -52,7 +52,7 @@ static svn_error_t * version(apr_pool_t *pool) { - return svn_opt_print_help4(NULL, "svnraisetreeconflict", TRUE, FALSE, FALSE, + return svn_opt_print_help5(NULL, "svnraisetreeconflict", TRUE, FALSE, FALSE, NULL, NULL, NULL, NULL, NULL, NULL, pool); } diff --git a/tools/dev/unix-build/Makefile.svn b/tools/dev/unix-build/Makefile.svn index 2c0561c..91aa899 100644 --- a/tools/dev/unix-build/Makefile.svn +++ b/tools/dev/unix-build/Makefile.svn @@ -45,6 +45,7 @@ EXCLUSIVE_WC_LOCKS ?= 1 USE_HTTPV1 ?= no USE_AUTHZ_SHORT_CIRCUIT ?= no RAMDISK ?= /ramdisk +MAKE_JOBS ?= 4 PWD = $(shell pwd) UNAME = $(shell uname) @@ -71,6 +72,12 @@ endif # 2.2 endif # 2.3 endif # 2.4 +ifeq ($(UNAME),OpenBSD) +# Pick the correct base compiler (ie. clang rather than ancient gcc 4.2.1) +CC = cc +CXX = c++ +endif + TAG ?= none ifeq ($(TAG),none) BRANCH ?= trunk @@ -170,18 +177,19 @@ FETCH_CMD = wget -c SUBVERSION_REPOS_URL = https://svn.apache.org/repos/asf/subversion BDB_URL = http://download.oracle.com/berkeley-db/$(BDB_DIST) APR_URL = https://svn.apache.org/repos/asf/apr/apr -APR_ICONV_URL = https://www.apache.org/dist/apr/$(APR_ICONV_DIST) +APR_ICONV_URL = https://archive.apache.org/dist/apr/$(APR_ICONV_DIST) GNU_ICONV_URL = https://ftp.gnu.org/pub/gnu/libiconv/$(GNU_ICONV_DIST) APR_UTIL_URL = https://svn.apache.org/repos/asf/apr/apr-util HTTPD_URL = https://archive.apache.org/dist/httpd/$(HTTPD_DIST) -NEON_URL = http://webdav.org/neon/$(NEON_DIST) +#NEON_URL = http://webdav.org/neon/$(NEON_DIST) +NEON_URL = http://ftp.openbsd.org/pub/OpenBSD/distfiles/$(NEON_DIST) SERF_URL = https://svn.apache.org/repos/asf/serf/tags/$(SERF_VER) SERF_OLD_URL = https://svn.apache.org/repos/asf/serf/tags/$(SERF_OLD_VER) SQLITE_URL = https://www.sqlite.org/2017/$(SQLITE_DIST) CYRUS_SASL_URL = ftp://ftp.andrew.cmu.edu/pub/cyrus-mail/$(CYRUS_SASL_DIST) LIBMAGIC_URL = ftp://ftp.astron.com/pub/file/$(LIBMAGIC_DIST) RUBY_URL = https://cache.ruby-lang.org/pub/ruby/2.4/$(RUBY_DIST) -BZ2_URL = http://bzip.org/$(BZ2_VER)/$(BZ2_DIST) +BZ2_URL = https://ftp.openbsd.org/pub/OpenBSD/distfiles/$(BZ2_DIST) PYTHON_URL = https://python.org/ftp/python/$(PYTHON_VER)/$(PYTHON_DIST) JUNIT_URL = https://downloads.sourceforge.net/project/junit/junit/$(JUNIT_VER)/$(JUNIT_DIST) GETTEXT_URL = https://ftp.gnu.org/pub/gnu/gettext/$(GETTEXT_DIST) @@ -238,6 +246,10 @@ endif # We need this to make sure some targets below pick up the right libraries LD_LIBRARY_PATH=$(PREFIX)/apr/lib:$(PREFIX)/gettext/lib:$(PREFIX)/iconv/lib:$(PREFIX)/bdb/lib:$(PREFIX)/neon/lib:$(PREFIX)/serf/lib:$(PREFIX)/sqlite/lib:$(PREFIX)/cyrus-sasl/lib:$(PREFIX)/iconv/lib:$(PREFIX)/libmagic/lib:$(PREFIX)/ruby/lib:$(PREFIX)/python/lib:$(PREFIX)/svn-$(WC)/lib +# We need this to make sure some targets below pick up the right pkg-config files +PKG_CONFIG_PATH=$(PREFIX)/apr/lib/pkgconfig:$(PREFIX)/neon/lib/pkgconfig:$(PREFIX)/serf/lib/pkgconfig:$(PREFIX)/sqlite/lib/pkgconfig:$(PREFIX)/ruby/lib/pkgconfig:$(PREFIX)/python/lib/pkgconfig:$(PREFIX)/lz4/lib/pkgconfig + + ####################################################################### # Main targets. ####################################################################### @@ -331,6 +343,7 @@ $(BDB_OBJDIR)/.retrieved: $(DISTDIR)/$(BDB_DIST) $(BDB_OBJDIR)/.configured: $(BDB_OBJDIR)/.retrieved cd $(BDB_SRCDIR)/build_unix \ && env CFLAGS="-g $(PROFILE_CFLAGS)" GREP="`which grep`" \ + CC=$(CC) CXX=$(CXX) \ ../dist/configure \ --prefix=$(PREFIX)/bdb \ --enable-debug @@ -338,7 +351,7 @@ $(BDB_OBJDIR)/.configured: $(BDB_OBJDIR)/.retrieved # compile bdb $(BDB_OBJDIR)/.compiled: $(BDB_OBJDIR)/.configured - (cd $(BDB_SRCDIR)/build_unix && env MAKEFLAGS= make) + (cd $(BDB_SRCDIR)/build_unix && env MAKEFLAGS= make -j${MAKE_JOBS}) touch $@ # install bdb @@ -388,6 +401,8 @@ $(APR_OBJDIR)/.configured: $(APR_OBJDIR)/.retrieved $(BDB_OBJDIR)/.installed cd $(APR_SRCDIR) && ./buildconf cd $(APR_OBJDIR) \ && env CFLAGS="-O0 -g $(PROFILE_CFLAGS)" GREP="`which grep`" \ + PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) \ + CC=$(CC) CXX=$(CXX) \ $(APR_SRCDIR)/configure \ --prefix=$(PREFIX)/apr \ --enable-maintainer-mode \ @@ -397,7 +412,7 @@ $(APR_OBJDIR)/.configured: $(APR_OBJDIR)/.retrieved $(BDB_OBJDIR)/.installed # compile apr $(APR_OBJDIR)/.compiled: $(APR_OBJDIR)/.configured - (cd $(APR_OBJDIR) && env MAKEFLAGS= make) + (cd $(APR_OBJDIR) && env MAKEFLAGS= make -j${MAKE_JOBS}) touch $@ # install apr @@ -436,7 +451,9 @@ $(APR_ICONV_OBJDIR)/.configured: $(APR_ICONV_OBJDIR)/.retrieved \ $(APR_OBJDIR)/.installed cd $(APR_ICONV_OBJDIR) \ && env CFLAGS="-g $(PROFILE_CFLAGS) -DAPR_POOL_DEBUG" \ + CC=$(CC) CXX=$(CXX) \ GREP="`which grep`" \ + PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) \ $(APR_ICONV_SRCDIR)/configure \ --prefix=$(PREFIX)/apr \ --with-apr=$(PREFIX)/apr @@ -445,7 +462,7 @@ $(APR_ICONV_OBJDIR)/.configured: $(APR_ICONV_OBJDIR)/.retrieved \ # compile apr-iconv $(APR_ICONV_OBJDIR)/.compiled: $(APR_ICONV_OBJDIR)/.configured (cd $(APR_ICONV_OBJDIR) \ - && env MAKEFLAGS= make CPPFLAGS="-D_OSD_POSIX" CFLAGS="-g -O0 $(PROFILE_CFLAGS)") + && env MAKEFLAGS= make CPPFLAGS="-D_OSD_POSIX" CFLAGS="-g -O0 $(PROFILE_CFLAGS)" -j${MAKE_JOBS}) touch $@ # install apr-iconv @@ -520,6 +537,7 @@ $(GNU_ICONV_OBJDIR)/.configured: $(GNU_ICONV_OBJDIR)/.retrieved ${MAKE} -f Makefile.devel lib/aliases.h cd $(GNU_ICONV_OBJDIR) \ && env CFLAGS="-g $(PROFILE_CFLAGS)" GREP="`which grep`"\ + PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) \ $(GNU_ICONV_SRCDIR)/configure \ --prefix=$(PREFIX)/iconv \ --enable-extra-encodings @@ -527,7 +545,7 @@ $(GNU_ICONV_OBJDIR)/.configured: $(GNU_ICONV_OBJDIR)/.retrieved # compile gnu-iconv $(GNU_ICONV_OBJDIR)/.compiled: $(GNU_ICONV_OBJDIR)/.configured - (cd $(GNU_ICONV_OBJDIR) && env MAKEFLAGS= make) + (cd $(GNU_ICONV_OBJDIR) && env MAKEFLAGS= make -j${MAKE_JOBS}) touch $@ # install gnu-iconv @@ -590,7 +608,9 @@ $(APR_UTIL_OBJDIR)/.configured: $(APR_UTIL_OBJDIR)/.retrieved \ cd $(APR_UTIL_SRCDIR) && ./buildconf --with-apr=$(APR_SRCDIR) cd $(APR_UTIL_OBJDIR) \ && env LD_LIBRARY_PATH=$(PREFIX)/bdb/lib \ + PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) \ CFLAGS="-O0 -g $(PROFILE_CFLAGS) -DAPR_POOL_DEBUG" \ + CC=$(CC) CXX=$(CXX) \ GREP="`which grep`" \ $(APR_UTIL_SRCDIR)/configure \ --prefix=$(PREFIX)/apr \ @@ -602,7 +622,7 @@ $(APR_UTIL_OBJDIR)/.configured: $(APR_UTIL_OBJDIR)/.retrieved \ # compile apr-util $(APR_UTIL_OBJDIR)/.compiled: $(APR_UTIL_OBJDIR)/.configured - (cd $(APR_UTIL_OBJDIR) && env MAKEFLAGS= make) + (cd $(APR_UTIL_OBJDIR) && env MAKEFLAGS= make -j${MAKE_JOBS}) touch $@ # install apr-util @@ -681,6 +701,13 @@ $(HTTPD_OBJDIR)/acinclude.diff: echo >>$@.tmp ' AC_CHECK_FUNCS(SSL_set_state)' mv -f $@.tmp $@ +# fix build without APR_HAS_THREADS (broken by r1750836) +ifneq ($(THREADING),yes) +HTTPD_REVERT_1750836_CMD = (cd $(HTTPD_SRCDIR)/modules/proxy && svn diff -c-1750836 https://svn.apache.org/repos/asf/httpd/httpd/branches/2.2.x/modules/proxy/proxy_util.c | patch) +else +HTTPD_REVERT_1750836_CMD = true +endif + # retrieve httpd $(HTTPD_OBJDIR)/.retrieved: $(DISTDIR)/$(HTTPD_DIST) \ $(HTTPD_OBJDIR)/chil-engine.diff $(HTTPD_OBJDIR)/ssl-set-state.diff \ @@ -709,6 +736,7 @@ $(HTTPD_OBJDIR)/.retrieved: $(DISTDIR)/$(HTTPD_DIST) \ < $(HTTPD_SRCDIR)/modules/ssl/${f}.orig \ > $(HTTPD_SRCDIR)/modules/ssl/${f};\ ) + $(HTTPD_REVERT_1750836_CMD) touch $@ # configure httpd @@ -717,7 +745,9 @@ $(HTTPD_OBJDIR)/.configured: $(HTTPD_OBJDIR)/.retrieved \ cd $(HTTPD_SRCDIR) && ./buildconf cd $(HTTPD_OBJDIR) \ && env CFLAGS="-g $(PROFILE_CFLAGS) -DAPR_POOL_DEBUG" \ + CC=$(CC) CXX=$(CXX) \ GREP="`which grep`" \ + PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) \ $(HTTPD_SRCDIR)/configure \ --prefix=$(PREFIX)/httpd \ --enable-maintainer-mode \ @@ -731,7 +761,7 @@ $(HTTPD_OBJDIR)/.configured: $(HTTPD_OBJDIR)/.retrieved \ # compile httpd $(HTTPD_OBJDIR)/.compiled: $(HTTPD_OBJDIR)/.configured - (cd $(HTTPD_OBJDIR) && env MAKEFLAGS= make) + (cd $(HTTPD_OBJDIR) && env MAKEFLAGS= make -j${MAKE_JOBS}) touch $@ # install httpd @@ -802,6 +832,8 @@ $(NEON_OBJDIR)/.configured: $(NEON_OBJDIR)/.retrieved fi cd $(NEON_OBJDIR) \ && env CFLAGS="-g $(PROFILE_CFLAGS)" GREP="`which grep`" \ + CC=$(CC) CXX=$(CXX) \ + PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) \ $(NEON_SRCDIR)/configure \ PATH=$(NEON_OBJDIR):$$PATH \ --prefix=$(PREFIX)/neon \ @@ -812,7 +844,7 @@ $(NEON_OBJDIR)/.configured: $(NEON_OBJDIR)/.retrieved # compile neon $(NEON_OBJDIR)/.compiled: $(NEON_OBJDIR)/.configured - (cd $(NEON_OBJDIR) && env MAKEFLAGS= make) + (cd $(NEON_OBJDIR) && env MAKEFLAGS= make -j${MAKE_JOBS}) touch $@ # install neon @@ -860,11 +892,13 @@ $(SERF_OBJDIR)/.retrieved: $(SERF_OBJDIR)/.compiled: $(SERF_OBJDIR)/.retrieved \ $(APR_UTIL_OBJDIR)/.installed cd $(SERF_SRCDIR) && \ - scons DEBUG=1 \ + scons -j${MAKE_JOBS} DEBUG=1 \ CFLAGS="-O0 -g $(PROFILE_CFLAGS) -DAPR_POOL_DEBUG" \ + CC=$(CC) CXX=$(CXX) \ APR=$(PREFIX)/apr \ APU=$(PREFIX)/apr \ - PREFIX=$(PREFIX)/serf + PREFIX=$(PREFIX)/serf \ + PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) touch $@ # install serf @@ -905,6 +939,7 @@ $(SERF_OLD_OBJDIR)/.compiled: $(SERF_OLD_OBJDIR)/.retrieved \ $(APR_UTIL_OBJDIR)/.installed cd $(SERF_OLD_SRCDIR) && \ env CFLAGS="-O0 -g $(PROFILE_CFLAGS) -DAPR_POOL_DEBUG" \ + CC=$(CC) CXX=$(CXX) \ ./serfmake --with-apr=$(PREFIX)/apr \ --prefix=$(PREFIX)/serf-old \ build @@ -956,6 +991,8 @@ endif $(SQLITE_OBJDIR)/.configured: $(SQLITE_OBJDIR)/.retrieved cd $(SQLITE_OBJDIR) \ && env CFLAGS="-g $(PROFILE_CFLAGS)" GREP="`which grep`" \ + PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) \ + CC=$(CC) CXX=$(CXX) \ $(SQLITE_SRCDIR)/configure \ --prefix=$(PREFIX)/sqlite \ $(THREADSAFE_FLAG) @@ -963,7 +1000,7 @@ $(SQLITE_OBJDIR)/.configured: $(SQLITE_OBJDIR)/.retrieved # compile sqlite $(SQLITE_OBJDIR)/.compiled: $(SQLITE_OBJDIR)/.configured - (cd $(SQLITE_OBJDIR) && env MAKEFLAGS= make) + (cd $(SQLITE_OBJDIR) && env MAKEFLAGS= make -j${MAKE_JOBS}) touch $@ # install sqlite @@ -1025,7 +1062,9 @@ $(CYRUS_SASL_OBJDIR)/.configured: $(CYRUS_SASL_OBJDIR)/.retrieved \ cd $(CYRUS_SASL_OBJDIR) \ && env CFLAGS="-g $(PROFILE_CFLAGS)" \ CPPFLAGS="-I/usr/include/kerberosV" \ + CC=$(CC) CXX=$(CXX) \ GREP="`which grep`" \ + PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) \ $(CYRUS_SASL_SRCDIR)/configure \ --with-dbpath=$(PREFIX)/cyrus-sasl/etc/sasldb2 \ --with-plugindir=$(PREFIX)/cyrus-sasl/lib/sasl2 \ @@ -1037,7 +1076,7 @@ $(CYRUS_SASL_OBJDIR)/.configured: $(CYRUS_SASL_OBJDIR)/.retrieved \ --prefix=$(PREFIX)/cyrus-sasl touch $@ -# compile cyrus-sasl +# compile cyrus-sasl (ignore MAKE_JOBS; multiple jobs cause random build failures) $(CYRUS_SASL_OBJDIR)/.compiled: $(CYRUS_SASL_OBJDIR)/.configured (cd $(CYRUS_SASL_OBJDIR) && env MAKEFLAGS= make) touch $@ @@ -1077,6 +1116,8 @@ $(LIBMAGIC_OBJDIR)/.retrieved: $(DISTDIR)/$(LIBMAGIC_DIST) $(LIBMAGIC_OBJDIR)/.configured: $(LIBMAGIC_OBJDIR)/.retrieved cd $(LIBMAGIC_OBJDIR) \ && env CFLAGS="-g $(PROFILE_CFLAGS)" GREP="`which grep`"\ + CC=$(CC) CXX=$(CXX) \ + PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) \ $(LIBMAGIC_SRCDIR)/configure \ --enable-fsect-man5 \ --prefix=$(PREFIX)/libmagic @@ -1084,7 +1125,7 @@ $(LIBMAGIC_OBJDIR)/.configured: $(LIBMAGIC_OBJDIR)/.retrieved # compile libmagic $(LIBMAGIC_OBJDIR)/.compiled: $(LIBMAGIC_OBJDIR)/.configured - (cd $(LIBMAGIC_OBJDIR) && env MAKEFLAGS= make) + (cd $(LIBMAGIC_OBJDIR) && env MAKEFLAGS= make -j${MAKE_JOBS}) touch $@ # install libmagic @@ -1111,13 +1152,54 @@ ruby-clean: $(DISTDIR)/$(RUBY_DIST): cd $(DISTDIR) && $(FETCH_CMD) $(RUBY_URL) +$(RUBY_OBJDIR)/openssl_missing.patch: + mkdir -p $(dir $@) + echo > $@.tmp 'Index: ext/openssl/openssl_missing.h' + echo >> $@.tmp '--- ext/openssl/openssl_missing.h.orig' + echo >> $@.tmp '+++ ext/openssl/openssl_missing.h' + echo >> $@.tmp '@@ -119,6 +119,9 @@ void ossl_HMAC_CTX_free(HMAC_CTX *);' + echo >> $@.tmp ' #if !defined(HAVE_X509_STORE_SET_EX_DATA)' + echo >> $@.tmp ' # define X509_STORE_set_ex_data(x, idx, data) \' + echo >> $@.tmp ' CRYPTO_set_ex_data(&(x)->ex_data, (idx), (data))' + echo >> $@.tmp '+#endif' + echo >> $@.tmp '+' + echo >> $@.tmp '+#if !defined(HAVE_X509_STORE_GET_EX_NEW_INDEX)' + echo >> $@.tmp ' # define X509_STORE_get_ex_new_index(l, p, newf, dupf, freef) \' + echo >> $@.tmp ' CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_X509_STORE, (l), (p), \' + echo >> $@.tmp ' (newf), (dupf), (freef))' + echo >> $@.tmp '@@ -192,6 +195,7 @@ void ossl_X509_REQ_get0_signature(const X509_REQ *, co' + echo >> $@.tmp ' #endif' + echo >> $@.tmp ' ' + echo >> $@.tmp ' #if !defined(HAVE_OPAQUE_OPENSSL)' + echo >> $@.tmp '+#if defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL' + echo >> $@.tmp ' #define IMPL_PKEY_GETTER(_type, _name) \' + echo >> $@.tmp ' static inline _type *EVP_PKEY_get0_##_type(EVP_PKEY *pkey) { \' + echo >> $@.tmp ' return pkey->pkey._name; }' + echo >> $@.tmp '@@ -243,6 +247,7 @@ IMPL_PKEY_GETTER(EC_KEY, ec)' + echo >> $@.tmp ' #undef IMPL_PKEY_GETTER' + echo >> $@.tmp ' #undef IMPL_KEY_ACCESSOR2' + echo >> $@.tmp ' #undef IMPL_KEY_ACCESSOR3' + echo >> $@.tmp '+#endif' + echo >> $@.tmp ' #endif /* HAVE_OPAQUE_OPENSSL */' + echo >> $@.tmp ' ' + echo >> $@.tmp ' #if defined(HAVE_AUTHENTICATED_ENCRYPTION) && !defined(EVP_CTRL_AEAD_GET_TAG)' + mv -f $@.tmp $@ + +ifeq ($(UNAME),OpenBSD) +RUBY_SSL_EX_NEW_DATA_PATCH = sed -i -e '/^have_func("X509_STORE_set_ex_data")$$/ { p; s/^.*$$/\have_func("X509_STORE_get_ex_new_index")/; }' +else +RUBY_SSL_EX_NEW_DATA_PATCH = true +endif + # retrieve ruby # -$(RUBY_OBJDIR)/.retrieved: $(DISTDIR)/$(RUBY_DIST) +$(RUBY_OBJDIR)/.retrieved: $(DISTDIR)/$(RUBY_DIST) $(RUBY_OBJDIR)/openssl_missing.patch $(call do_check_sha256,$(RUBY_DIST)) [ -d $(RUBY_OBJDIR) ] || mkdir -p $(RUBY_OBJDIR) tar -C $(SRCDIR) -zxf $(DISTDIR)/$(RUBY_DIST) -which ghead && sed -i -e "s/head -c/ghead -c/" $(RUBY_SRCDIR)/configure + $(RUBY_SSL_EX_NEW_DATA_PATCH) $(RUBY_SRCDIR)/ext/openssl/extconf.rb + cd $(RUBY_SRCDIR) && patch -p0 < $(RUBY_OBJDIR)/openssl_missing.patch touch $@ ifeq ($(THREADING),yes) @@ -1130,6 +1212,8 @@ endif $(RUBY_OBJDIR)/.configured: $(RUBY_OBJDIR)/.retrieved cd $(RUBY_OBJDIR) \ && env CFLAGS="-g $(PROFILE_CFLAGS)" GREP="`which grep`"\ + CC=$(CC) CXX=$(CXX) \ + PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) \ $(RUBY_SRCDIR)/configure \ --prefix=$(PREFIX)/ruby \ --enable-shared \ @@ -1140,7 +1224,7 @@ $(RUBY_OBJDIR)/.configured: $(RUBY_OBJDIR)/.retrieved --without-gmp touch $@ -# compile ruby +# compile ruby (ignore MAKE_JOBS; multiple jobs cause random build failures) $(RUBY_OBJDIR)/.compiled: $(RUBY_OBJDIR)/.configured (cd $(RUBY_OBJDIR) && env MAKEFLAGS= make) touch $@ @@ -1177,7 +1261,8 @@ $(BZ2_OBJDIR)/.retrieved: $(DISTDIR)/$(BZ2_DIST) # compile bz2 $(BZ2_OBJDIR)/.compiled: $(BZ2_OBJDIR)/.retrieved - (cd $(BZ2_SRCDIR) && env MAKEFLAGS= make CFLAGS="-g $(PROFILE_CFLAGS) -fPIC") + (cd $(BZ2_SRCDIR) && env MAKEFLAGS= make CC=$(CC) CXX=$(CXX) \ + CFLAGS="-g $(PROFILE_CFLAGS) -fPIC" -j${MAKE_JOBS}) touch $@ # install bz2 @@ -1237,9 +1322,11 @@ $(PYTHON_OBJDIR)/.configured: $(PYTHON_OBJDIR)/.retrieved \ $(BZ2_OBJDIR)/.installed cd $(PYTHON_OBJDIR) \ && env CFLAGS="-g $(PROFILE_CFLAGS)" GREP="`which grep`" \ + CC=$(CC) CXX=$(CXX) \ CPPFLAGS="-I$(PREFIX)/bz2/include" \ LDFLAGS="-Wl,-rpath=$(PREFIX)/python/lib -L$(PREFIX)/bz2/lib" \ LD_LIBRARY_PATH="$(LD_LIBRARY_PATH):$$LD_LIBRARY_PATH" \ + PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) \ $(PYTHON_SRCDIR)/configure \ --prefix=$(PREFIX)/python \ --enable-shared \ @@ -1253,7 +1340,7 @@ $(PYTHON_OBJDIR)/.compiled: $(PYTHON_OBJDIR)/.configured (cd $(PYTHON_OBJDIR) && \ env MAKEFLAGS= \ LD_LIBRARY_PATH="$(LD_LIBRARY_PATH):$$LD_LIBRARY_PATH" \ - make) + make -j${MAKE_JOBS}) touch $@ # install python @@ -1306,7 +1393,9 @@ $(GETTEXT_OBJDIR)/.retrieved: $(DISTDIR)/$(GETTEXT_DIST) $(GETTEXT_OBJDIR)/.configured: $(GETTEXT_OBJDIR)/.retrieved cd $(GETTEXT_SRCDIR) \ && env CFLAGS="-g $(PROFILE_CFLAGS)" GREP="`which grep`"\ + CC=$(CC) CXX=$(CXX) \ LDFLAGS="-L$(PREFIX)/iconv/lib" \ + PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) \ $(GETTEXT_SRCDIR)/configure \ --prefix=$(PREFIX)/gettext \ --with-libiconv-prefix=$(PREFIX)/iconv \ @@ -1324,7 +1413,7 @@ $(GETTEXT_OBJDIR)/.configured: $(GETTEXT_OBJDIR)/.retrieved # compile gettext $(GETTEXT_OBJDIR)/.compiled: $(GETTEXT_OBJDIR)/.configured - (cd $(GETTEXT_SRCDIR) && env MAKEFLAGS= make) + (cd $(GETTEXT_SRCDIR) && env MAKEFLAGS= make -j${MAKE_JOBS}) touch $@ # install gettext @@ -1365,7 +1454,8 @@ $(LZ4_OBJDIR)/.configured: $(LZ4_OBJDIR)/.retrieved # compile lz4 $(LZ4_OBJDIR)/.compiled: $(LZ4_OBJDIR)/.configured (cd $(LZ4_SRCDIR)/lib && \ - env MAKEFLAGS= $(MAKE) PREFIX=$(PREFIX)/lz4) + env MAKEFLAGS= $(MAKE) CC=$(CC) CXX=$(CXX) \ + -j${MAKE_JOBS} PREFIX=$(PREFIX)/lz4) touch $@ # install lz4 @@ -1467,6 +1557,7 @@ SERF_FLAG=--with-serf="$(PREFIX)/serf" # serf >= 1.3.0 is built with scons and no longer sets up rpath linker flags, # so we have to do that ourselves :( SERF_LDFLAG=-Wl,-rpath,$(PREFIX)/serf/lib -Wl,-rpath,$(PREFIX)/bdb/lib +LZ4_LDFLAG=-Wl,-rpath,$(PREFIX)/lz4/lib MOD_DAV_SVN=modules/svn-$(WC)/mod_dav_svn.so MOD_AUTHZ_SVN=modules/svn-$(WC)/mod_authz_svn.so MOD_DONTDOTHAT=modules/svn-$(WC)/mod_dontdothat.so @@ -1492,6 +1583,17 @@ SVN_WITH_HTTPD=--with-apxs="$(PREFIX)/httpd/bin/apxs" \ SVN_WITH_SASL=--with-sasl="$(PREFIX)/cyrus-sasl" endif +# On OpenBSD, MExtUtils -e ldopts outputs -L/usr/local/lib, which can +# cause us to link Perl bindings against the wrong set of SVN libraries. +# As a workaround, we patch the configure script after it has been generated. +ifeq ($(UNAME),OpenBSD) +SWIG_PL_INCLUDES_HACK= sed -i 's^\($$PERL -MExtUtils::Embed -e ccopts\)^\1 | sed -e s@-I/usr/local/include@@^' $(svn_builddir)/configure +SWIG_PL_LINK_HACK= sed -i 's^\($$PERL -MExtUtils::Embed -e ldopts\)^\1 | sed -e s@-L/usr/local/lib@@^' $(svn_builddir)/configure +else +SWIG_PL_INCLUDES_HACK=true +SWIG_PL_LINK_HACK=true +endif + $(SVN_OBJDIR)/.configured: $(SVN_OBJDIR)/.retrieved $(DISTDIR)/$(JUNIT_DIST) \ $(APR_OBJDIR)/.installed $(APR_UTIL_OBJDIR)/.installed \ $(BDB_OBJDIR)/.installed $(SQLITE_OBJDIR)/.installed \ @@ -1500,11 +1602,15 @@ $(SVN_OBJDIR)/.configured: $(SVN_OBJDIR)/.retrieved $(DISTDIR)/$(JUNIT_DIST) \ $(SERF_OBJDIR)/.installed $(SERF_OLD_OBJDIR)/.installed \ $(RUBY_OBJDIR)/.installed $(PYTHON_OBJDIR)/.installed cd $(SVN_SRCDIR) && ./autogen.sh + $(SWIG_PL_INCLUDES_HACK) + $(SWIG_PL_LINK_HACK) cd $(svn_builddir) && \ - env LDFLAGS="-L$(PREFIX)/neon/lib -L$(PREFIX)/apr/lib $(SERF_LDFLAG) -L$(PREFIX)/gettext/lib -L$(PREFIX)/iconv/lib" \ + env LDFLAGS="-L$(PREFIX)/neon/lib -L$(PREFIX)/apr/lib $(SERF_LDFLAG) $(LZ4_LDFLAG) -L$(PREFIX)/gettext/lib -L$(PREFIX)/iconv/lib" \ + CC=$(CC) CXX=$(CXX) \ CFLAGS="-I$(PREFIX)/gettext/include -DAPR_POOL_DEBUG" \ CXXFLAGS="-I$(PREFIX)/gettext/include -DAPR_POOL_DEBUG" \ LD_LIBRARY_PATH="$(LD_LIBRARY_PATH):$$LD_LIBRARY_PATH" \ + PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) \ GREP="`which grep`" \ PATH=$(PREFIX)/ruby/bin:$(PREFIX)/python/bin:$(PREFIX)/gettext/bin:$$PATH \ $(SVN_SRCDIR)/configure \ @@ -1533,7 +1639,7 @@ $(SVN_OBJDIR)/.configured: $(SVN_OBJDIR)/.retrieved $(DISTDIR)/$(JUNIT_DIST) \ # compile svn $(SVN_OBJDIR)/.compiled: $(SVN_OBJDIR)/.configured cd $(svn_builddir) \ - && env MAKEFLAGS= make EXTRA_CFLAGS="$(PROFILE_CFLAGS) $(W_NO_SYSTEM_HEADERS)" + && env MAKEFLAGS= make -j${MAKE_JOBS} EXTRA_CFLAGS="$(PROFILE_CFLAGS) $(W_NO_SYSTEM_HEADERS)" touch $@ # install svn @@ -1552,17 +1658,30 @@ $(SVN_OBJDIR)/.pre-generated-swig-cleaned: && env MAKEFLAGS= make clean-swig touch $@ + +# On OpenBSD, Perl's LDDLFLAGS include -L/usr/local/lib, which can cause +# us to link Perl bindings against the wrong set of SVN libraries. +# We manually fix up the generated Makefile.PL to work around this issue. +ifeq ($(UNAME),OpenBSD) +MAKEFILE_PL_LDDLFLAGS_HACK= sed -i 's@^WriteMakefile@$$config{LDDLFLAGS} =~ s+-L/usr/local/lib++; WriteMakefile@' \ + $(SVN_SRCDIR)/subversion/bindings/swig/perl/native/Makefile.PL +else +MAKEFILE_PL_LDDLFLAGS_HACK=true +endif + $(SVN_OBJDIR)/.bindings-compiled: $(SVN_OBJDIR)/.installed $(SVN_OBJDIR)/.pre-generated-swig-cleaned cd $(svn_builddir) \ && env LD_LIBRARY_PATH=$(LD_LIBRARY_PATH) \ - env MAKEFLAGS= make swig-py + env MAKEFLAGS= make -j${MAKE_JOBS} swig-py cd $(svn_builddir) && \ env PATH=$(PREFIX)/ruby/bin:$$PATH \ - LD_LIBRARY_PATH=$(LD_LIBRARY_PATH) env MAKEFLAGS= make swig-rb + LD_LIBRARY_PATH=$(LD_LIBRARY_PATH) env MAKEFLAGS= make -j${MAKE_JOBS} swig-rb if [ $(ENABLE_PERL_BINDINGS) = yes ]; then \ + cd $(svn_builddir) && make $(SVN_SRCDIR)/subversion/bindings/swig/perl/native/Makefile.PL; \ + $(MAKEFILE_PL_LDDLFLAGS_HACK); \ cd $(svn_builddir) \ && env LD_LIBRARY_PATH=$(LD_LIBRARY_PATH) \ - env MAKEFLAGS= make swig-pl; \ + env MAKEFLAGS= make -j${MAKE_JOBS} swig-pl; \ fi if [ $(ENABLE_JAVA_BINDINGS) = yes ]; then \ cd $(svn_builddir) \ @@ -1576,13 +1695,15 @@ $(SVN_OBJDIR)/.bindings-installed: $(SVN_OBJDIR)/.bindings-compiled env MAKEFLAGS= make install-swig-py cd $(svn_builddir) && \ env PATH=$(PREFIX)/ruby/bin:$$PATH \ - LD_LIBRARY_PATH=$(LD_LIBRARY_PATH) env MAKEFLAGS= make install-swig-rb + LD_LIBRARY_PATH=$(LD_LIBRARY_PATH) MAKEFLAGS= make install-swig-rb if [ $(ENABLE_PERL_BINDINGS) = yes ]; then \ cd $(svn_builddir) \ - && env MAKEFLAGS= make install-swig-pl-lib; \ - cd subversion/bindings/swig/perl/native \ - && perl Makefile.PL PREFIX="$(SVN_PREFIX)" \ - && env MAKEFLAGS= make install; \ + && env MAKEFLAGS= LD_LIBRARY_PATH=$(LD_LIBRARY_PATH) \ + make install-swig-pl-lib; \ + cd subversion/bindings/swig/perl/native \ + && perl Makefile.PL PREFIX="$(SVN_PREFIX)" \ + && env MAKEFLAGS= LD_LIBRARY_PATH=$(LD_LIBRARY_PATH) \ + make install; \ fi if [ $(ENABLE_JAVA_BINDINGS) = yes ]; then \ cd $(svn_builddir) \ @@ -1913,6 +2034,7 @@ endif HTTPD_CMD = env LD_LIBRARY_PATH=$(LD_LIBRARY_PATH) $(LIB_PTHREAD_HACK) \ $(PREFIX)/httpd/bin/apachectl +HTTPD_LOG_ROTATE = mv $(PREFIX)/httpd/logs/error_log $(PREFIX)/httpd/logs/error_log.old HTTPD_START_CMD = $(HTTPD_CMD) -f $(HTTPD_CHECK_CONF) -k start HTTPD_START_CMD_PROXY = $(HTTPD_CMD) -f $(HTTPD_PROXY_CONF) HTTPD_START_CMD_DEBUG = $(HTTPD_START_CMD) -X @@ -1931,6 +2053,7 @@ SVNSERVE_STOP_CMD = kill `cat $(PWD)/svnserve-$(WC).pid`; sleep 3; \ rm -f $(PWD)/svnserve-$(WC).pid start-httpd: $(HTTPD_CHECK_CONF) + -$(HTTPD_LOG_ROTATE) $(HTTPD_START_CMD) @echo "To run tests over http, run:" @echo " make check BASE_URL=http://localhost:$(HTTPD_CHECK_PORT)" @@ -1971,6 +2094,7 @@ define do_check env LD_LIBRARY_PATH=$(LD_LIBRARY_PATH) $(LIB_PTHREAD_HACK) \ env MAKEFLAGS= make check PARALLEL=$(PARALLEL) CLEANUP=$(CLEANUP) \ EXCLUSIVE_WC_LOCKS=$(EXCLUSIVE_WC_LOCKS) \ + SVN_BIN_DIR=$(SVN_PREFIX)/bin \ MEMCACHED_SERVER=$(MEMCACHED_SERVER) $1 FS_TYPE=$$fs; \ for log in tests.log fails.log; do \ test -f $$log && mv -f $$log $$log.$@-$$fs; \ @@ -2052,7 +2176,7 @@ svn-check-javahl: -if [ $(ENABLE_JAVA_BINDINGS) = yes ]; then \ (cd $(svn_builddir) && \ env LD_LIBRARY_PATH=$(LD_LIBRARY_PATH) \ - env MAKEFLAGS= make $(JAVAHL_CHECK_TARGET) 2>&1) | \ + MAKEFLAGS= make $(JAVAHL_CHECK_TARGET) 2>&1) | \ tee $(svn_builddir)/tests.log.bindings.javahl; \ fi diff --git a/tools/dev/unix-build/README b/tools/dev/unix-build/README index 13cdc42..8a3780c 100644 --- a/tools/dev/unix-build/README +++ b/tools/dev/unix-build/README @@ -94,3 +94,22 @@ everything is "svn-check". Notes ===== The script currently doesn't build Ctypes Python bindings. + +OpenBSD-specific notes +====================== +On OpenBSD install the following packages to get dependencies and +tools not covered by this Makefile: + +pkg_add autoconf automake bison coreutils gmake gperf groff libtool \ + python ruby scons subversion swig wget + +Some of these packages are available in several versions. Tested at time +of writing were: autoconf-2.68 automake-1.19 python-2.7.14 ruby-2.4.2 + +OpenBSD's autoconf and automake wrappers require desired versions in +environment variables and will raise errors if these aren't set: +export AUTOCONF_VERSION=2.68 +export AUTOMAKE_VERSION=1.19 + +A 'python' symlink is required; follow instructions printed by pkg_add +when the python package is installed. diff --git a/tools/dev/wc-ng/svn-wc-db-tester.c b/tools/dev/wc-ng/svn-wc-db-tester.c index ccdd102..ba63b63 100644 --- a/tools/dev/wc-ng/svn-wc-db-tester.c +++ b/tools/dev/wc-ng/svn-wc-db-tester.c @@ -44,7 +44,7 @@ static svn_error_t * version(apr_pool_t *pool) { - return svn_opt_print_help4(NULL, "svn-wc-db-tester", TRUE, FALSE, FALSE, + return svn_opt_print_help5(NULL, "svn-wc-db-tester", TRUE, FALSE, FALSE, NULL, NULL, NULL, NULL, NULL, NULL, pool); } diff --git a/tools/dev/which-error.py b/tools/dev/which-error.py index 6c683cb..fca4c47 100755 --- a/tools/dev/which-error.py +++ b/tools/dev/which-error.py @@ -23,7 +23,7 @@ # under the License. # ==================================================================== # -# $HeadURL: https://svn.apache.org/repos/asf/subversion/branches/1.10.x/tools/dev/which-error.py $ +# $HeadURL: https://svn.apache.org/repos/asf/subversion/branches/1.11.x/tools/dev/which-error.py $ # $LastChangedDate: 2016-04-30 08:16:53 +0000 (Sat, 30 Apr 2016) $ # $LastChangedBy: stefan2 $ # $LastChangedRevision: 1741723 $ diff --git a/tools/dist/README.backport b/tools/dist/README.backport index 0b9c66e..c3fdc68 100644 --- a/tools/dist/README.backport +++ b/tools/dist/README.backport @@ -7,20 +7,23 @@ F1. Auto-merge bot; the nightly svn-role commits. F2. Conflicts detector bot; the svn-backport-conflicts-1.9.x buildbot task. -And two interactive functions, described later. +And two interactive functions¹: + +F3. Reviewing STATUS nominations and casting votes. + +F4. Adding new entries to STATUS. The scripts are: backport.pl: - oldest script, implements both [F1] and [F2], plus two interactive - functions¹. As of March 2015, used in production by svn-role and - by svn-backport-conflicts-1.9.x. + oldest script, implements [F1], [F2], and [F3]. As of Feb 2018, used in + production by svn-role (running on svn-qavm3) and by svn-backport-conflicts-1.9.x + (a buildbot job). nominate.pl: - Symlink to backport.pl. Implements one of the two interactive features. - Not used by bots. + Symlink to backport.pl. Implements [F4]. (The script inspects its argv[0].) backport_tests_pl.py: Regression tests for backport.pl. @@ -39,9 +42,11 @@ backport/*.py: detect-conflicting-backports.py: Implementation of [F2] using backport.py. + Not currently used in production. merge-approved-backports.py: Implementation of [F1] using backport.py. + Not currently used in production. backport_tests_py.py: Regression tests for detect-conflicting-backports.py and merge-approved-backports.py @@ -52,13 +57,28 @@ backport_tests.py: svntest framework (../../subversion/tests/cmdline/svntest/), which is written in Python 2. -backport*.dump: + Note that backport_tests.py and backport/*.py are written in different + languages, so they never 'import' each other. backport_tests.py invokes + detect-conflicting-backports.py, merge-approved-backports.py, and + backport.pl in the same manner: through subprocess.check_call(). + +backport_tests_data/backport*.dump: Expected output files for backport_tests.py; see the BackportTest - decorator. + decorator in backport_tests.py. All scripts can be run with '--help' to display their usage messages. +backport.pl is considered deprecated since backport.py is better architected +and is written in a language that many more active developers are comfortable +with. The unattended jobs [F1] and [F2] should be converted to using +backport.py whenever someone gets around to do the legwork. The interactive +versions [F3] and [F4] are still in active use, however, so the physical +backport.pl script should be kept around until Python versions of these are +available. + + +TODO: document that "Notes: ... --accept=foo ..." is parsed, see backport_tests.py #3. ¹ For backport.pl's interactive features, see: diff --git a/tools/dist/backport.pl b/tools/dist/backport.pl index 67f8313..a8a7836 100755 --- a/tools/dist/backport.pl +++ b/tools/dist/backport.pl @@ -9,11 +9,11 @@ use v5.10.0; # needed for $^V # experimental and "subject to change" in v5.18 (see perl5180delta). Every # use of it now triggers a warning. # -# As of Perl v5.24.1, the semantics of given/when provided by Perl are +# As of Perl v5.26.1, the semantics of given/when provided by Perl are # compatible with those expected by the script, so disable the warning for # those Perls. But don't try to disable the the warning category on Perls # that don't know that category, since that breaks compilation. -no if (v5.17.0 le $^V and $^V le v5.24.1), +no if (v5.17.0 le $^V and $^V le v5.26.1), warnings => 'experimental::smartmatch'; # Licensed to the Apache Software Foundation (ASF) under one @@ -791,7 +791,7 @@ sub vote { # Add to state votes that aren't '+0' or 'edit' $state->{$_->{digest}}++ for grep - +{ qw/-1 t -0 t +1 t/ }->{$_->{vote}}, + ($_->{approval} or $_->{vote} =~ /^(-1|-0|[+]1)$/), @votesarray; } } @@ -1279,7 +1279,7 @@ sub nominate_main { # Open the file in line-mode (not paragraph-mode). my @STATUS; tie @STATUS, "Tie::File", $STATUS, recsep => "\n"; - my ($index) = grep { $STATUS[$_] =~ /^Veto/ } (0..$#STATUS); + my ($index) = grep { $STATUS[$_] =~ /^Veto|^Approved/ } (0..$#STATUS); die "Couldn't find where to add an entry" unless $index; # Add an empty line if needed. @@ -1297,7 +1297,8 @@ sub nominate_main { # Done! system "$SVN diff -- $STATUS"; if (prompt "Commit this nomination? ") { - system "$SVN commit -m '* STATUS: Nominate r$revnums[0].' -- $STATUS"; + my $header = join ', ', map "r$_", @revnums; + system "$SVN commit -m '* STATUS: Nominate $header.' -- $STATUS"; exit $?; } elsif (!$had_local_mods or prompt "Revert STATUS (destroying local mods)? ") { diff --git a/tools/dist/backport/status.py b/tools/dist/backport/status.py index 727939d..7ec378d 100644 --- a/tools/dist/backport/status.py +++ b/tools/dist/backport/status.py @@ -194,10 +194,10 @@ class StatusFile: try: entry = StatusEntry(para_text, status_file=self) kind = Kind.nomination - except ParseException: + except ParseException as e: kind = Kind.unknown - logger.warning("Failed to parse entry {!r} in {!r}".format( - para_text, status_fp)) + logger.warning("Failed to parse entry {!r} in {!r}: {}".format( + para_text, status_fp, e)) else: kind = Kind.preamble @@ -379,9 +379,11 @@ class StatusEntry: raise ParseException("Entry found with neither branch nor revisions") # Parse the logsummary. - while lines and not self._is_subheader(lines[0]): + while True: self.logsummary.append(lines[0]) lines = lines[1:] + if (not lines) or self._is_subheader(lines[0]): + break # Parse votes. if "Votes:" in lines: diff --git a/tools/dist/backport_tests.py b/tools/dist/backport_tests.py index ec483a7..27df294 100644 --- a/tools/dist/backport_tests.py +++ b/tools/dist/backport_tests.py @@ -53,6 +53,12 @@ import sys @contextlib.contextmanager def chdir(dir): + """This is a context manager that saves the current working directory's + pathname. Upon entry it chdir's to the argument DIR; upon exit it chdir's + back to the saved pathname. + + The current working directory is restored using os.chdir(), not os.fchdir(). + """ try: saved_dir = os.getcwd() os.chdir(dir) @@ -660,6 +666,21 @@ def backport_unicode_entry(sbox): # Run it. run_backport(sbox) +#---------------------------------------------------------------------- +@BackportTest('76cee987-25c9-4d6c-ad40-000000000013') +def backport_logsummary_colon(sbox): + "a logsummary that looks like a header" + + # r6: nominate r4 + approved_entries = [ + make_entry([4], logsummary="HTTPv2: Add comments."), + ] + sbox.simple_append(STATUS, serialize_STATUS(approved_entries)) + sbox.simple_commit(message='Nominate r4') + + # Run it. + run_backport(sbox) + #---------------------------------------------------------------------- @@ -680,6 +701,7 @@ test_list = [ None, backport_otherproject_change, backport_STATUS_mods, backport_unicode_entry, + backport_logsummary_colon, # When adding a new test, include the test number in the last # 6 bytes of the UUID, in decimal. ] diff --git a/tools/dist/backport_tests_data/backport_logsummary_colon.dump b/tools/dist/backport_tests_data/backport_logsummary_colon.dump new file mode 100644 index 0000000..db9d6ce --- /dev/null +++ b/tools/dist/backport_tests_data/backport_logsummary_colon.dump @@ -0,0 +1,522 @@ +SVN-fs-dump-format-version: 2 + +UUID: 76cee987-25c9-4d6c-ad40-000000000013 + +Revision-number: 0 +Prop-content-length: 10 +Content-length: 10 + +PROPS-END + +Revision-number: 1 +Prop-content-length: 83 +Content-length: 83 + +K 10 +svn:author +V 7 +jrandom +K 7 +svn:log +V 27 +Log message for revision 1. +PROPS-END + +Node-path: A +Node-kind: dir +Node-action: add +Prop-content-length: 10 +Content-length: 10 + +PROPS-END + + +Node-path: A/B +Node-kind: dir +Node-action: add +Prop-content-length: 10 +Content-length: 10 + +PROPS-END + + +Node-path: A/B/E +Node-kind: dir +Node-action: add +Prop-content-length: 10 +Content-length: 10 + +PROPS-END + + +Node-path: A/B/E/alpha +Node-kind: file +Node-action: add +Text-content-md5: d1fa4a3ced98961674a441930a51f2d3 +Text-content-sha1: b347d1da69df9a6a70433ceeaa0d46c8483e8c03 +Prop-content-length: 10 +Text-content-length: 26 +Content-length: 36 + +PROPS-END +This is the file 'alpha'. + + +Node-path: A/B/E/beta +Node-kind: file +Node-action: add +Text-content-md5: 67c756078f24f946f6ec2d00d02f50e1 +Text-content-sha1: d001710ac8e622c6d1fe59b1e265a3908acdd2a3 +Prop-content-length: 10 +Text-content-length: 25 +Content-length: 35 + +PROPS-END +This is the file 'beta'. + + +Node-path: A/B/F +Node-kind: dir +Node-action: add +Prop-content-length: 10 +Content-length: 10 + +PROPS-END + + +Node-path: A/B/lambda +Node-kind: file +Node-action: add +Text-content-md5: 911c7a8d869b8c1e566f57da54d889c6 +Text-content-sha1: 784a9298366863da2b65ebf82b4e1123755a2421 +Prop-content-length: 10 +Text-content-length: 27 +Content-length: 37 + +PROPS-END +This is the file 'lambda'. + + +Node-path: A/C +Node-kind: dir +Node-action: add +Prop-content-length: 10 +Content-length: 10 + +PROPS-END + + +Node-path: A/D +Node-kind: dir +Node-action: add +Prop-content-length: 10 +Content-length: 10 + +PROPS-END + + +Node-path: A/D/G +Node-kind: dir +Node-action: add +Prop-content-length: 10 +Content-length: 10 + +PROPS-END + + +Node-path: A/D/G/pi +Node-kind: file +Node-action: add +Text-content-md5: adddfc3e6b605b5f90ceeab11b4e8ab6 +Text-content-sha1: 411e258dc14b42701fdc29b75f653e93f8686415 +Prop-content-length: 10 +Text-content-length: 23 +Content-length: 33 + +PROPS-END +This is the file 'pi'. + + +Node-path: A/D/G/rho +Node-kind: file +Node-action: add +Text-content-md5: 82f2211cf4ab22e3555fc7b835fbc604 +Text-content-sha1: 56388a031dffbf9df7c32e1f299b1d5d7ef60881 +Prop-content-length: 10 +Text-content-length: 24 +Content-length: 34 + +PROPS-END +This is the file 'rho'. + + +Node-path: A/D/G/tau +Node-kind: file +Node-action: add +Text-content-md5: 9936e2716e469bb686deb98c280ead58 +Text-content-sha1: 62e8c07d56bee94ea4577e80414fa8805aaf0175 +Prop-content-length: 10 +Text-content-length: 24 +Content-length: 34 + +PROPS-END +This is the file 'tau'. + + +Node-path: A/D/H +Node-kind: dir +Node-action: add +Prop-content-length: 10 +Content-length: 10 + +PROPS-END + + +Node-path: A/D/H/chi +Node-kind: file +Node-action: add +Text-content-md5: 8f5ebad6d1f7775c2682e54417cbe4d3 +Text-content-sha1: abeac1bf62099ab66b44779198dc19f40e3244f4 +Prop-content-length: 10 +Text-content-length: 24 +Content-length: 34 + +PROPS-END +This is the file 'chi'. + + +Node-path: A/D/H/omega +Node-kind: file +Node-action: add +Text-content-md5: fe4ec8bdd3d2056db4f55b474a10fadc +Text-content-sha1: c06e671bf15a6af55086176a0931d3b5034c82e6 +Prop-content-length: 10 +Text-content-length: 26 +Content-length: 36 + +PROPS-END +This is the file 'omega'. + + +Node-path: A/D/H/psi +Node-kind: file +Node-action: add +Text-content-md5: e81f8f68ba50e749c200cb3c9ce5d2b1 +Text-content-sha1: 9c438bde39e8ccbbd366df2638e3cb6700950204 +Prop-content-length: 10 +Text-content-length: 24 +Content-length: 34 + +PROPS-END +This is the file 'psi'. + + +Node-path: A/D/gamma +Node-kind: file +Node-action: add +Text-content-md5: 412138bd677d64cd1c32fafbffe6245d +Text-content-sha1: 74b75d7f2e1a0292f17d5a57c570bd89783f5d1c +Prop-content-length: 10 +Text-content-length: 26 +Content-length: 36 + +PROPS-END +This is the file 'gamma'. + + +Node-path: A/mu +Node-kind: file +Node-action: add +Text-content-md5: baf78ae06a2d5b7d9554c5f1280d3fa8 +Text-content-sha1: b4d00c56351d1a752e24d839d41a362d8da4a4c7 +Prop-content-length: 10 +Text-content-length: 23 +Content-length: 33 + +PROPS-END +This is the file 'mu'. + + +Node-path: iota +Node-kind: file +Node-action: add +Text-content-md5: 2d18c5e57e84c5b8a5e9a6e13fa394dc +Text-content-sha1: 2c0aa9014a0cd07f01795a333d82485ef6d083e2 +Prop-content-length: 10 +Text-content-length: 25 +Content-length: 35 + +PROPS-END +This is the file 'iota'. + + +Revision-number: 2 +Prop-content-length: 68 +Content-length: 68 + +K 10 +svn:author +V 7 +jrandom +K 7 +svn:log +V 12 +Create trunk +PROPS-END + +Node-path: subversion +Node-kind: dir +Node-action: add +Prop-content-length: 10 +Content-length: 10 + +PROPS-END + + +Node-path: subversion/branches +Node-kind: dir +Node-action: add +Prop-content-length: 10 +Content-length: 10 + +PROPS-END + + +Node-path: subversion/tags +Node-kind: dir +Node-action: add +Prop-content-length: 10 +Content-length: 10 + +PROPS-END + + +Node-path: subversion/trunk +Node-kind: dir +Node-action: add +Prop-content-length: 10 +Content-length: 10 + +PROPS-END + + +Node-path: subversion/trunk/A +Node-kind: dir +Node-action: add +Node-copyfrom-rev: 1 +Node-copyfrom-path: A + + +Node-path: subversion/trunk/iota +Node-kind: file +Node-action: add +Node-copyfrom-rev: 1 +Node-copyfrom-path: iota +Text-copy-source-md5: 2d18c5e57e84c5b8a5e9a6e13fa394dc +Text-copy-source-sha1: 2c0aa9014a0cd07f01795a333d82485ef6d083e2 + + +Node-path: A +Node-action: delete + + +Node-path: iota +Node-action: delete + + +Revision-number: 3 +Prop-content-length: 87 +Content-length: 87 + +K 10 +svn:author +V 7 +jrandom +K 7 +svn:log +V 31 +Create branch, with STATUS file +PROPS-END + +Node-path: branch +Node-kind: dir +Node-action: add +Node-copyfrom-rev: 2 +Node-copyfrom-path: subversion/trunk + + +Node-path: branch/STATUS +Node-kind: file +Node-action: add +Text-content-md5: d41d8cd98f00b204e9800998ecf8427e +Text-content-sha1: da39a3ee5e6b4b0d3255bfef95601890afd80709 +Prop-content-length: 10 +Text-content-length: 0 +Content-length: 10 + +PROPS-END + + +Revision-number: 4 +Prop-content-length: 68 +Content-length: 68 + +K 10 +svn:author +V 7 +jrandom +K 7 +svn:log +V 12 +First change +PROPS-END + +Node-path: subversion/trunk/iota +Node-kind: file +Node-action: change +Text-content-md5: 67f471c2ecc2c9e561d122d6e6b0f847 +Text-content-sha1: 750accb6e7f880a1d05ce725c19eb60183bb4b26 +Text-content-length: 38 +Content-length: 38 + +This is the file 'iota'. +First change + + +Revision-number: 5 +Prop-content-length: 69 +Content-length: 69 + +K 10 +svn:author +V 7 +jrandom +K 7 +svn:log +V 13 +Second change +PROPS-END + +Node-path: subversion/trunk/A/mu +Node-kind: file +Node-action: change +Text-content-md5: eab751301b4e650c83324dfef4aad667 +Text-content-sha1: ab36cad564c7c50dec5ac1eb0bf879cf4e3a5f99 +Text-content-length: 37 +Content-length: 37 + +This is the file 'mu'. +Second change + + +Revision-number: 6 +Prop-content-length: 67 +Content-length: 67 + +K 10 +svn:author +V 7 +jrandom +K 7 +svn:log +V 11 +Nominate r4 +PROPS-END + +Node-path: branch/STATUS +Node-kind: file +Node-action: change +Text-content-md5: 21cf72d59d9e71a49260e3cf31f78b76 +Text-content-sha1: 9938559a403d5a18099aace3db6719bdb8940449 +Text-content-length: 245 +Content-length: 245 + +Status of 1.8.x: + +Candidate changes: +================== + +Random new subheading: +====================== + +Veto-blocked changes: +===================== + +Approved changes: +================= + + * r4 + HTTPv2: Add comments. + Votes: + +1: jrandom + + + +Revision-number: 7 +Prop-content-length: 135 +Content-length: 135 + +K 10 +svn:author +V 6 +daniel +K 7 +svn:log +V 80 +Merge r4 from trunk: + + * r4 + HTTPv2: Add comments. + Votes: + +1: jrandom + +PROPS-END + +Node-path: branch +Node-kind: dir +Node-action: change +Prop-content-length: 54 +Content-length: 54 + +K 13 +svn:mergeinfo +V 19 +/subversion/trunk:4 +PROPS-END + + +Node-path: branch/STATUS +Node-kind: file +Node-action: change +Text-content-md5: 6f71fec92afeaa5c1ebe02349f548ca9 +Text-content-sha1: eece02003d9c51610249e3fdd0d4e191e02ba3b7 +Text-content-length: 185 +Content-length: 185 + +Status of 1.8.x: + +Candidate changes: +================== + +Random new subheading: +====================== + +Veto-blocked changes: +===================== + +Approved changes: +================= + + +Node-path: branch/iota +Node-kind: file +Node-action: change +Text-content-md5: 67f471c2ecc2c9e561d122d6e6b0f847 +Text-content-sha1: 750accb6e7f880a1d05ce725c19eb60183bb4b26 +Text-content-length: 38 +Content-length: 38 + +This is the file 'iota'. +First change + + diff --git a/tools/dist/create-minor-release-branch.py b/tools/dist/create-minor-release-branch.py new file mode 100755 index 0000000..7126edd --- /dev/null +++ b/tools/dist/create-minor-release-branch.py @@ -0,0 +1,298 @@ +#!/usr/bin/env python +# python: coding=utf-8 +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + + +# About this script: +# This script is intended to automate steps in creating a new Subversion +# minor release. + +import os +import re +import sys +import logging +import subprocess +import argparse # standard in Python 2.7 + +from release import Version + + +# Some constants +repos = 'https://svn.apache.org/repos/asf/subversion' +secure_repos = 'https://svn.apache.org/repos/asf/subversion' +buildbot_repos = 'https://svn.apache.org/repos/infra/infrastructure/buildbot/aegis/buildmaster' + +# Local working copies +base_dir = None # set by main() + +def get_trunk_wc_path(path=None): + trunk_wc_path = os.path.join(base_dir, 'svn-trunk') + if path is None: return trunk_wc_path + return os.path.join(trunk_wc_path, path) +def get_branch_wc_path(ver, path=None): + branch_wc_path = os.path.join(base_dir, ver.branch + '.x') + if path is None: return branch_wc_path + return os.path.join(branch_wc_path, path) +def get_buildbot_wc_path(path=None): + buildbot_wc_path = os.path.join(base_dir, 'svn-buildmaster') + if path is None: return buildbot_wc_path + return os.path.join(buildbot_wc_path, path) + +def get_trunk_url(): + return secure_repos + '/trunk' +def get_branch_url(ver): + return secure_repos + '/branches/' + ver.branch + '.x' +def get_tag_url(ver): + return secure_repos + '/tags/' + ver.base +def get_buildbot_url(): + return buildbot_repos + +#---------------------------------------------------------------------- +# Utility functions + +def run(cmd, dry_run=False): + print('+ ' + ' '.join(cmd)) + if not dry_run: + stdout = subprocess.check_output(cmd) + print(stdout) + +def run_svn(cmd, dry_run=False): + run(['svn'] + cmd, dry_run) + +def svn_commit(cmd): + run_svn(['commit'] + cmd, dry_run=True) + +def svn_checkout(*args): + args = ['checkout'] + list(args) + ['--revision={2017-12-01}'] + run_svn(args) + +#---------------------------------------------------------------------- +def edit_file(path, pattern, replacement): + print("Editing '%s'" % (path,)) + print(" pattern='%s'" % (pattern,)) + print(" replace='%s'" % (replacement,)) + old_text = open(path, 'r').read() + new_text = re.sub(pattern, replacement, old_text) + assert new_text != old_text + open(path, 'w').write(new_text) + +def prepend_file(path, text): + print("Prepending to '%s'" % (path,)) + print(" text='%s'" % (text,)) + original = open(path, 'r').read() + open(path, 'w').write(text + original) + +#---------------------------------------------------------------------- +def make_release_branch(ver): + run_svn(['copy', get_trunk_url(), get_branch_url(ver), + '-m', 'Create the ' + ver.branch + '.x release branch.'], + dry_run=True) + +#---------------------------------------------------------------------- +def update_minor_ver_in_trunk(ver): + """Change the minor version in trunk to the next (future) minor version. + """ + trunk_wc = get_trunk_wc_path() + trunk_url = get_trunk_url() + svn_checkout(trunk_url, trunk_wc) + + prev_ver = Version('1.%d.0' % (ver.minor - 1,)) + next_ver = Version('1.%d.0' % (ver.minor + 1,)) + relpaths = [] + + relpath = 'subversion/include/svn_version.h' + relpaths.append(relpath) + edit_file(get_trunk_wc_path(relpath), + r'(#define SVN_VER_MINOR *)%s' % (ver.minor,), + r'\g<1>%s' % (next_ver.minor,)) + + relpath = 'subversion/tests/cmdline/svntest/main.py' + relpaths.append(relpath) + edit_file(get_trunk_wc_path(relpath), + r'(SVN_VER_MINOR = )%s' % (ver.minor,), + r'\g<1>%s' % (next_ver.minor,)) + + relpath = 'subversion/bindings/javahl/src/org/apache/subversion/javahl/NativeResources.java' + relpaths.append(relpath) + try: + # since r1817921 (just after branching 1.10) + edit_file(get_trunk_wc_path(relpath), + r'SVN_VER_MINOR = %s;' % (ver.minor,), + r'SVN_VER_MINOR = %s;' % (next_ver.minor,)) + except: + # before r1817921: two separate places + edit_file(get_trunk_wc_path(relpath), + r'version.isAtLeast\(1, %s, 0\)' % (ver.minor,), + r'version.isAtLeast\(1, %s, 0\)' % (next_ver.minor,)) + edit_file(get_trunk_wc_path(relpath), + r'1.%s.0, but' % (ver.minor,), + r'1.%s.0, but' % (next_ver.minor,)) + + relpath = 'CHANGES' + relpaths.append(relpath) + # insert at beginning of CHANGES file + prepend_file(get_trunk_wc_path(relpath), + 'Version ' + next_ver.base + '\n' + + '(?? ??? 20XX, from /branches/' + next_ver.branch + '.x)\n' + + get_tag_url(next_ver) + '\n' + + '\n') + + log_msg = '''\ +Increment the trunk version number to %s, and introduce a new CHANGES +section, following the creation of the %s.x release branch. + +* subversion/include/svn_version.h, + subversion/bindings/javahl/src/org/apache/subversion/javahl/NativeResources.java, + subversion/tests/cmdline/svntest/main.py + (SVN_VER_MINOR): Increment to %s. + +* CHANGES: New section for %s.0. +''' % (next_ver.branch, ver.branch, next_ver.minor, next_ver.branch) + commit_paths = [get_trunk_wc_path(p) for p in relpaths] + svn_commit(commit_paths + ['-m', log_msg]) + +#---------------------------------------------------------------------- +def create_status_file_on_branch(ver): + branch_wc = get_branch_wc_path(ver) + branch_url = get_branch_url(ver) + svn_checkout(branch_url, branch_wc, '--depth=immediates') + + status_local_path = os.path.join(branch_wc, 'STATUS') + text='''\ + * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * THIS RELEASE STREAM IS OPEN FOR STABILIZATION. * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * + +This file tracks the status of releases in the %s.x line. + +See http://subversion.apache.org/docs/community-guide/releasing.html#release-stabilization +for details on how release lines and voting work, what kinds of bugs can +delay a release, etc. + +Status of %s: + +Candidate changes: +================== + + +Veto-blocked changes: +===================== + + +Approved changes: +================= +''' % (ver.branch, ver.base) + open(status_local_path, 'wx').write(text) + run_svn(['add', status_local_path]) + svn_commit([status_local_path, + '-m', '* branches/' + ver.branch + '.x/STATUS: New file.']) + +#---------------------------------------------------------------------- +def update_backport_bot(ver): + print("""MANUAL STEP: Fork & edit & pull-request on GitHub: +https://github.com/apache/infrastructure-puppet/blob/deployment/modules/svnqavm_pvm_asf/manifests/init.pp +"Add new %s.x branch to list of backport branches" +""" % (ver.branch,)) + print("""Someone needs to run the 'svn checkout' manually. +The exact checkout command is documented in machines/svn-qavm2/notes.txt +in the private repository (need to use a trunk client and the svn-master.a.o +hostname). +""") + +#---------------------------------------------------------------------- +def update_buildbot_config(ver): + """Add the new branch to the list of branches monitored by the buildbot + master. + """ + buildbot_wc = get_buildbot_wc_path() + buildbot_url = get_buildbot_url() + svn_checkout(buildbot_url, buildbot_wc) + + prev_ver = Version('1.%d.0' % (ver.minor - 1,)) + next_ver = Version('1.%d.0' % (ver.minor + 1,)) + + relpath = 'master1/projects/subversion.conf' + edit_file(get_buildbot_wc_path(relpath), + r'(MINOR_LINES=\[.*%s)(\])' % (prev_ver.minor,), + r'\1, %s\2' % (ver.minor,)) + + log_msg = '''\ +Subversion: start monitoring the %s branch. +''' % (ver.branch) + commit_paths = [get_buildbot_wc_path(relpath)] + svn_commit(commit_paths + ['-m', log_msg]) + +#---------------------------------------------------------------------- +def steps(args): + ver = Version('1.10.0') + + make_release_branch(ver) + update_minor_ver_in_trunk(ver) + create_status_file_on_branch(ver) + update_backport_bot(ver) + update_buildbot_config(ver) + + +#---------------------------------------------------------------------- +# Main entry point for argument parsing and handling + +def main(): + 'Parse arguments, and drive the appropriate subcommand.' + + # Setup our main parser + parser = argparse.ArgumentParser( + description='Create an Apache Subversion release branch.') + parser.add_argument('--verbose', action='store_true', default=False, + help='Increase output verbosity') + parser.add_argument('--base-dir', default=os.getcwd(), + help='''The directory in which to create needed files and + folders. The default is the current working + directory.''') + subparsers = parser.add_subparsers(title='subcommands') + + # Setup the parser for the build-env subcommand + subparser = subparsers.add_parser('steps', + help='''Run the release-branch-creation steps.''') + subparser.set_defaults(func=steps) + + # Parse the arguments + args = parser.parse_args() + + global base_dir + base_dir = args.base_dir + + # Set up logging + logger = logging.getLogger() + if args.verbose: + logger.setLevel(logging.DEBUG) + else: + logger.setLevel(logging.INFO) + + # Make timestamps in tarballs independent of local timezone + os.environ['TZ'] = 'UTC' + + # finally, run the subcommand, and give it the parsed arguments + args.func(args) + + +if __name__ == '__main__': + main() diff --git a/tools/dist/edit-N-log-messages b/tools/dist/edit-N-log-messages new file mode 100755 index 0000000..fa6a2a2 --- /dev/null +++ b/tools/dist/edit-N-log-messages @@ -0,0 +1,94 @@ +#!/usr/bin/env zsh +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +set -e + +# setup +0=${0:t}; NAME=$0 +svn=${SVN:-svn} +svnadmin=${SVNADMIN:-svnadmin} + +usage() { + echo "usage: $NAME -r N:M" + echo " will retrieve all log messages in the range rN:rM, open them in" + echo " \$EDITOR, and commit any edits to them." + echo "" + echo " Run this with cwd being a working copy of ^/subversion/trunk." + # TODO: We only need the cwd in case SVN_CLIENT__REVKIND_NEEDS_WC() is true + # for N or M. When N and M are both numeric or HEAD, teach this script + # to disregard its cwd and contact ^/subversion/trunk directly. +} + +# parse argv +while getopts r: letter; do + if [[ $letter == r ]]; then + revision_range=$OPTARG + else + usage >&2 + exit 1 + fi +done +shift $((OPTIND - 1)) +[[ -n $revision_range ]] || { usage >&2; exit 1; } + +# get log messages +cd "$(mktemp -d)" +echo "${0}: Temporary directory: ${(q-)PWD}" +revisions=( ${(f)"$( + # We use $OLDPWD rather than a URL in case $revision_range is, say, + # "BASE:HEAD". + $svn log -q -r $revision_range -- $OLDPWD | + grep '^r' | cut -d' ' -f1 | grep '^r[0-9]*$' +)"} ) +for rN in $revisions; do + $svn propget --revprop -r $rN --strict 'svn:log' -- $OLDPWD > ./$rN & +done +wait + +# set up to detect which ones have changed +$svnadmin create ./.r +$svn checkout -q file://$PWD/.r ./ +$svn add -q ./r* +$svn commit -q -m "Import revisions $revision_range" +rm -rf ./.r # (!) + +# edit +case $EDITOR in + (*vim*) $EDITOR -p ./r*;; + (*) $EDITOR ./r*;; +esac + +# prompt for permission to continue +if $svn status -q | grep -q ''; then + $svn status -q + read -q "?Commit the above propedits? " || { echo "${0}: exiting"; exit 0; } + echo "" +else + echo "${0}: No changes." + echo "${0}: You can remove ${(q-)PWD} now." + exit 0 +fi + +# make propedits +# TODO: make these changes atomically +# 'svn propedit' is atomic and could drive a non-interactive $EDITOR, but for +# now, we just trust the committer to read commits@. +targets=( ${(f)"$($svn status -q | grep '^M' | cut -c9-)"} ) +for i in $targets; do + $svn propset --revprop -r $i -F ./$i -- 'svn:log' $OLDPWD +done diff --git a/tools/dist/release.py b/tools/dist/release.py index 5518d6f..e101179 100755 --- a/tools/dist/release.py +++ b/tools/dist/release.py @@ -51,6 +51,7 @@ import operator import itertools import subprocess import argparse # standard in Python 2.7 +import io # Find ezt, using Subversion's copy, if there isn't one on the system. try: @@ -71,16 +72,16 @@ tool_versions = { '954bd69b391edc12d6a4a51a2dd1476543da5c6bbf05a95b59dc0dd6fd4c2969'], 'libtool' : ['2.4.6', 'e3bd4d5d3d025a36c21dd6af7ea818a2afcd4dfc1ea5a17b39d7854bcd0c06e3'], - 'swig' : ['3.0.10', - '2939aae39dec06095462f1b95ce1c958ac80d07b926e48871046d17c0094f44c'], + 'swig' : ['3.0.12', + '7cf9f447ae7ed1c51722efc45e7f14418d15d7a1e143ac9f09a668999f4fc94d'], }, '1.10' : { 'autoconf' : ['2.69', '954bd69b391edc12d6a4a51a2dd1476543da5c6bbf05a95b59dc0dd6fd4c2969'], 'libtool' : ['2.4.6', 'e3bd4d5d3d025a36c21dd6af7ea818a2afcd4dfc1ea5a17b39d7854bcd0c06e3'], - 'swig' : ['3.0.10', - '2939aae39dec06095462f1b95ce1c958ac80d07b926e48871046d17c0094f44c'], + 'swig' : ['3.0.12', + '7cf9f447ae7ed1c51722efc45e7f14418d15d7a1e143ac9f09a668999f4fc94d'], }, '1.9' : { 'autoconf' : ['2.69', @@ -102,7 +103,7 @@ tool_versions = { # The version that is our current recommended release # ### TODO: derive this from svn_version.h; see ../../build/getversion.py -recommended_release = '1.9' +recommended_release = '1.10' # Some constants repos = 'https://svn.apache.org/repos/asf/subversion' @@ -174,7 +175,7 @@ class Version(object): ver_tag = '" (Alpha %d)"' % self.pre_num ver_numtag = '"-alpha%d"' % self.pre_num elif self.pre == 'beta': - ver_tag = '" (Beta %d)"' % args.version.pre_num + ver_tag = '" (Beta %d)"' % self.pre_num ver_numtag = '"-beta%d"' % self.pre_num elif self.pre == 'rc': ver_tag = '" (Release Candidate %d)"' % self.pre_num @@ -712,9 +713,13 @@ def roll_tarballs(args): filepath = os.path.join(get_tempdir(args.base_dir), filename) shutil.move(filepath, get_deploydir(args.base_dir)) filepath = os.path.join(get_deploydir(args.base_dir), filename) - m = hashlib.sha1() - m.update(open(filepath, 'r').read()) - open(filepath + '.sha1', 'w').write(m.hexdigest()) + if args.version < Version("1.11.0-alpha1"): + # 1.10 and earlier generate *.sha1 files for compatibility reasons. + # They are deprecated, however, so we don't publicly link them in + # the announcements any more. + m = hashlib.sha1() + m.update(open(filepath, 'r').read()) + open(filepath + '.sha1', 'w').write(m.hexdigest()) m = hashlib.sha512() m.update(open(filepath, 'r').read()) open(filepath + '.sha512', 'w').write(m.hexdigest()) @@ -737,8 +742,12 @@ def sign_candidates(args): def sign_file(filename): asc_file = open(filename + '.asc', 'a') logging.info("Signing %s" % filename) - proc = subprocess.check_call(['gpg', '-ba', '-o', '-', filename], - stdout=asc_file) + if args.userid: + proc = subprocess.check_call(['gpg', '-ba', '-u', args.userid, + '-o', '-', filename], stdout=asc_file) + else: + proc = subprocess.check_call(['gpg', '-ba', '-o', '-', filename], + stdout=asc_file) asc_file.close() target = get_target(args) @@ -773,8 +782,9 @@ def post_candidates(args): #---------------------------------------------------------------------- # Create tag +# Bump versions on branch -def create_tag(args): +def create_tag_only(args): 'Create tag in the repository' target = get_target(args) @@ -805,56 +815,80 @@ def create_tag(args): logging.error("Do you need to pass --branch=trunk?") raise +def bump_versions_on_branch(args): + 'Bump version numbers on branch' + + logging.info('Bumping version numbers on the branch') + + if not args.branch: + args.branch = 'branches/%d.%d.x' % (args.version.major, args.version.minor) + + branch = secure_repos + '/' + args.branch.rstrip('/') + + def replace_in_place(fd, startofline, flat, spare): + """In file object FD, replace FLAT with SPARE in the first line + starting with regex STARTOFLINE.""" + + pattern = r'^(%s)%s' % (startofline, re.escape(flat)) + repl = r'\g<1>%s' % (spare,) + fd.seek(0, os.SEEK_SET) + lines = fd.readlines() + for i, line in enumerate(lines): + replacement = re.sub(pattern, repl, line) + if replacement != line: + lines[i] = replacement + break + else: + raise RuntimeError("Could not replace r'%s' with r'%s' in '%s'" + % (pattern, repl, fd.url)) + + fd.seek(0, os.SEEK_SET) + fd.writelines(lines) + fd.truncate() # for current callers, new value is never shorter. + + new_version = Version('%d.%d.%d' % + (args.version.major, args.version.minor, + args.version.patch + 1)) + + HEAD = subprocess.check_output(['svn', 'info', '--show-item=revision', + '--', branch]).strip() + HEAD = int(HEAD) + def file_object_for(relpath): + fd = tempfile.NamedTemporaryFile() + url = branch + '/' + relpath + fd.url = url + subprocess.check_call(['svn', 'cat', '%s@%d' % (url, HEAD)], + stdout=fd) + return fd + + svn_version_h = file_object_for('subversion/include/svn_version.h') + replace_in_place(svn_version_h, '#define SVN_VER_PATCH *', + str(args.version.patch), str(new_version.patch)) + + STATUS = file_object_for('STATUS') + replace_in_place(STATUS, 'Status of ', + str(args.version), str(new_version)) + + svn_version_h.seek(0, os.SEEK_SET) + STATUS.seek(0, os.SEEK_SET) + subprocess.check_call(['svnmucc', '-r', str(HEAD), + '-m', 'Post-release housekeeping: ' + 'bump the %s branch to %s.' + % (branch.split('/')[-1], str(new_version)), + 'put', svn_version_h.name, svn_version_h.url, + 'put', STATUS.name, STATUS.url, + ]) + del svn_version_h + del STATUS + +def create_tag_and_bump_versions(args): + '''Create tag in the repository and, if not a prerelease version, + bump version numbers on the branch''' + + create_tag_only(args) + if not args.version.is_prerelease(): - logging.info('Bumping revisions on the branch') - def replace_in_place(fd, startofline, flat, spare): - """In file object FD, replace FLAT with SPARE in the first line - starting with STARTOFLINE.""" - - fd.seek(0, os.SEEK_SET) - lines = fd.readlines() - for i, line in enumerate(lines): - if line.startswith(startofline): - lines[i] = line.replace(flat, spare) - break - else: - raise RuntimeError('Definition of %r not found' % startofline) - - fd.seek(0, os.SEEK_SET) - fd.writelines(lines) - fd.truncate() # for current callers, new value is never shorter. - - new_version = Version('%d.%d.%d' % - (args.version.major, args.version.minor, - args.version.patch + 1)) - - def file_object_for(relpath): - fd = tempfile.NamedTemporaryFile() - url = branch + '/' + relpath - fd.url = url - subprocess.check_call(['svn', 'cat', '%s@%d' % (url, args.revnum)], - stdout=fd) - return fd - - svn_version_h = file_object_for('subversion/include/svn_version.h') - replace_in_place(svn_version_h, '#define SVN_VER_PATCH ', - str(args.version.patch), str(new_version.patch)) - - STATUS = file_object_for('STATUS') - replace_in_place(STATUS, 'Status of ', - str(args.version), str(new_version)) - - svn_version_h.seek(0, os.SEEK_SET) - STATUS.seek(0, os.SEEK_SET) - subprocess.check_call(['svnmucc', '-r', str(args.revnum), - '-m', 'Post-release housekeeping: ' - 'bump the %s branch to %s.' - % (branch.split('/')[-1], str(new_version)), - 'put', svn_version_h.name, svn_version_h.url, - 'put', STATUS.name, STATUS.url, - ]) - del svn_version_h - del STATUS + bump_versions_on_branch(args) #---------------------------------------------------------------------- # Clean dist @@ -938,6 +972,7 @@ def write_news(args): 'version_base' : args.version.base, 'anchor': args.version.get_download_anchor(), 'is_recommended': ezt_bool(args.version.is_recommended()), + 'announcement_url': args.announcement_url, } if args.version.is_prerelease(): @@ -947,37 +982,50 @@ def write_news(args): template = ezt.Template() template.parse(get_tmplfile(template_filename).read()) - template.generate(sys.stdout, data) + + # Insert the output into an existing file if requested, else print it + if args.edit_html_file: + tmp_name = args.edit_html_file + '.tmp' + with open(args.edit_html_file, 'r') as f, open(tmp_name, 'w') as g: + inserted = False + for line in f: + if not inserted and line.startswith('<div class="h3" id="news-'): + template.generate(g, data) + g.write('\n') + inserted = True + g.write(line) + os.remove(args.edit_html_file) + os.rename(tmp_name, args.edit_html_file) + else: + template.generate(sys.stdout, data) -def get_sha1info(args): - 'Return a list of sha1 info for the release' +def get_fileinfo(args): + 'Return a list of file info (filenames) for the release tarballs' target = get_target(args) - sha1s = glob.glob(os.path.join(target, 'subversion*-%s*.sha1' % args.version)) + files = glob.glob(os.path.join(target, 'subversion*-%s*.asc' % args.version)) + files.sort() class info(object): pass - sha1info = [] - for s in sha1s: + fileinfo = [] + for f in files: i = info() - # strip ".sha1" - i.filename = os.path.basename(s)[:-5] - i.sha1 = open(s, 'r').read() - sha1info.append(i) + # strip ".asc" + i.filename = os.path.basename(f)[:-4] + fileinfo.append(i) - return sha1info + return fileinfo def write_announcement(args): 'Write the release announcement.' - sha1info = get_sha1info(args) siginfo = "\n".join(get_siginfo(args, True)) + "\n" data = { 'version' : str(args.version), - 'sha1info' : sha1info, 'siginfo' : siginfo, 'major-minor' : args.version.branch, 'major-minor-patch' : args.version.base, @@ -1007,10 +1055,10 @@ def write_announcement(args): def write_downloads(args): 'Output the download section of the website.' - sha1info = get_sha1info(args) + fileinfo = get_fileinfo(args) data = { 'version' : str(args.version), - 'fileinfo' : sha1info, + 'fileinfo' : fileinfo, } template = ezt.Template(compress_whitespace = False) @@ -1174,6 +1222,173 @@ def get_keys(args): fd.seek(0) subprocess.check_call(['gpg', '--import'], stdin=fd) +def add_to_changes_dict(changes_dict, audience, section, change, revision): + # Normalize arguments + if audience: + audience = audience.upper() + if section: + section = section.lower() + change = change.strip() + + if not audience in changes_dict: + changes_dict[audience] = dict() + if not section in changes_dict[audience]: + changes_dict[audience][section] = dict() + + changes = changes_dict[audience][section] + if change in changes: + changes[change].add(revision) + else: + changes[change] = set([revision]) + +def print_section(changes_dict, audience, section, title, mandatory=False): + if audience in changes_dict: + audience_changes = changes_dict[audience] + if mandatory or (section in audience_changes): + if title: + print(' - %s:' % title) + if section in audience_changes: + print_changes(audience_changes[section]) + elif mandatory: + print(' (none)') + +def print_changes(changes): + # Print in alphabetical order, so entries with the same prefix are together + for change in sorted(changes): + revs = changes[change] + rev_string = 'r' + str(min(revs)) + (' et al' if len(revs) > 1 else '') + print(' * %s (%s)' % (change, rev_string)) + +def write_changelog(args): + 'Write changelog, parsed from commit messages' + # Changelog lines are lines with the following format: + # '['[audience[:section]]']' <message> + # or: + # <message> '['[audience[:section]]']' + # where audience = U (User-visible) or D (Developer-visible) + # section = general|major|minor|client|server|clientserver|other|api|bindings + # (section is optional and is treated case-insensitively) + # message = the actual text for CHANGES + # + # This means the "changes label" can be used as prefix or suffix, and it + # can also be left empty (which results in an uncategorized changes entry), + # if the committer isn't sure where the changelog entry belongs. + # + # Putting [skip], [ignore], [c:skip] or [c:ignore] somewhere in the + # log message means this commit must be ignored for Changelog processing + # (ignored even with the --include-unlabeled-summaries option). + # + # If there is no changes label anywhere in the commit message, and the + # --include-unlabeled-summaries option is used, we'll consider the summary + # line of the commit message (= first line except if it starts with a *) + # as an uncategorized changes entry, except if it contains "status", + # "changes", "post-release housekeeping" or "follow-up". + # + # Examples: + # [U:major] Better interactive conflict resolution for tree conflicts + # ra_serf: Adjustments for serf versions with HTTP/2 support [U:minor] + # [U] Fix 'svn diff URL@REV WC' wrongly looks up URL@HEAD (issue #4597) + # Fix bug with canonicalizing Window-specific drive-relative URL [] + # New svn_ra_list() API function [D:api] + # [D:bindings] JavaHL: Allow access to constructors of a couple JavaHL classes + + branch = secure_repos + '/' + args.branch + previous = secure_repos + '/' + args.previous + include_unlabeled = args.include_unlabeled + + mergeinfo = subprocess.check_output(['svn', 'mergeinfo', '--show-revs', + 'eligible', '--log', branch, previous]).splitlines() + + separator_pattern = re.compile('^-{72}$') + revline_pattern = re.compile('^r(\d+) \| [^\|]+ \| [^\|]+ \| \d+ lines?$') + changes_prefix_pattern = re.compile('^\[(U|D)?:?([^\]]+)?\](.+)$') + changes_suffix_pattern = re.compile('^(.+)\[(U|D)?:?([^\]]+)?\]$') + + changes_dict = dict() # audience -> (section -> (change -> set(revision))) + revision = -1 + got_firstline = False + unlabeled_summary = None + changes_ignore = False + audience = None + section = None + message = None + + for line in mergeinfo: + if separator_pattern.match(line): + # New revision section. Reset variables. + # If there's an unlabeled summary from a previous section, and + # include_unlabeled is True, put it into uncategorized_changes. + if include_unlabeled and unlabeled_summary and not changes_ignore: + add_to_changes_dict(changes_dict, None, None, + unlabeled_summary, revision) + revision = -1 + got_firstline = False + unlabeled_summary = None + changes_ignore = False + audience = None + section = None + message = None + continue + + revmatch = revline_pattern.match(line) + if revmatch and (revision == -1): + # A revision line: get the revision number + revision = int(revmatch.group(1)) + logging.debug('Changelog processing revision r%d' % revision) + continue + + if line.strip() == '': + # Skip empty / whitespace lines + continue + + if not got_firstline: + got_firstline = True + if (not re.search('status|changes|post-release housekeeping|follow-up|^\*', + line, re.IGNORECASE) + and not changes_prefix_pattern.match(line) + and not changes_suffix_pattern.match(line)): + unlabeled_summary = line + + if re.search('\[(c:)?(skip|ignore)\]', line, re.IGNORECASE): + changes_ignore = True + + prefix_match = changes_prefix_pattern.match(line) + if prefix_match: + audience = prefix_match.group(1) + section = prefix_match.group(2) + message = prefix_match.group(3) + add_to_changes_dict(changes_dict, audience, section, message, revision) + + suffix_match = changes_suffix_pattern.match(line) + if suffix_match: + message = suffix_match.group(1) + audience = suffix_match.group(2) + section = suffix_match.group(3) + add_to_changes_dict(changes_dict, audience, section, message, revision) + + # Output the sorted changelog entries + # 1) Uncategorized changes + print_section(changes_dict, None, None, None) + print + # 2) User-visible changes + print(' User-visible changes:') + print_section(changes_dict, 'U', None, None) + print_section(changes_dict, 'U', 'general', 'General') + print_section(changes_dict, 'U', 'major', 'Major new features') + print_section(changes_dict, 'U', 'minor', 'Minor new features and improvements') + print_section(changes_dict, 'U', 'client', 'Client-side bugfixes', mandatory=True) + print_section(changes_dict, 'U', 'server', 'Server-side bugfixes', mandatory=True) + print_section(changes_dict, 'U', 'clientserver', 'Client-side and server-side bugfixes') + print_section(changes_dict, 'U', 'other', 'Other tool improvements and bugfixes') + print_section(changes_dict, 'U', 'bindings', 'Bindings bugfixes', mandatory=True) + print + # 3) Developer-visible changes + print(' Developer-visible changes:') + print_section(changes_dict, 'D', None, None) + print_section(changes_dict, 'D', 'general', 'General', mandatory=True) + print_section(changes_dict, 'D', 'api', 'API changes', mandatory=True) + print_section(changes_dict, 'D', 'bindings', 'Bindings') + #---------------------------------------------------------------------- # Main entry point for argument parsing and handling @@ -1231,6 +1446,10 @@ def main(): subparser.add_argument('--target', help='''The full path to the directory containing release artifacts.''') + subparser.add_argument('--userid', + help='''The (optional) USER-ID specifying the key to be + used for signing, such as '110B1C95' (Key-ID). If + omitted, uses the default key.''') # Setup the parser for the post-candidates subcommand subparser = subparsers.add_parser('post-candidates', @@ -1247,8 +1466,26 @@ def main(): # Setup the parser for the create-tag subcommand subparser = subparsers.add_parser('create-tag', - help='''Create the release tag.''') - subparser.set_defaults(func=create_tag) + help='''Create the release tag and, if not a prerelease + version, bump version numbers on the branch.''') + subparser.set_defaults(func=create_tag_and_bump_versions) + subparser.add_argument('version', type=Version, + help='''The release label, such as '1.7.0-alpha1'.''') + subparser.add_argument('revnum', type=lambda arg: int(arg.lstrip('r')), + help='''The revision number to base the release on.''') + subparser.add_argument('--branch', + help='''The branch to base the release on, + relative to ^/subversion/.''') + subparser.add_argument('--username', + help='''Username for ''' + secure_repos + '''.''') + subparser.add_argument('--target', + help='''The full path to the directory containing + release artifacts.''') + + # Setup the parser for the bump-versions-on-branch subcommand + subparser = subparsers.add_parser('bump-versions-on-branch', + help='''Bump version numbers on branch.''') + subparser.set_defaults(func=bump_versions_on_branch) subparser.add_argument('version', type=Version, help='''The release label, such as '1.7.0-alpha1'.''') subparser.add_argument('revnum', type=lambda arg: int(arg.lstrip('r')), @@ -1288,6 +1525,11 @@ def main(): help='''Output to stdout template text for use in the news section of the Subversion website.''') subparser.set_defaults(func=write_news) + subparser.add_argument('--announcement-url', + help='''The URL to the archived announcement email.''') + subparser.add_argument('--edit-html-file', + help='''Insert the text into this file + news.html, index.html).''') subparser.add_argument('version', type=Version, help='''The release label, such as '1.7.0-alpha1'.''') @@ -1338,6 +1580,29 @@ def main(): separate subcommand.''') subparser.set_defaults(func=cleanup) + # write-changelog + subparser = subparsers.add_parser('write-changelog', + help='''Output to stdout changelog entries parsed from + commit messages, optionally labeled with a category + like [U:client], [D:api], [U], ...''') + subparser.set_defaults(func=write_changelog) + subparser.add_argument('branch', + help='''The branch (or tag or trunk), relative to + ^/subversion/, of which to generate the + changelog, when compared to "previous".''') + subparser.add_argument('previous', + help='''The "previous" branch or tag, relative to + ^/subversion/, to compare "branch" against.''') + subparser.add_argument('--include-unlabeled-summaries', + dest='include_unlabeled', + action='store_true', default=False, + help='''Include summary lines that do not have a changes + label, unless an explicit [c:skip] or [c:ignore] + is part of the commit message (except if the + summary line contains 'STATUS', 'CHANGES', + 'Post-release housekeeping', 'Follow-up' or starts + with '*').''') + # Parse the arguments args = parser.parse_args() diff --git a/tools/dist/templates/download.ezt b/tools/dist/templates/download.ezt index 4c6fda8..19dac3d 100644 --- a/tools/dist/templates/download.ezt +++ b/tools/dist/templates/download.ezt @@ -2,16 +2,14 @@ <table class="centered"> <tr> <th>File</th> - <th>Checksum (SHA1)</th> <th>Checksum (SHA512)</th> <th>Signatures</th> </tr> [for fileinfo]<tr> <td><a href="[[]preferred]subversion/[fileinfo.filename]">[fileinfo.filename]</a></td> - <td class="checksum">[fileinfo.sha1]</td> <!-- The sha512 line does not have a class="checksum" since the link needn't be rendered in monospace. --> - <td>[<a href="http://www.apache.org/dist/subversion/[fileinfo.filename].sha512">SHA-512</a>]</td> - <td>[<a href="http://www.apache.org/dist/subversion/[fileinfo.filename].asc">PGP</a>]</td> + <td>[<a href="https://www.apache.org/dist/subversion/[fileinfo.filename].sha512">SHA-512</a>]</td> + <td>[<a href="https://www.apache.org/dist/subversion/[fileinfo.filename].asc">PGP</a>]</td> </tr>[end] </table> diff --git a/tools/dist/templates/rc-news.ezt b/tools/dist/templates/rc-news.ezt index a645ffa..04f094d 100644 --- a/tools/dist/templates/rc-news.ezt +++ b/tools/dist/templates/rc-news.ezt @@ -8,10 +8,10 @@ release is not intended for production use, but is provided as a milestone to encourage wider testing and feedback from intrepid users and maintainers. Please see the - <a href="">release + <a href="[announcement_url]">release announcement</a> for more information about this release, and the <a href="/docs/release-notes/[major-minor].html">release notes</a> and - <a href="http://svn.apache.org/repos/asf/subversion/tags/[version]/CHANGES"> + <a href="https://svn.apache.org/repos/asf/subversion/tags/[version]/CHANGES"> change log</a> for information about what will eventually be in the [version_base] release.</p> diff --git a/tools/dist/templates/rc-release-ann.ezt b/tools/dist/templates/rc-release-ann.ezt index ca5f4d0..6c089bd 100644 --- a/tools/dist/templates/rc-release-ann.ezt +++ b/tools/dist/templates/rc-release-ann.ezt @@ -5,12 +5,8 @@ Subject: [[]ANNOUNCE] Apache Subversion [version] released I'm happy to announce the release of Apache Subversion [version]. Please choose the mirror closest to you by visiting: - http://subversion.apache.org/download.cgi#[anchor] + https://subversion.apache.org/download.cgi#[anchor] -The SHA1 checksums are: - -[for sha1info] [sha1info.sha1] [sha1info.filename] -[end] SHA-512 checksums are available at: https://www.apache.org/dist/subversion/subversion-[version].tar.bz2.sha512 @@ -19,9 +15,9 @@ SHA-512 checksums are available at: PGP Signatures are available at: - http://www.apache.org/dist/subversion/subversion-[version].tar.bz2.asc - http://www.apache.org/dist/subversion/subversion-[version].tar.gz.asc - http://www.apache.org/dist/subversion/subversion-[version].zip.asc + https://www.apache.org/dist/subversion/subversion-[version].tar.bz2.asc + https://www.apache.org/dist/subversion/subversion-[version].tar.gz.asc + https://www.apache.org/dist/subversion/subversion-[version].zip.asc For this release, the following people have provided PGP signatures: @@ -57,13 +53,18 @@ end users please. Release notes for the [major-minor].x release series may be found at: - http://subversion.apache.org/docs/release-notes/[major-minor].html + https://subversion.apache.org/docs/release-notes/[major-minor].html You can find the list of changes between [version] and earlier versions at: - http://svn.apache.org/repos/asf/subversion/tags/[version]/CHANGES + https://svn.apache.org/repos/asf/subversion/tags/[version]/CHANGES Questions, comments, and bug reports to users@subversion.apache.org. Thanks, - The Subversion Team + +-- +To unsubscribe, please see: + + https://subversion.apache.org/mailing-lists.html#unsubscribing diff --git a/tools/dist/templates/stable-news.ezt b/tools/dist/templates/stable-news.ezt index 8fcaae9..4cd82ac 100644 --- a/tools/dist/templates/stable-news.ezt +++ b/tools/dist/templates/stable-news.ezt @@ -10,10 +10,10 @@ [else] This is the most complete release of the [major-minor].x line to date, and we encourage all users to upgrade as soon as reasonable. [end] Please see the - <a href="" + <a href="[announcement_url]" >release announcement</a> and the - <a href="http://svn.apache.org/repos/asf/subversion/tags/[version]/CHANGES" - >change log</a> for more information about this release.</p> + <a href="/docs/release-notes/[major-minor]" + >release notes</a> for more information about this release.</p> <p>To get this release from the nearest mirror, please visit our <a href="/download.cgi#[anchor]">download page</a>.</p> diff --git a/tools/dist/templates/stable-release-ann.ezt b/tools/dist/templates/stable-release-ann.ezt index 2aec041..d334de4 100644 --- a/tools/dist/templates/stable-release-ann.ezt +++ b/tools/dist/templates/stable-release-ann.ezt @@ -7,7 +7,7 @@ To: announce@subversion.apache.org, users@subversion.apache.org, dev@subversion. I'm happy to announce the release of Apache Subversion [version]. Please choose the mirror closest to you by visiting: - http://subversion.apache.org/download.cgi#[anchor] + https://subversion.apache.org/download.cgi#[anchor] [if-any dot-zero] This is a stable feature release of the Apache Subversion open source version control system. @@ -18,10 +18,6 @@ open source version control system. This is a stable bugfix release of the Apache Subversion open source version control system. [end][end] -The SHA1 checksums are: - -[for sha1info] [sha1info.sha1] [sha1info.filename] -[end] SHA-512 checksums are available at: https://www.apache.org/dist/subversion/subversion-[version].tar.bz2.sha512 @@ -30,22 +26,27 @@ SHA-512 checksums are available at: PGP Signatures are available at: - http://www.apache.org/dist/subversion/subversion-[version].tar.bz2.asc - http://www.apache.org/dist/subversion/subversion-[version].tar.gz.asc - http://www.apache.org/dist/subversion/subversion-[version].zip.asc + https://www.apache.org/dist/subversion/subversion-[version].tar.bz2.asc + https://www.apache.org/dist/subversion/subversion-[version].tar.gz.asc + https://www.apache.org/dist/subversion/subversion-[version].zip.asc For this release, the following people have provided PGP signatures: [siginfo] Release notes for the [major-minor].x release series may be found at: - http://subversion.apache.org/docs/release-notes/[major-minor].html + https://subversion.apache.org/docs/release-notes/[major-minor].html You can find the list of changes between [version] and earlier versions at: - http://svn.apache.org/repos/asf/subversion/tags/[version]/CHANGES + https://svn.apache.org/repos/asf/subversion/tags/[version]/CHANGES Questions, comments, and bug reports to users@subversion.apache.org. Thanks, - The Subversion Team + +-- +To unsubscribe, please see: + + https://subversion.apache.org/mailing-lists.html#unsubscribing diff --git a/tools/examples/svnlook.py b/tools/examples/svnlook.py index 5865e22..dd797a0 100755 --- a/tools/examples/svnlook.py +++ b/tools/examples/svnlook.py @@ -21,7 +21,7 @@ # under the License. ###################################################################### # -# $HeadURL: https://svn.apache.org/repos/asf/subversion/branches/1.10.x/tools/examples/svnlook.py $ +# $HeadURL: https://svn.apache.org/repos/asf/subversion/branches/1.11.x/tools/examples/svnlook.py $ # $LastChangedDate: 2013-11-14 11:11:07 +0000 (Thu, 14 Nov 2013) $ # $LastChangedRevision: 1541878 $ diff --git a/tools/hook-scripts/commit-access-control.pl.in b/tools/hook-scripts/commit-access-control.pl.in index 5710276..2a4c266 100755 --- a/tools/hook-scripts/commit-access-control.pl.in +++ b/tools/hook-scripts/commit-access-control.pl.in @@ -6,7 +6,7 @@ # commit in repository REPOS using the permissions listed in the # configuration file CONF_FILE. # -# $HeadURL: https://svn.apache.org/repos/asf/subversion/branches/1.10.x/tools/hook-scripts/commit-access-control.pl.in $ +# $HeadURL: https://svn.apache.org/repos/asf/subversion/branches/1.11.x/tools/hook-scripts/commit-access-control.pl.in $ # $LastChangedDate: 2009-11-16 19:07:17 +0000 (Mon, 16 Nov 2009) $ # $LastChangedBy: hwright $ # $LastChangedRevision: 880911 $ diff --git a/tools/hook-scripts/mailer/mailer.py b/tools/hook-scripts/mailer/mailer.py index c8d658c..9698298 100755 --- a/tools/hook-scripts/mailer/mailer.py +++ b/tools/hook-scripts/mailer/mailer.py @@ -22,10 +22,10 @@ # # mailer.py: send email describing a commit # -# $HeadURL: https://svn.apache.org/repos/asf/subversion/branches/1.10.x/tools/hook-scripts/mailer/mailer.py $ -# $LastChangedDate: 2017-01-07 19:35:49 +0000 (Sat, 07 Jan 2017) $ -# $LastChangedBy: julianfoad $ -# $LastChangedRevision: 1777846 $ +# $HeadURL: https://svn.apache.org/repos/asf/subversion/branches/1.11.x/tools/hook-scripts/mailer/mailer.py $ +# $LastChangedDate: 2018-02-18 19:06:38 +0000 (Sun, 18 Feb 2018) $ +# $LastChangedBy: danielsh $ +# $LastChangedRevision: 1824690 $ # # USAGE: mailer.py commit REPOS REVISION [CONFIG-FILE] # mailer.py propchange REPOS REVISION AUTHOR REVPROPNAME [CONFIG-FILE] @@ -71,16 +71,10 @@ _MIN_SVN_VERSION = [1, 5, 0] # Import the Subversion Python bindings, making sure they meet our # minimum version requirements. -try: - import svn.fs - import svn.delta - import svn.repos - import svn.core -except ImportError: - sys.stderr.write( - "You need version %s or better of the Subversion Python bindings.\n" \ - % ".".join([str(x) for x in _MIN_SVN_VERSION])) - sys.exit(1) +import svn.fs +import svn.delta +import svn.repos +import svn.core if _MIN_SVN_VERSION > [svn.core.SVN_VER_MAJOR, svn.core.SVN_VER_MINOR, svn.core.SVN_VER_PATCH]: diff --git a/tools/hook-scripts/svn2feed.py b/tools/hook-scripts/svn2feed.py index c3abe8c..bbe9cd1 100755 --- a/tools/hook-scripts/svn2feed.py +++ b/tools/hook-scripts/svn2feed.py @@ -70,7 +70,7 @@ Options: # is actually set only on initial feed creation, and thereafter simply # re-used from the pickle each time. -# $HeadURL: https://svn.apache.org/repos/asf/subversion/branches/1.10.x/tools/hook-scripts/svn2feed.py $ +# $HeadURL: https://svn.apache.org/repos/asf/subversion/branches/1.11.x/tools/hook-scripts/svn2feed.py $ # $LastChangedDate: 2016-04-30 08:16:53 +0000 (Sat, 30 Apr 2016) $ # $LastChangedBy: stefan2 $ # $LastChangedRevision: 1741723 $ diff --git a/tools/hook-scripts/svnperms.py b/tools/hook-scripts/svnperms.py index 6f059fa..6ee91e2 100755 --- a/tools/hook-scripts/svnperms.py +++ b/tools/hook-scripts/svnperms.py @@ -21,7 +21,7 @@ # # -# $HeadURL: https://svn.apache.org/repos/asf/subversion/branches/1.10.x/tools/hook-scripts/svnperms.py $ +# $HeadURL: https://svn.apache.org/repos/asf/subversion/branches/1.11.x/tools/hook-scripts/svnperms.py $ # $LastChangedDate: 2016-04-30 08:16:53 +0000 (Sat, 30 Apr 2016) $ # $LastChangedBy: stefan2 $ # $LastChangedRevision: 1741723 $ diff --git a/tools/server-side/fsfs-reshard.py b/tools/server-side/fsfs-reshard.py index d9937ad..25e19db 100755 --- a/tools/server-side/fsfs-reshard.py +++ b/tools/server-side/fsfs-reshard.py @@ -46,7 +46,7 @@ # under the License. # ==================================================================== # -# $HeadURL: https://svn.apache.org/repos/asf/subversion/branches/1.10.x/tools/server-side/fsfs-reshard.py $ +# $HeadURL: https://svn.apache.org/repos/asf/subversion/branches/1.11.x/tools/server-side/fsfs-reshard.py $ # $LastChangedDate: 2016-04-30 08:16:53 +0000 (Sat, 30 Apr 2016) $ # $LastChangedBy: stefan2 $ # $LastChangedRevision: 1741723 $ diff --git a/tools/server-side/svnauthz.c b/tools/server-side/svnauthz.c index fc6cd89..0744d07 100644 --- a/tools/server-side/svnauthz.c +++ b/tools/server-side/svnauthz.c @@ -110,29 +110,34 @@ static svn_opt_subcommand_t /* Array of available subcommands. * The entire list must be terminated with an entry of nulls. */ -static const svn_opt_subcommand_desc2_t cmd_table[] = +static const svn_opt_subcommand_desc3_t cmd_table[] = { - {"help", subcommand_help, {"?", "h"}, - ("usage: svnauthz help [SUBCOMMAND...]\n\n" - "Describe the usage of this program or its subcommands.\n"), + {"help", subcommand_help, {"?", "h"}, {( + "usage: svnauthz help [SUBCOMMAND...]\n" + "\n" + "Describe the usage of this program or its subcommands.\n" + )}, {0} }, - {"validate", subcommand_validate, {0} /* no aliases */, - ("Checks the syntax of an authz file.\n" + {"validate", subcommand_validate, {0} /* no aliases */, {( + "Checks the syntax of an authz file.\n" "usage: 1. svnauthz validate TARGET\n" - " 2. svnauthz validate --transaction TXN REPOS_PATH FILE_PATH\n\n" + " 2. svnauthz validate --transaction TXN REPOS_PATH FILE_PATH\n" + "\n" " 1. Loads and validates the syntax of the authz file at TARGET.\n" " TARGET can be a path to a file or an absolute file:// URL to an authz\n" - " file in a repository, but cannot be a repository relative URL (^/).\n\n" + " file in a repository, but cannot be a repository relative URL (^/).\n" + "\n" " 2. Loads and validates the syntax of the authz file at FILE_PATH in the\n" - " transaction TXN in the repository at REPOS_PATH.\n\n" + " transaction TXN in the repository at REPOS_PATH.\n" + "\n" "Returns:\n" " 0 when syntax is OK.\n" " 1 when syntax is invalid.\n" " 2 operational error\n" - ), + )}, {'t'} }, - {"accessof", subcommand_accessof, {0} /* no aliases */, - ("Print or test the permissions set by an authz file.\n" + {"accessof", subcommand_accessof, {0} /* no aliases */, {( + "Print or test the permissions set by an authz file.\n" "usage: 1. svnauthz accessof TARGET\n" " 2. svnauthz accessof -t TXN REPOS_PATH FILE_PATH\n" "\n" @@ -159,10 +164,10 @@ static const svn_opt_subcommand_desc2_t cmd_table[] = " 1 when syntax is invalid.\n" " 2 operational error\n" " 3 when '--is' argument doesn't match\n" - ), + )}, {'t', svnauthz__username, svnauthz__path, svnauthz__repos, svnauthz__is, svnauthz__groups_file, 'R'} }, - { NULL, NULL, {0}, NULL, {0} } + { NULL, NULL, {0}, {NULL}, {0} } }; static svn_error_t * @@ -171,11 +176,14 @@ subcommand_help(apr_getopt_t *os, void *baton, apr_pool_t *pool) struct svnauthz_opt_state *opt_state = baton; const char *header = ("general usage: svnauthz SUBCOMMAND TARGET [ARGS & OPTIONS ...]\n" - " " SVNAUTHZ_COMPAT_NAME " TARGET\n\n" + " " SVNAUTHZ_COMPAT_NAME " TARGET\n" + "\n" "If the command name starts with '" SVNAUTHZ_COMPAT_NAME "', runs in\n" - "pre-1.8 compatibility mode: run the 'validate' subcommand on TARGET.\n\n" + "pre-1.8 compatibility mode: run the 'validate' subcommand on TARGET.\n" + "\n" "Type 'svnauthz help <subcommand>' for help on a specific subcommand.\n" - "Type 'svnauthz --version' to see the program version.\n\n" + "Type 'svnauthz --version' to see the program version.\n" + "\n" "Available subcommands:\n"); const char *fs_desc_start @@ -186,7 +194,7 @@ subcommand_help(apr_getopt_t *os, void *baton, apr_pool_t *pool) version_footer = svn_stringbuf_create(fs_desc_start, pool); SVN_ERR(svn_fs_print_modules(version_footer, pool)); - SVN_ERR(svn_opt_print_help4(os, "svnauthz", + SVN_ERR(svn_opt_print_help5(os, "svnauthz", opt_state ? opt_state->version : FALSE, FALSE, /* quiet */ FALSE, /* verbose */ @@ -459,7 +467,7 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) { svn_error_t *err; - const svn_opt_subcommand_desc2_t *subcommand = NULL; + const svn_opt_subcommand_desc3_t *subcommand = NULL; struct svnauthz_opt_state opt_state = { 0 }; apr_getopt_t *os; apr_array_header_t *received_opts; @@ -545,9 +553,9 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) { /* Pre 1.8 compatibility mode. */ if (argc == 1) /* No path argument */ - subcommand = svn_opt_get_canonical_subcommand2(cmd_table, "help"); + subcommand = svn_opt_get_canonical_subcommand3(cmd_table, "help"); else - subcommand = svn_opt_get_canonical_subcommand2(cmd_table, "validate"); + subcommand = svn_opt_get_canonical_subcommand3(cmd_table, "validate"); } /* If the user asked for help, then the rest of the arguments are @@ -555,7 +563,7 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) just typos/mistakes. Whatever the case, the subcommand to actually run is subcommand_help(). */ if (opt_state.help) - subcommand = svn_opt_get_canonical_subcommand2(cmd_table, "help"); + subcommand = svn_opt_get_canonical_subcommand3(cmd_table, "help"); if (subcommand == NULL) { @@ -564,8 +572,8 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) if (opt_state.version) { /* Use the "help" subcommand to handle the "--version" option. */ - static const svn_opt_subcommand_desc2_t pseudo_cmd = - { "--version", subcommand_help, {0}, "", + static const svn_opt_subcommand_desc3_t pseudo_cmd = + { "--version", subcommand_help, {0}, {""}, {svnauthz__version /* must accept its own option */ } }; subcommand = &pseudo_cmd; @@ -585,7 +593,7 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) SVN_ERR(svn_utf_cstring_to_utf8(&first_arg, os->argv[os->ind++], pool)); - subcommand = svn_opt_get_canonical_subcommand2(cmd_table, first_arg); + subcommand = svn_opt_get_canonical_subcommand3(cmd_table, first_arg); if (subcommand == NULL) { os->ind++; @@ -658,11 +666,11 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) if (opt_id == 'h' || opt_id == '?') continue; - if (! svn_opt_subcommand_takes_option3(subcommand, opt_id, NULL)) + if (! svn_opt_subcommand_takes_option4(subcommand, opt_id, NULL)) { const char *optstr; const apr_getopt_option_t *badopt = - svn_opt_get_option_from_code2(opt_id, options_table, subcommand, + svn_opt_get_option_from_code3(opt_id, options_table, subcommand, pool); svn_opt_format_option(&optstr, badopt, FALSE, pool); if (subcommand->name[0] == '-') diff --git a/tools/server-side/svnpubsub/svnwcsub.py b/tools/server-side/svnpubsub/svnwcsub.py index 1a65b37..ca47293 100755 --- a/tools/server-side/svnpubsub/svnwcsub.py +++ b/tools/server-side/svnpubsub/svnwcsub.py @@ -32,7 +32,7 @@ # TODO: # - bulk update at startup time to avoid backlog warnings -# - fold BDEC into Daemon +# - fold BigDoEverythingClasss ("BDEC") into Daemon # - fold WorkingCopy._get_match() into __init__ # - remove wc_ready(). assume all WorkingCopy instances are usable. # place the instances into .watch at creation. the .update_applies() |