You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by ju...@apache.org on 2013/08/19 14:07:58 UTC
svn commit: r1515380 [15/15] - in /subversion/branches/move-tracking-1: ./
build/ac-macros/ build/generator/ build/generator/swig/
build/generator/templates/ contrib/client-side/emacs/ doc/programmer/
notes/http-and-webdav/ subversion/ subversion/bindi...
Modified: subversion/branches/move-tracking-1/tools/buildbot/slaves/win32-SharpSvn/svn-config.cmd.template
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-1/tools/buildbot/slaves/win32-SharpSvn/svn-config.cmd.template?rev=1515380&r1=1515379&r2=1515380&view=diff
==============================================================================
--- subversion/branches/move-tracking-1/tools/buildbot/slaves/win32-SharpSvn/svn-config.cmd.template (original)
+++ subversion/branches/move-tracking-1/tools/buildbot/slaves/win32-SharpSvn/svn-config.cmd.template Mon Aug 19 12:07:51 2013
@@ -29,3 +29,22 @@ SET TMP=%TEMP%
IF NOT EXIST "%TESTDIR%\" MKDIR "%TESTDIR%"
IF NOT EXIST "%TEMP%\" MKDIR "%TEMP%"
+
+
+
+
+
+SET SVN_URL=
+SET SVN_RELURL=
+for /F "usebackq tokens=1,* delims=:" %%i IN (`svn info .`) do (
+
+ IF "%%i" == "URL" (
+ SET SVN_URL=%%j
+ ) ELSE IF "%%i" == "Relative URL" (
+ SET SVN_RELURL=%%j
+ )
+)
+SET SVN_URL=%SVN_URL:~1%
+SET SVN_RELURL=%SVN_RELURL:~3%
+SET SVN_SUBBRANCH=%SVN_RELURL:~11%
+SET SVN_BRANCH=%SVN_SUBBRANCH:branches/=%
Modified: subversion/branches/move-tracking-1/tools/buildbot/slaves/win32-SharpSvn/svntest-bindings.cmd
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-1/tools/buildbot/slaves/win32-SharpSvn/svntest-bindings.cmd?rev=1515380&r1=1515379&r2=1515380&view=diff
==============================================================================
--- subversion/branches/move-tracking-1/tools/buildbot/slaves/win32-SharpSvn/svntest-bindings.cmd (original)
+++ subversion/branches/move-tracking-1/tools/buildbot/slaves/win32-SharpSvn/svntest-bindings.cmd Mon Aug 19 12:07:51 2013
@@ -22,10 +22,10 @@ SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDE
CALL ..\svn-config.cmd
IF ERRORLEVEL 1 EXIT /B 1
+ECHO ON
-svnversion . /1.6.x | find "S" > nul:
-IF ERRORLEVEL 1 (
- ECHO --- Building 1.6.x: Skipping bindings ---
+IF "%SVN_BRANCH%" LEQ "1.6.x" (
+ ECHO --- Building 1.6.x or older: Skipping bindings ---
EXIT /B 0
)
@@ -34,52 +34,79 @@ SET result=0
python win-tests.py -d -f fsfs --javahl "%TESTDIR%\tests"
IF ERRORLEVEL 1 (
- echo [python reported error %ERRORLEVEL%]
- SET result=1
-)
-
-IF EXIST "%TESTDIR%\swig" rmdir /s /q "%TESTDIR%\swig"
-mkdir "%TESTDIR%\swig\py-release\libsvn"
-mkdir "%TESTDIR%\swig\py-release\svn"
-
-xcopy "release\subversion\bindings\swig\python\*.pyd" "%TESTDIR%\swig\py-release\libsvn\*.pyd" > nul:
-xcopy "release\subversion\bindings\swig\python\libsvn_swig_py\*.dll" "%TESTDIR%\swig\py-release\libsvn\*.dll" > nul:
-xcopy "subversion\bindings\swig\python\*.py" "%TESTDIR%\swig\py-release\libsvn\*.py" > nul:
-xcopy "subversion\bindings\swig\python\svn\*.py" "%TESTDIR%\swig\py-release\svn\*.py" > nul:
-
-SET PYTHONPATH=%TESTDIR%\swig\py-release
-
-python subversion\bindings\swig\python\tests\run_all.py
-IF ERRORLEVEL 1 (
- echo [Python reported error %ERRORLEVEL%]
+ echo [python reported error !ERRORLEVEL!]
SET result=1
)
-mkdir "%TESTDIR%\swig\pl-release\SVN"
-mkdir "%TESTDIR%\swig\pl-release\auto\SVN"
-xcopy subversion\bindings\swig\perl\native\*.pm "%TESTDIR%\swig\pl-release\SVN" > nul:
-pushd release\subversion\bindings\swig\perl\native
-for %%i in (*.dll) do (
- set name=%%i
- mkdir "%TESTDIR%\swig\pl-release\auto\SVN\!name:~0,-4!"
- xcopy "!name:~0,-4!.*" "%TESTDIR%\swig\pl-release\auto\SVN\!name:~0,-4!" > nul:
- xcopy /y "_Core.dll" "%TESTDIR%\swig\pl-release\auto\SVN\!name:~0,-4!" > nul:
-)
-popd
+if "%SVN_BRANCH%" GTR "1.9." (
-svnversion . /1.7.x | find "S" > nul:
-IF ERRORLEVEL 1 (
- ECHO --- Building 1.7.x: Skipping perl tests ---
- EXIT /B %result%
-)
+ python win-tests.py -r -f fsfs --swig=python "%TESTDIR%\tests"
-SET PERL5LIB=%PERL5LIB%;%TESTDIR%\swig\pl-release;
-pushd subversion\bindings\swig\perl\native
-perl -MExtUtils::Command::MM -e test_harness() t\*.t
-IF ERRORLEVEL 1 (
- echo [Perl reported error %ERRORLEVEL%]
- SET result=1
+ IF ERRORLEVEL 1 (
+ echo [Python tests exited with error !ERRORLEVEL!]
+ SET result=1
+ )
+
+) ELSE (
+ IF EXIST "%TESTDIR%\swig" rmdir /s /q "%TESTDIR%\swig"
+ mkdir "%TESTDIR%\swig\py-release\libsvn"
+ mkdir "%TESTDIR%\swig\py-release\svn"
+
+ xcopy "release\subversion\bindings\swig\python\*.pyd" "%TESTDIR%\swig\py-release\libsvn\*.pyd" > nul:
+ xcopy "release\subversion\bindings\swig\python\libsvn_swig_py\*.dll" "%TESTDIR%\swig\py-release\libsvn\*.dll" > nul:
+ xcopy "subversion\bindings\swig\python\*.py" "%TESTDIR%\swig\py-release\libsvn\*.py" > nul:
+ xcopy "subversion\bindings\swig\python\svn\*.py" "%TESTDIR%\swig\py-release\svn\*.py" > nul:
+
+ SET PYTHONPATH=%TESTDIR%\swig\py-release
+
+ python subversion\bindings\swig\python\tests\run_all.py
+ IF ERRORLEVEL 1 (
+ echo [Python tests exited with error !ERRORLEVEL!]
+ SET result=1
+ )
+)
+
+if "%SVN_BRANCH%" GTR "1.9." (
+
+ python win-tests.py -d -f fsfs --swig=perl "%TESTDIR%\tests"
+
+ IF ERRORLEVEL 1 (
+ echo [Perl tests exited with error !ERRORLEVEL!]
+ SET result=1
+ )
+
+) ELSE IF "%SVN_BRANCH%" GTR "1.8." (
+
+ mkdir "%TESTDIR%\swig\pl-debug\SVN"
+ mkdir "%TESTDIR%\swig\pl-debug\auto\SVN"
+ xcopy subversion\bindings\swig\perl\native\*.pm "%TESTDIR%\swig\pl-debug\SVN" > nul:
+ pushd debug\subversion\bindings\swig\perl\native
+ for %%i in (*.dll) do (
+ set name=%%i
+ mkdir "%TESTDIR%\swig\pl-debug\auto\SVN\!name:~0,-4!"
+ xcopy "!name:~0,-4!.*" "%TESTDIR%\swig\pl-debug\auto\SVN\!name:~0,-4!" > nul:
+ xcopy /y "_Core.dll" "%TESTDIR%\swig\pl-debug\auto\SVN\!name:~0,-4!" > nul:
+ )
+ popd
+
+
+ SET PERL5LIB=%PERL5LIB%;%TESTDIR%\swig\pl-debug;
+ pushd subversion\bindings\swig\perl\native
+ perl -MExtUtils::Command::MM -e "test_harness()" t\*.t
+ IF ERRORLEVEL 1 (
+ echo [Perl reported error !ERRORLEVEL!]
+ SET result=1
+ )
+ popd
+)
+
+if "%SVN_BRANCH%" GTR "1.9." (
+ python win-tests.py -d -f fsfs --swig=ruby "%TESTDIR%\tests"
+
+ IF ERRORLEVEL 1 (
+ echo [Ruby tests reported error !ERRORLEVEL!] (not fatal)
+ REM SET result=1
+ )
)
-popd
exit /b %result%
Modified: subversion/branches/move-tracking-1/tools/buildbot/slaves/win32-SharpSvn/svntest-build-bindings.cmd
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-1/tools/buildbot/slaves/win32-SharpSvn/svntest-build-bindings.cmd?rev=1515380&r1=1515379&r2=1515380&view=diff
==============================================================================
--- subversion/branches/move-tracking-1/tools/buildbot/slaves/win32-SharpSvn/svntest-build-bindings.cmd (original)
+++ subversion/branches/move-tracking-1/tools/buildbot/slaves/win32-SharpSvn/svntest-build-bindings.cmd Mon Aug 19 12:07:51 2013
@@ -23,14 +23,26 @@ SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDE
CALL ..\svn-config.cmd
IF ERRORLEVEL 1 EXIT /B 1
-svnversion . /1.6.x | find "S" > nul:
-IF ERRORLEVEL 1 (
+IF "%SVN_BRANCH%" LEQ "1.6.x" (
ECHO --- Building 1.6.x: Skipping bindings ---
EXIT /B 0
)
-msbuild subversion_vcnet.sln /p:Configuration=Debug /p:Platform=win32 /t:__JAVAHL__ /t:__JAVAHL_TESTS__
+SET DEBUG_TARGETS=/t:__JAVAHL__ /t:__JAVAHL_TESTS__
+SET RELEASE_TARGETS=/t:__SWIG_PYTHON__
+
+if "%SVN_BRANCH%" GTR "1.8." (
+ SET DEBUG_TARGETS=%DEBUG_TARGETS% /t:__SWIG_PERL__
+)
+
+if "%SVN_BRANCH%" GTR "1.9." (
+ SET DEBUG_TARGETS=%DEBUG_TARGETS% /t:__SWIG_RUBY__
+)
+
+msbuild subversion_vcnet.sln /m /p:Configuration=Debug /p:Platform=win32 %DEBUG_TARGETS%
IF ERRORLEVEL 1 EXIT /B 1
-msbuild subversion_vcnet.sln /p:Configuration=Release /p:Platform=win32 /t:__SWIG_PYTHON__ /t:__SWIG_PERL__
+msbuild subversion_vcnet.sln /p:Configuration=Release /p:Platform=win32 %RELEASE_TARGETS%
IF ERRORLEVEL 1 EXIT /B 1
+
+EXIT /B 0
\ No newline at end of file
Modified: subversion/branches/move-tracking-1/tools/client-side/svn-bench/svn-bench.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-1/tools/client-side/svn-bench/svn-bench.c?rev=1515380&r1=1515379&r2=1515380&view=diff
==============================================================================
--- subversion/branches/move-tracking-1/tools/client-side/svn-bench/svn-bench.c (original)
+++ subversion/branches/move-tracking-1/tools/client-side/svn-bench/svn-bench.c Mon Aug 19 12:07:51 2013
@@ -278,7 +278,7 @@ check_lib_versions(void)
};
SVN_VERSION_DEFINE(my_version);
- return svn_ver_check_list(&my_version, checklist);
+ return svn_ver_check_list2(&my_version, checklist, svn_ver_equal);
}
Modified: subversion/branches/move-tracking-1/tools/dev/build-svn-deps-win.pl
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-1/tools/dev/build-svn-deps-win.pl?rev=1515380&r1=1515379&r2=1515380&view=diff
==============================================================================
--- subversion/branches/move-tracking-1/tools/dev/build-svn-deps-win.pl (original)
+++ subversion/branches/move-tracking-1/tools/dev/build-svn-deps-win.pl Mon Aug 19 12:07:51 2013
@@ -51,7 +51,6 @@
# Usage/help output from the usual flags/on error input.
# Make SQLITE_VER friendly since we're using no dots right now.
# Work out the fixes to the projects' sources and contribute them back.
-# Allow selection of Release/Debug builds.
# Allow selection of Arch (x86 and x64)
# ZLib support for OpenSSL (have to patch openssl)
# Use CMake zlib build instead.
@@ -135,7 +134,8 @@ our $SRCDIR; # directory where we store
# Some other options
our $VS_VER;
our $NEON;
-our $SVN_VER = '1.8.x';
+our $SVN_VER = '1.9.x';
+our $DEBUG = 0;
# Utility function to remove dots from a string
sub remove_dots {
@@ -351,6 +351,7 @@ sub clean_structure {
rmtree($INCDIR);
rmtree($LIBDIR);
rmtree("$INSTDIR\\serf");
+ rmtree("$INSTDIR\\neon");
rmtree("$INSTDIR\\sqlite-amalgamation");
# Dirs created indirectly by the install targets
@@ -422,7 +423,7 @@ sub download_dependencies {
download_file($PCRE_URL, "$SRCDIR\\pcre.zip", \$PCRE_FILE);
download_file($SQLITE_URL, "$SRCDIR\\sqlite-amalgamation.zip", \$SQLITE_FILE);
download_file($SERF_URL, "$SRCDIR\\serf.zip", \$SERF_FILE);
- download_file($NEON_URL, "$SRCDIR\\neon.tar.gz", \$NEON_FILE) if defined($NEON);
+ download_file($NEON_URL, "$SRCDIR\\neon.tar.gz", \$NEON_FILE) if $NEON;
}
##############
@@ -488,7 +489,7 @@ sub extract_dependencies {
extract_file($SERF_FILE, $INSTDIR,
"$INSTDIR\\serf-$SERF_VER", "$INSTDIR\\serf");
extract_file($NEON_FILE, $INSTDIR,
- "$INSTDIR\\neon-$NEON_VER", "$INSTDIR\\neon") if defined($NEON);
+ "$INSTDIR\\neon-$NEON_VER", "$INSTDIR\\neon") if $NEON;
}
#########
@@ -499,7 +500,7 @@ sub build_pcre {
chdir_or_die("$SRCLIB\\pcre");
my $pcre_generator = 'NMake Makefiles';
# Have to use RelWithDebInfo since httpd looks for the pdb files
- my $pcre_build_type = '-DCMAKE_BUILD_TYPE:STRING=RelWithDebInfo';
+ my $pcre_build_type = '-DCMAKE_BUILD_TYPE:STRING=' . ($DEBUG ? 'Debug' : 'RelWithDebInfo');
my $pcre_shared_libs = '-DBUILD_SHARED_LIBS:BOOL=ON';
my $pcre_install_prefix = "-DCMAKE_INSTALL_PREFIX:PATH=$INSTDIR";
my $cmake_cmd = qq("$CMAKE" -G "$pcre_generator" "$pcre_build_type" "$pcre_shared_libs" "$pcre_install_prefix" .);
@@ -514,7 +515,7 @@ sub build_pcre {
# build generates, it it doesn't match that then Subversion will fail to build.
sub build_zlib {
chdir_or_die("$SRCLIB\\zlib");
- $ENV{CC_OPTS} = '/MD /02 /Zi';
+ $ENV{CC_OPTS} = $DEBUG ? '/MDd /Gm /ZI /Od /GZ /D_DEBUG' : '/MD /02 /Zi';
$ENV{COMMON_CC_OPTS} = '/nologo /W3 /DWIN32 /D_WINDOWS';
system_or_die("Failure building zilb", qq("$NMAKE" /nologo -f win32\\Makefile.msc STATICLIB=zlibstat.lib all));
@@ -543,8 +544,9 @@ sub build_openssl {
# The apache build docs suggest no-rc5 no-idea enable-mdc2 on top of what
# is used below, the primary driver behind that is patents, but I believe
# the rc5 and idea patents have expired.
+ my $platform = $DEBUG ? 'debug-VC-WIN32' : 'VC-WIN32';
system_or_die("Failure configuring openssl",
- qq("$PERL" Configure no-asm "--prefix=$INSTDIR" VC-WIN32));
+ qq("$PERL" Configure no-asm "--prefix=$INSTDIR" $platform));
system_or_die("Failure building openssl (bat)", 'ms\do_ms.bat');
system_or_die("Failure building openssl (nmake)", qq("$NMAKE" /f ms\\ntdll.mak));
system_or_die("Failure testing openssl", qq("$NMAKE" /f ms\\ntdll.mak test));
@@ -601,6 +603,9 @@ sub httpd_fix_makefile {
modify_file_in_place($file, sub {
s/\.vcproj/.vcxproj/i;
+ # below fixes that installd breaks when trying to install pcre because
+ # dll is named pcred.dll when a Debug build.
+ s/^(\s*copy srclib\\pcre\\pcre\.\$\(src_dll\)\s+"\$\(inst_dll\)"\s+<\s*\.y\s*)$/!IF EXISTS("srclib\\pcre\\pcre\.\$(src_dll)")\n$1!ENDIF\n!IF EXISTS("srclib\\pcre\\pcred\.\$(src_dll)")\n\tcopy srclib\\pcre\\pcred.\$(src_dll)\t\t\t"\$(inst_dll)" <.y\n!ENDIF\n/;
});
}
@@ -650,8 +655,9 @@ sub get_output_file {
# Find the name of the bdb library we've installed in our LIBDIR.
sub find_bdb_lib {
my $result;
+ my $debug = $DEBUG ? 'd' : '';
find(sub {
- if (not defined($result) and /^libdb\d+\.lib$/) {
+ if (not defined($result) and /^libdb\d+$debug\.lib$/) {
$result = $_;
}
}, $LIBDIR);
@@ -688,12 +694,25 @@ sub httpd_enable_bdb {
insert_dependency_in_proj('support\htdbm.vcxproj', $bdb_lib, '.bdb');
}
+# Apply the same fix as found in r1486937 on httpd 2.4.x branch.
+sub httpd_fix_debug {
+ my ($httpd_major, $httpd_minor, $httpd_patch) = $HTTPD_VER =~ /^(\d+)\.(\d+)\.(.+)$/;
+ return unless ($httpd_major <= 2 && $httpd_minor <= 4 && $httpd_patch < 5);
+
+ modify_file_in_place('libhttpd.dsp', sub {
+ s/^(!MESSAGE "libhttpd - Win32 Debug" \(based on "Win32 \(x86\) Dynamic-Link Library"\))$/$1\n!MESSAGE "libhttpd - Win32 Lexical" (based on "Win32 (x86) Dynamic-Link Library")/;
+ s/^(# Begin Group "headers")$/# Name "libhttpd - Win32 Lexical"\n$1/;
+ }, '.lexical');
+}
+
sub build_httpd {
chdir_or_die($HTTPD);
my $vs_2012 = $VS_VER eq '2012';
my $vs_2010 = $VS_VER eq '2010';
+ httpd_fix_debug();
+
# I don't think cvtdsp.pl is necessary with Visual Studio 2012
# but it shouldn't hurt anything either. Including it allows
# for the possibility that this may work for older Visual Studio
@@ -763,8 +782,9 @@ sub build_httpd {
# configurations inside the project since we get them from the environment.
# Once all that is done the BuildBin project should be buildable for you to
# diagnose the problem.
+ my $target = $DEBUG ? "installd" : "installr";
system_or_die("Failed building/installing httpd/apr/apu/api",
- qq("$NMAKE" /f Makefile.win installr "DBM_LIST=db" "INSTDIR=$INSTDIR"));
+ qq("$NMAKE" /f Makefile.win $target "DBM_LIST=db" "INSTDIR=$INSTDIR"));
chdir_or_die($TOPDIR);
}
@@ -776,13 +796,15 @@ sub build_bdb {
my $sln = 'build_windows\Berkeley_DB_vs2010.sln';
upgrade_solution($sln);
+ my $platform = $DEBUG ? 'Debug|Win32' : 'Release|Win32';
+
# Build the db Project first since the full solution fails due to a broken
# dependency with the current version of BDB if we don't.
system_or_die("Failed building DBD (Project db)",
- qq("$DEVENV" "$sln" /Build "Release|Win32" /Project db));
+ qq("$DEVENV" "$sln" /Build "$platform" /Project db));
system_or_die("Failed building DBD",
- qq("$DEVENV" "$sln" /Build "Release|Win32"));
+ qq("$DEVENV" "$sln" /Build "$platform"));
# BDB doesn't seem to have it's own install routines so we'll do it ourselves
copy_or_die('build_windows\db.h', $INCDIR);
@@ -792,16 +814,31 @@ sub build_bdb {
} elsif (/\.lib$/) {
copy_or_die($_, $LIBDIR);
}
- }, 'build_windows\Win32\Release');
+ }, 'build_windows\\Win32\\' . ($DEBUG ? 'Debug' : 'Release'));
chdir_or_die($TOPDIR);
}
+# Right now this doesn't actually build serf but just patches it so that it
+# can build against a debug build of OpenSSL.
+sub build_serf {
+ chdir_or_die("$TOPDIR\\serf");
+
+ modify_file_in_place('serf.mak', sub {
+ s/^(INTDIR = Release)$/$1\nOPENSSL_OUT_SUFFIX =/;
+ s/^(INTDIR = Debug)$/$1\nOPENSSL_OUT_SUFFIX = .dbg/;
+ s/(\$\(OPENSSL_SRC\)\\out32(?:dll)?)/$1\$(OPENSSL_OUT_SUFFIX)/g;
+ }, '.debug');
+
+ chdir_or_die($TOPDIR);
+}
+
sub build_dependencies {
build_bdb();
build_zlib();
build_pcre();
build_openssl();
+ build_serf();
build_httpd();
}
Modified: subversion/branches/move-tracking-1/tools/dev/fsfs-access-map.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-1/tools/dev/fsfs-access-map.c?rev=1515380&r1=1515379&r2=1515380&view=diff
==============================================================================
--- subversion/branches/move-tracking-1/tools/dev/fsfs-access-map.c (original)
+++ subversion/branches/move-tracking-1/tools/dev/fsfs-access-map.c Mon Aug 19 12:07:51 2013
@@ -92,6 +92,9 @@ typedef struct handle_info_t
typedef unsigned char byte;
typedef unsigned short word;
+/* an RGB color */
+typedef byte color_t[3];
+
/* global const char * file name -> *file_info_t map */
static apr_hash_t *files = NULL;
@@ -188,6 +191,14 @@ open_file(const char *name, int handle)
else
file->rev_num = -1;
+ /* filter out log/phys index files */
+ if (file->rev_num >= 0)
+ {
+ const char *suffix = name + strlen(name) - 4;
+ if (strcmp(suffix, ".l2p") == 0 || strcmp(suffix, ".p2l") == 0)
+ file->rev_num = -1;
+ }
+
apr_hash_set(files, file->name, APR_HASH_KEY_STRING, file);
}
@@ -275,10 +286,17 @@ parse_line(svn_stringbuf_t *line)
char *return_value = strrchr(line->data, ' ');
char *first_param_end;
apr_int64_t func_return = 0;
+ char *func_start = strchr(line->data, ' ');
if (func_end == NULL || return_value == NULL)
return;
+ if (func_start == NULL || func_start > func_end)
+ func_start = line->data;
+ else
+ while(*func_start == ' ')
+ func_start++;
+
first_param_end = strchr(func_end, ',');
if (first_param_end == NULL)
first_param_end = strchr(func_end, ')');
@@ -295,7 +313,7 @@ parse_line(svn_stringbuf_t *line)
svn_error_clear(svn_cstring_atoi64(&func_return, return_value));
/* process those operations that we care about */
- if (strcmp(line->data, "open") == 0)
+ if (strcmp(func_start, "open") == 0)
{
/* remove double quotes from file name parameter */
*func_end++ = 0;
@@ -303,11 +321,11 @@ parse_line(svn_stringbuf_t *line)
open_file(func_end, (int)func_return);
}
- else if (strcmp(line->data, "read") == 0)
+ else if (strcmp(func_start, "read") == 0)
read_file(atoi(func_end), func_return);
- else if (strcmp(line->data, "lseek") == 0)
+ else if (strcmp(func_start, "lseek") == 0)
seek_file(atoi(func_end), func_return);
- else if (strcmp(line->data, "close") == 0)
+ else if (strcmp(func_start, "close") == 0)
close_file(atoi(func_end));
}
@@ -494,17 +512,82 @@ write_bitmap_header(apr_file_t *file, in
apr_file_write(file, header, &written);
}
-/* write the cluster read map for all files in INFO as BMP image to FILE.
+/* To COLOR, add the fractional value of SOURCE from fractional indexes
+ * SOURCE_START to SOURCE_END and apply the SCALING_FACTOR.
+ */
+static void
+add_sample(color_t color,
+ color_t *source,
+ double source_start,
+ double source_end,
+ double scaling_factor)
+{
+ double factor = (source_end - source_start) / scaling_factor;
+
+ apr_size_t i;
+ for (i = 0; i < sizeof(color_t) / sizeof(*color); ++i)
+ color[i] += (source_end - source_start < 0.5) && source_start > 1.0
+ ? factor * source[(apr_size_t)source_start - 1][i]
+ : factor * source[(apr_size_t)source_start][i];
+}
+
+/* Scale the IN_LEN RGB values from IN to OUT_LEN RGB values in OUT.
+ */
+static void
+scale_line(color_t* out,
+ apr_size_t out_len,
+ color_t *in,
+ apr_size_t in_len)
+{
+ double scaling_factor = (double)(in_len) / (double)(out_len);
+
+ apr_size_t i;
+ memset(out, 0, out_len * sizeof(color_t));
+ for (i = 0; i < out_len; ++i)
+ {
+ color_t color = { 0 };
+
+ double source_start = i * scaling_factor;
+ double source_end = (i + 1) * scaling_factor;
+
+ if ((apr_size_t)source_start == (apr_size_t)source_end)
+ {
+ add_sample(color, in, source_start, source_end, scaling_factor);
+ }
+ else
+ {
+ apr_size_t k;
+ apr_size_t first_sample_end = (apr_size_t)source_start + 1;
+ apr_size_t last_sample_start = (apr_size_t)source_end;
+
+ add_sample(color, in, source_start, first_sample_end, scaling_factor);
+ for (k = first_sample_end; k < last_sample_start; ++k)
+ add_sample(color, in, k, k + 1, scaling_factor);
+
+ add_sample(color, in, last_sample_start, source_end, scaling_factor);
+ }
+
+ memcpy(out[i], color, sizeof(color));
+ }
+}
+
+/* Write the cluster read map for all files in INFO as BMP image to FILE.
+ * If MAX_X is not 0, scale all lines to MAX_X pixels. Use POOL for
+ * allocations.
*/
static void
-write_bitmap(apr_array_header_t *info, apr_file_t *file)
+write_bitmap(apr_array_header_t *info,
+ apr_size_t max_x,
+ apr_file_t *file,
+ apr_pool_t *pool)
{
int ysize = info->nelts;
int xsize = 0;
int x, y;
int row_size;
- int padding;
apr_size_t written;
+ color_t *line, *scaled_line;
+ svn_boolean_t do_scale = max_x > 0;
/* xsize = max cluster number */
for (y = 0; y < ysize; ++y)
@@ -516,37 +599,40 @@ write_bitmap(apr_array_header_t *info, a
xsize = 0x3fff;
if (ysize >= 0x4000)
ysize = 0x3fff;
+ if (max_x == 0)
+ max_x = xsize;
/* rows in BMP files must be aligned to 4 bytes */
- row_size = APR_ALIGN(xsize * 3, 4);
- padding = row_size - xsize * 3;
+ row_size = APR_ALIGN(max_x * sizeof(color_t), 4);
+ /**/
+ line = apr_pcalloc(pool, xsize * sizeof(color_t));
+ scaled_line = apr_pcalloc(pool, row_size);
+
/* write header to file */
- write_bitmap_header(file, xsize, ysize);
+ write_bitmap_header(file, max_x, ysize);
/* write all rows */
for (y = 0; y < ysize; ++y)
{
file_stats_t *file_info = APR_ARRAY_IDX(info, y, file_stats_t *);
+ int block_count = file_info->read_map->nelts;
for (x = 0; x < xsize; ++x)
{
- byte color[3] = { 128, 128, 128 };
- if (x < file_info->read_map->nelts)
+ color_t color = { 128, 128, 128 };
+ if (x < block_count)
{
word count = APR_ARRAY_IDX(file_info->read_map, x, word);
select_color(color, count);
}
- written = sizeof(color);
- apr_file_write(file, color, &written);
+ memcpy(line[x], color, sizeof(color));
}
- if (padding)
- {
- char pad[3] = { 0 };
- written = padding;
- apr_file_write(file, pad, &written);
- }
+ scale_line(scaled_line, max_x, line, block_count ? block_count : 1);
+
+ written = row_size;
+ apr_file_write(file, do_scale ? scaled_line : line, &written);
}
}
@@ -665,7 +751,13 @@ int main(int argc, const char *argv[])
apr_file_open(&file, "access.bmp",
APR_WRITE | APR_CREATE | APR_TRUNCATE | APR_BUFFERED,
APR_OS_DEFAULT, pool);
- write_bitmap(get_rev_files(pool), file);
+ write_bitmap(get_rev_files(pool), 0, file, pool);
+ apr_file_close(file);
+
+ apr_file_open(&file, "access_scaled.bmp",
+ APR_WRITE | APR_CREATE | APR_TRUNCATE | APR_BUFFERED,
+ APR_OS_DEFAULT, pool);
+ write_bitmap(get_rev_files(pool), 1024, file, pool);
apr_file_close(file);
apr_file_open(&file, "scale.bmp",
Modified: subversion/branches/move-tracking-1/tools/dev/fsfs-reorg.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-1/tools/dev/fsfs-reorg.c?rev=1515380&r1=1515379&r2=1515380&view=diff
==============================================================================
--- subversion/branches/move-tracking-1/tools/dev/fsfs-reorg.c (original)
+++ subversion/branches/move-tracking-1/tools/dev/fsfs-reorg.c Mon Aug 19 12:07:51 2013
@@ -29,6 +29,7 @@
#include <apr_file_io.h>
#include <apr_poll.h>
+#include "svn_private_config.h"
#include "svn_pools.h"
#include "svn_diff.h"
#include "svn_io.h"
Modified: subversion/branches/move-tracking-1/tools/dev/svnraisetreeconflict/svnraisetreeconflict.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-1/tools/dev/svnraisetreeconflict/svnraisetreeconflict.c?rev=1515380&r1=1515379&r2=1515380&view=diff
==============================================================================
--- subversion/branches/move-tracking-1/tools/dev/svnraisetreeconflict/svnraisetreeconflict.c (original)
+++ subversion/branches/move-tracking-1/tools/dev/svnraisetreeconflict/svnraisetreeconflict.c Mon Aug 19 12:07:51 2013
@@ -187,7 +187,7 @@ raise_tree_conflict(int argc, const char
{
int i = 0;
svn_wc_conflict_version_t *left, *right;
- svn_wc_conflict_description2_t *c;
+ svn_wc_conflict_description3_t *c;
svn_wc_context_t *wc_ctx;
/* Conflict description parameters */
@@ -223,7 +223,7 @@ raise_tree_conflict(int argc, const char
peg_rev1, kind1, pool);
right = svn_wc_conflict_version_create2(repos_url2, NULL, path_in_repos2,
peg_rev2, kind2, pool);
- c = svn_wc_conflict_description_create_tree2(wc_abspath, kind,
+ c = svn_wc_conflict_description_create_tree3(wc_abspath, kind,
operation, left, right, pool);
c->action = (svn_wc_conflict_action_t)action;
c->reason = (svn_wc_conflict_reason_t)reason;
@@ -311,7 +311,7 @@ check_lib_versions(void)
};
SVN_VERSION_DEFINE(my_version);
- return svn_ver_check_list(&my_version, checklist);
+ return svn_ver_check_list2(&my_version, checklist, svn_ver_equal);
}
int
Modified: subversion/branches/move-tracking-1/tools/dev/unix-build/Makefile.svn
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-1/tools/dev/unix-build/Makefile.svn?rev=1515380&r1=1515379&r2=1515380&view=diff
==============================================================================
--- subversion/branches/move-tracking-1/tools/dev/unix-build/Makefile.svn (original)
+++ subversion/branches/move-tracking-1/tools/dev/unix-build/Makefile.svn Mon Aug 19 12:07:51 2013
@@ -70,9 +70,9 @@ APR_VER = 1.4.6
APR_ICONV_VER = 1.2.1
GNU_ICONV_VER = 1.14
APR_UTIL_VER = 1.4.1
-HTTPD_VER = 2.2.22
+HTTPD_VER = 2.2.25
NEON_VER = 0.29.6
-SERF_VER = 1.2.1
+SERF_VER = 1.3.1
SERF_OLD_VER = 0.3.1
CYRUS_SASL_VER = 2.1.25
SQLITE_VER = 3071600
@@ -548,15 +548,35 @@ httpd-reset:
httpd-clean:
-(cd $(HTTPD_OBJDIR) && make clean)
+ rm -f $(HTTPD_OBJDIR)/no_ssl_v2.diff
# fetch distfile for httpd
$(DISTDIR)/$(HTTPD_DIST):
cd $(DISTDIR) && $(FETCH_CMD) $(HTTPD_URL)
+$(HTTPD_OBJDIR)/no_ssl_v2.diff:
+ mkdir -p $(dir $@)
+ echo > $@.tmp '--- modules/ssl/ssl_engine_io.c.orig Sat Jul 13 16:49:52 2013'
+ echo >> $@.tmp '+++ modules/ssl/ssl_engine_io.c Sat Jul 13 16:50:10 2013'
+ echo >> $@.tmp '@@ -1079,7 +1079,9 @@'
+ echo >> $@.tmp ' * IPv4 and IPv6 addresses are not permitted".)'
+ echo >> $@.tmp ' */'
+ echo >> $@.tmp ' if (hostname_note &&'
+ echo >> $@.tmp '+#ifndef OPENSSL_NO_SSL2'
+ echo >> $@.tmp ' sc->proxy->protocol != SSL_PROTOCOL_SSLV2 &&'
+ echo >> $@.tmp '+#endif'
+ echo >> $@.tmp ' sc->proxy->protocol != SSL_PROTOCOL_SSLV3 &&'
+ echo >> $@.tmp ' apr_ipsubnet_create(&ip, hostname_note, NULL,'
+ echo >> $@.tmp ' c->pool) != APR_SUCCESS) {'
+ mv -f $@.tmp $@
+
# retrieve httpd
-$(HTTPD_OBJDIR)/.retrieved: $(DISTDIR)/$(HTTPD_DIST)
+$(HTTPD_OBJDIR)/.retrieved: $(DISTDIR)/$(HTTPD_DIST) \
+ $(HTTPD_OBJDIR)/no_ssl_v2.diff
[ -d $(HTTPD_OBJDIR) ] || mkdir -p $(HTTPD_OBJDIR)
tar -C $(SRCDIR) -jxf $(DISTDIR)/$(HTTPD_DIST)
+ cd $(SRCDIR)/httpd-$(HTTPD_VER) && \
+ patch -p0 < $(HTTPD_OBJDIR)/no_ssl_v2.diff
touch $@
# configure httpd
@@ -687,7 +707,7 @@ serf-reset:
rm -f $(SERF_OBJDIR)/$(f);)
serf-clean:
- -(cd $(SERF_SRCDIR) && ./serfmake clean)
+ -(cd $(SERF_SRCDIR) && scons -c)
# fetch distfile for serf
@@ -713,19 +733,16 @@ $(SERF_OBJDIR)/.retrieved:
# compile serf (serf won't compile outside its source tree)
$(SERF_OBJDIR)/.compiled: $(SERF_OBJDIR)/.retrieved
cd $(SERF_SRCDIR) && \
- env CFLAGS="-O0 -g $(PROFILE_CFLAGS)" \
- ./serfmake --with-apr=$(PREFIX)/apr \
- --prefix=$(PREFIX)/serf \
- build
+ scons DEBUG=1 CFLAGS="-O0 -g $(PROFILE_CFLAGS)" \
+ APR=$(PREFIX)/apr \
+ APU=$(PREFIX)/apr \
+ PREFIX=$(PREFIX)/serf
touch $@
# install serf
$(SERF_OBJDIR)/.installed: $(SERF_OBJDIR)/.compiled
cd $(SERF_SRCDIR) && \
- ./serfmake --with-apr=$(PREFIX)/apr \
- --with-apr-util=$(PREFIX)/apr \
- --prefix=$(PREFIX)/serf \
- install
+ scons install
touch $@
#######################################################################
Modified: subversion/branches/move-tracking-1/tools/dist/backport.pl
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-1/tools/dist/backport.pl?rev=1515380&r1=1515379&r2=1515380&view=diff
==============================================================================
--- subversion/branches/move-tracking-1/tools/dist/backport.pl (original)
+++ subversion/branches/move-tracking-1/tools/dist/backport.pl Mon Aug 19 12:07:51 2013
@@ -20,59 +20,104 @@ use feature qw/switch say/;
# specific language governing permissions and limitations
# under the License.
+use Digest ();
use Term::ReadKey qw/ReadMode ReadKey/;
+use File::Basename qw/basename dirname/;
use File::Copy qw/copy move/;
use File::Temp qw/tempfile/;
-use POSIX qw/ctermid/;
+use POSIX qw/ctermid strftime/;
+use Text::Wrap qw/wrap/;
+use Tie::File ();
+############### Start of reading values from environment ###############
+
+# Programs we use.
+my $SVNAUTH = $ENV{SVNAUTH} // 'svnauth'; # optional dependency
my $SVN = $ENV{SVN} || 'svn'; # passed unquoted to sh
+my $SHELL = $ENV{SHELL} // '/bin/sh';
my $VIM = 'vim';
-my $STATUS = './STATUS';
-my $BRANCHES = '^/subversion/branches';
-my %ERRORS = ();
+my $EDITOR = $ENV{SVN_EDITOR} // $ENV{VISUAL} // $ENV{EDITOR} // 'ed';
+my $PAGER = $ENV{PAGER} // 'less -F' // 'cat';
+
+# Mode flags.
+# svn-role: YES=1 MAY_COMMIT=1
+# conflicts-bot: YES=1 MAY_COMMIT=0
+# interactive: YES=0 MAY_COMMIT=0 (default)
+my $YES = exists $ENV{YES}; # batch mode: eliminate prompts, add sleeps
+my $MAY_COMMIT = 'false';
+$MAY_COMMIT = 'true' if ($ENV{MAY_COMMIT} // "false") =~ /^(1|yes|true)$/i;
-my $YES = ($ENV{YES} // 0) ? 1 : 0; # batch mode: eliminate prompts, add sleeps
-my $MAY_COMMIT = qw[false true][0];
-my $DEBUG = qw[false true][0]; # 'set -x', etc
+# Other knobs.
+my $VERBOSE = 0;
+my $DEBUG = (exists $ENV{DEBUG}) ? 'true' : 'false'; # 'set -x', etc
+
+# Username for entering votes.
+my $SVN_A_O_REALM = '<https://svn.apache.org:443> ASF Committers';
my ($AVAILID) = $ENV{AVAILID} // do {
- my $SVN_A_O_REALM = 'd3c8a345b14f6a1b42251aef8027ab57';
- open USERNAME, '<', "$ENV{HOME}/.subversion/auth/svn.simple/$SVN_A_O_REALM";
- 1 until <USERNAME> eq "username\n";
- <USERNAME>;
- local $_ = <USERNAME>;
- chomp;
- $_
+ local $_ = `$SVNAUTH list 2>/dev/null`;
+ ($? == 0 && /Auth.*realm: \Q$SVN_A_O_REALM\E\nUsername: (.*)/) ? $1 : undef
+} // do {
+ local $/; # slurp mode
+ my $filename = Digest->new("MD5")->add($SVN_A_O_REALM)->hexdigest;
+ `cat $ENV{HOME}/.subversion/auth/svn.simple/$filename`
+ =~ /K 8\nusername\nV \d+\n(.*)/ and $1 or undef
}
// warn "Username for commits (of votes/merges) not found";
-my $EDITOR = $ENV{SVN_EDITOR} // $ENV{VISUAL} // $ENV{EDITOR} // 'ed';
-my $VERBOSE = 0;
-$DEBUG = 'true' if exists $ENV{DEBUG};
-$MAY_COMMIT = 'true' if ($ENV{MAY_COMMIT} // "false") =~ /^(1|yes|true)$/i;
-# derived values
+############## End of reading values from the environment ##############
+
+# Constants.
+my $STATUS = './STATUS';
+my $STATEFILE = './.backports1';
+my $BRANCHES = '^/subversion/branches';
+
+# Globals.
+my %ERRORS = ();
+my $MERGED_SOMETHING = 0;
my $SVNq;
+
+# Derived values.
my $SVNvsn = do {
my ($major, $minor, $patch) = `$SVN --version -q` =~ /^(\d+)\.(\d+)\.(\d+)/;
1e6*$major + 1e3*$minor + $patch;
};
-
$SVN .= " --non-interactive" if $YES or not defined ctermid;
$SVNq = "$SVN -q ";
$SVNq =~ s/-q// if $DEBUG eq 'true';
-sub usage {
- my $basename = $0;
- $basename =~ s#.*/##;
+
+sub backport_usage {
+ my $basename = basename $0;
print <<EOF;
-backport.pl: a tool for reviewing and merging STATUS entries. Run this with
-CWD being the root of the stable branch (e.g., 1.8.x). The ./STATUS file
-should be at HEAD.
+backport.pl: a tool for reviewing, merging, and voting on STATUS entries.
+
+Normally, invoke this with CWD being the root of the stable branch (e.g.,
+1.8.x):
+
+ Usage: test -e \$d/STATUS && cd \$d && \\
+ backport.pl [PATTERN]
+ (where \$d is a working copy of branches/1.8.x)
+
+Alternatively, invoke this via a symlink named "b" placed at the same directory
+as the STATUS file, in which case the CWD doesn't matter (the script will cd):
+
+ Usage: ln -s /path/to/backport.pl \$d/b && \\
+ \$d/b [PATTERN]
+ (where \$d is a working copy of branches/1.8.x)
+
+In either case, the ./STATUS file should be at HEAD. If it has local mods,
+they will be preserved through 'revert' operations but included in 'commit'
+operations.
+
+If PATTERN is provided, only entries which match PATTERN are considered. The
+sense of "match" is either substring (fgrep) or Perl regexp (with /msi).
In interactive mode (the default), you will be prompted once per STATUS entry.
At a prompt, you have the following options:
y: Run a merge. It will not be committed.
WARNING: This will run 'update' and 'revert -R ./'.
+l: Show logs for the entries being nominated.
q: Quit the "for each nomination" loop.
±1: Enter a +1 or -1 vote
You will be prompted to commit your vote at the end.
@@ -83,7 +128,10 @@ a: Move the entry to the "Approved cha
to enter a third +1 vote, type "a" "+" "1".
e: Edit the entry in $EDITOR.
You will be prompted to commit your edits at the end.
-N: Move to the next entry.
+N: Move to the next entry. Cache the entry in '$STATEFILE' and do not
+ prompt for it again (even across runs) until it is changed.
+ : Move to the next entry, without adding the current one to the cache.
+ (That's a space character, ASCII 0x20.)
After running a merge, you have the following options:
@@ -91,25 +139,58 @@ y: Open a shell.
d: View a diff.
N: Move to the next entry.
-There is also a batch mode: when \$YES and \$MAY_COMMIT are defined to '1' i
+There is also a batch mode (normally used only by cron jobs and buildbot tasks,
+rather than interactively): when \$YES and \$MAY_COMMIT are defined to '1' in
the environment, this script will iterate the "Approved:" section, and merge
and commit each entry therein. If only \$YES is defined, the script will
merge every nomination (including unapproved and vetoed ones), and complain
-to stderr if it notices any conflicts. These mode are normally used by the
-'svn-role' cron job and/or buildbot, not by human users.
+to stderr if it notices any conflicts.
The 'svn' binary defined by the environment variable \$SVN, or otherwise the
'svn' found in \$PATH, will be used to manage the working copy.
EOF
}
+sub nominate_usage {
+ my $basename = basename $0;
+ print <<EOF;
+nominate.pl: a tool for adding entries to STATUS.
+
+Usage: $0 "foo r42 bar r43 qux 45." "\$Some_justification"
+
+Will add:
+ * r42, r43, r45
+ (log message of r42)
+ Justification:
+ \$Some_justification
+ Votes:
+ +1: $AVAILID
+to STATUS. Backport branches are detected automatically.
+
+The STATUS file in the current directory is used (unless argv[0] is "n", in
+which case the STATUS file in the directory of argv[0] is used; the intent
+is to create a symlink named "n" in the branch wc root).
+
+EOF
+# TODO: Optionally add a "Notes" section.
+# TODO: Look for backport branches named after issues.
+# TODO: Do a dry-run merge on added entries.
+# TODO: Do a dry-run merge on interactively-edited entries in backport.pl
+}
+
+sub digest_string {
+ Digest->new("MD5")->add(@_)->hexdigest
+}
+
sub prompt {
- print "$_[0] "; shift;
+ print $_[0]; shift;
my %args = @_;
my $getchar = sub {
+ my $answer;
ReadMode 'cbreak';
- my $answer = (ReadKey 0);
- ReadMode 'cbreak';
+ eval { $answer = (ReadKey 0) };
+ ReadMode 'normal';
+ die $@ if $@;
print $answer;
return $answer;
};
@@ -117,41 +198,52 @@ sub prompt {
die "$0: called prompt() in non-interactive mode!" if $YES;
my $answer = $getchar->();
$answer .= $getchar->() if exists $args{extra} and $answer =~ $args{extra};
- say "";
+ say "" unless $args{dontprint};
return $args{verbose}
? $answer
: ($answer =~ /^y/i) ? 1 : 0;
}
+
sub merge {
my %entry = @_;
+ $MERGED_SOMETHING++;
my ($logmsg_fh, $logmsg_filename) = tempfile();
my ($mergeargs, $pattern);
- my $backupfile = "backport_pl.$$.tmp";
+ # Include the time so it's easier to find the interesting backups.
+ my $backupfile = strftime "backport_pl.%Y%m%d-%H%M%S.$$.tmp", localtime;
+ die if -s $backupfile;
if ($entry{branch}) {
- # NOTE: This doesn't escape the branch into the pattern.
- $pattern = sprintf '\V\(%s branch(es)?\|branches\/%s\|Branch\(es\)\?: \*\n\? \*%s\)', $entry{branch}, $entry{branch}, $entry{branch};
+ my $vim_escaped_branch =
+ join "",
+ map { sprintf '\[%s%s]', $_, ($_ x ($_ eq '\\')) }
+ split //,
+ $entry{branch};
+ $pattern = sprintf '\VBranch: \*\n\? \*\(\.\*\/branches\/\)\?%s',
+ $vim_escaped_branch;
if ($SVNvsn >= 1_008_000) {
$mergeargs = "$BRANCHES/$entry{branch}";
- say $logmsg_fh "Merge the $entry{header}:";
+ say $logmsg_fh "Merge $entry{header}:";
} else {
$mergeargs = "--reintegrate $BRANCHES/$entry{branch}";
- say $logmsg_fh "Reintegrate the $entry{header}:";
+ say $logmsg_fh "Reintegrate $entry{header}:";
}
say $logmsg_fh "";
} elsif (@{$entry{revisions}}) {
$pattern = '^ [*] \V' . 'r' . $entry{revisions}->[0];
- $mergeargs = join " ", (map { "-c$_" } @{$entry{revisions}}), '^/subversion/trunk';
- if (@{$entry{revisions}} > 1) {
- say $logmsg_fh "Merge the $entry{header} from trunk:";
- say $logmsg_fh "";
- } else {
- say $logmsg_fh "Merge r$entry{revisions}->[0] from trunk:";
- say $logmsg_fh "";
- }
+ $mergeargs = join " ",
+ ($entry{accept} ? "--accept=$entry{accept}" : ()),
+ (map { "-c$_" } @{$entry{revisions}}),
+ '--',
+ '^/subversion/trunk';
+ say $logmsg_fh
+ "Merge $entry{header} from trunk",
+ $entry{accept} ? ", with --accept=$entry{accept}" : "",
+ ":";
+ say $logmsg_fh "";
} else {
die "Don't know how to call $entry{header}";
}
@@ -188,7 +280,7 @@ fi
if $MAY_COMMIT; then
$VIM -e -s -n -N -i NONE -u NONE -c '/$pattern/normal! dap' -c wq $STATUS
$SVNq commit -F $logmsg_filename
-elif test 1 -ne $YES; then
+elif test -z "\$YES"; then
echo "Would have committed:"
echo '[[['
$SVN status -q
@@ -205,7 +297,7 @@ if $MAY_COMMIT; then
if [ -n "\$YES" ]; then sleep 15; fi
$SVNq rm $BRANCHES/$entry{branch} -m "Remove the '$entry{branch}' branch, $reintegrated_word in r\$reinteg_rev."
if [ -n "\$YES" ]; then sleep 1; fi
-elif test 1 -ne $YES; then
+elif test -z "\$YES"; then
echo "Would remove $reintegrated_word '$entry{branch}' branch"
fi
EOF
@@ -213,7 +305,7 @@ EOF
open SHELL, '|-', qw#/bin/sh# or die "$! (in '$entry{header}')";
print SHELL $script;
close SHELL or warn "$0: sh($?): $! (in '$entry{header}')";
- $ERRORS{$entry{id}} = "sh($?): $!" if $?;
+ $ERRORS{$entry{id}} = [\%entry, "sh($?): $!"] if $?;
if (-z $backupfile) {
unlink $backupfile;
@@ -232,10 +324,18 @@ sub sanitize_branch {
return $_;
}
+sub logsummarysummary {
+ my $entry = shift;
+ join "",
+ $entry->{logsummary}->[0], ('[...]' x (0 < $#{$entry->{logsummary}}))
+}
+
# TODO: may need to parse other headers too?
sub parse_entry {
- my $lines = shift;
+ my $raw = shift;
my @lines = @_;
+ my $depends;
+ my $accept;
my (@revisions, @logsummary, $branch, @votes);
# @lines = @_;
@@ -245,6 +345,7 @@ sub parse_entry {
# revisions
$branch = sanitize_branch $1
+ and shift
if $_[0] =~ /^(\S*) branch$/ or $_[0] =~ m#branches/(\S+)#;
while ($_[0] =~ /^r/) {
my $sawrevnum = 0;
@@ -264,29 +365,64 @@ sub parse_entry {
unshift @votes, pop until $_[-1] =~ /^\s*Votes:/ or not defined $_[-1];
pop;
- # branch
+ # depends, branch, notes
while (@_) {
- shift and next unless $_[0] =~ s/^\s*Branch(es)?:\s*//;
- $branch = sanitize_branch (shift || shift || die "Branch header found without value");
+ given (shift) {
+ when (/^Depends:/) {
+ $depends++;
+ }
+ if (s/^Branch:\s*//) {
+ $branch = sanitize_branch ($_ || shift || die "Branch header found without value");
+ }
+ if (s/^Notes:\s*//) {
+ my $notes = $_;
+ $notes .= shift while @_ and $_[0] !~ /^\w/;
+ my %accepts = map { $_ => 1 } ($notes =~ /--accept[ =]([a-z-]+)/g);
+ given (scalar keys %accepts) {
+ when (0) { }
+ when (1) { $accept = [keys %accepts]->[0]; }
+ default {
+ warn "Too many --accept values at '",
+ logsummarysummary({ logsummary => [@logsummary] }),
+ "'";
+ }
+ }
+ }
+ }
}
# Compute a header.
my ($header, $id);
- $header = "r$revisions[0] group" if @revisions;
- $id = "r$revisions[0]" if @revisions;
- $header = "$branch branch" if $branch;
- $id = $branch if $branch;
- warn "No header for [@lines]" unless $header;
+ if ($branch) {
+ $header = "the $branch branch";
+ $id = $branch;
+ } elsif (@revisions == 1) {
+ $header = "r$revisions[0]";
+ $id = "r$revisions[0]";
+ } elsif (@revisions) {
+ $header = "the r$revisions[0] group";
+ $id = "r$revisions[0]";
+ } else {
+ die "Entry '$raw' has neither revisions nor branch";
+ }
+ my $header_start = ($header =~ /^the/ ? ucfirst($header) : $header);
+
+ warn "Entry has both branch '$branch' and --accept=$accept specified\n"
+ if $branch and $accept;
return (
revisions => [@revisions],
logsummary => [@logsummary],
branch => $branch,
header => $header,
+ header_start => $header_start,
+ depends => $depends,
id => $id,
votes => [@votes],
entry => [@lines],
- raw => $lines,
+ accept => $accept,
+ raw => $raw,
+ digest => digest_string($raw),
);
}
@@ -296,77 +432,146 @@ sub edit_string {
die "$0: called edit_string() in non-interactive mode!" if $YES;
my $string = shift;
my $name = shift;
+ my %args = @_;
+ my $trailing_eol = $args{trailing_eol};
my ($fh, $fn) = tempfile;
print $fh $string;
$fh->flush or die $!;
system("$EDITOR -- $fn") == 0
or warn "\$EDITOR failed editing $name: $! ($?); "
."edit results ($fn) ignored.";
- return `cat $fn`;
+ my $rv = `cat $fn`;
+ $rv =~ s/\n*\z// and $rv .= ("\n" x $trailing_eol) if defined $trailing_eol;
+ $rv;
}
sub vote {
- my ($approved, $votes) = @_;
+ my ($state, $approved, $votes) = @_;
+ # TODO: use votesarray instead of votescheck
+ my (%approvedcheck, %votescheck);
my $raw_approved = "";
- my @votes;
+ my @votesarray;
return unless %$approved or %$votes;
+ my $had_empty_line;
+
$. = 0;
open STATUS, "<", $STATUS;
open VOTES, ">", "$STATUS.$$.tmp";
while (<STATUS>) {
- unless (exists $votes->{$.}) {
- (exists $approved->{$.}) ? ($raw_approved .= $_) : (print VOTES);
+ $had_empty_line = /\n\n\z/;
+ my $key = digest_string $_;
+
+ $approvedcheck{$key}++ if exists $approved->{$key};
+ $votescheck{$key}++ if exists $votes->{$key};
+
+ unless (exists $votes->{$key} or exists $approved->{$key}) {
+ print VOTES;
next;
}
- my ($vote, $entry) = @{$votes->{$.}};
- push @{$votes->{$.}}, 1;
- push @votes, [$vote, $entry];
+ unless (exists $votes->{$key}) {
+ push @votesarray, {
+ entry => $approved->{$key},
+ approval => 1,
+ digest => $key,
+ };
+ $raw_approved .= $_;
+ next;
+ }
+
+ # We have a vote, and potentially an approval.
+
+ my ($vote, $entry) = @{$votes->{$key}};
+ push @votesarray, {
+ entry => $entry,
+ vote => $vote,
+ approval => (exists $approved->{$key}),
+ digest => $key,
+ };
if ($vote eq 'edit') {
local $_ = $entry->{raw};
- (exists $approved->{$.}) ? ($raw_approved .= $_) : (print VOTES);
+ $votesarray[-1]->{digest} = digest_string $_;
+ (exists $approved->{$key}) ? ($raw_approved .= $_) : (print VOTES);
next;
}
s/^(\s*\Q$vote\E:.*)/"$1, $AVAILID"/me
or s/(.*\w.*?\n)/"$1 $vote: $AVAILID\n"/se;
- $_ = edit_string $_, $entry->{header} if $vote ne '+1';
- (exists $approved->{$.}) ? ($raw_approved .= $_) : (print VOTES);
+ $_ = edit_string $_, $entry->{header}, trailing_eol => 2
+ if $vote ne '+1';
+ $votesarray[-1]->{digest} = digest_string $_;
+ (exists $approved->{$key}) ? ($raw_approved .= $_) : (print VOTES);
}
close STATUS;
+ print VOTES "\n" if $raw_approved and !$had_empty_line;
print VOTES $raw_approved;
close VOTES;
- die "Some vote chunks weren't found: "
- if grep scalar(@$_) != 3, values %$votes;
+ warn "Some vote chunks weren't found: ",
+ join ',',
+ map $votes->{$_}->[1]->{id},
+ grep { !$votescheck{$_} } keys %$votes
+ if scalar(keys %$votes) != scalar(keys %votescheck);
+ warn "Some approval chunks weren't found: ",
+ join ',',
+ map $approved->{$_}->{id},
+ grep { !$approvedcheck{$_} } keys %$approved
+ if scalar(keys %$approved) != scalar(keys %approvedcheck);
+ prompt "Press the 'any' key to continue...\n", dontprint => 1
+ if scalar(keys %$approved) != scalar(keys %approvedcheck)
+ or scalar(keys %$votes) != scalar(keys %votescheck);
move "$STATUS.$$.tmp", $STATUS;
my $logmsg = do {
- my %allkeys = map { $_ => 1 } keys(%$votes), keys(%$approved);
my @sentences = map {
- exists $votes->{$_}
+ my $words_vote = ", approving" x $_->{approval};
+ my $words_edit = " and approve" x $_->{approval};
+ exists $_->{vote}
? (
- ( $votes->{$_}->[0] eq 'edit'
- ? "Edit the $votes->{$_}->[1]->{id} entry"
- : "Vote $votes->{$_}->[0] on the $votes->{$_}->[1]->{header}"
+ ( $_->{vote} eq 'edit'
+ ? "Edit$words_edit the $_->{entry}->{id} entry"
+ : "Vote $_->{vote} on $_->{entry}->{header}$words_vote"
)
- . (exists $approved->{$_} ? ", approving" : "")
. "."
)
: # exists only in $approved
- "Approve the $approved->{$_}->{header}."
- } keys %allkeys;
+ "Approve $_->{entry}->{header}."
+ } @votesarray;
(@sentences == 1)
? $sentences[0]
: "* STATUS:\n" . join "", map " $_\n", @sentences;
};
- system $SVN, qw/diff --/, $STATUS;
- say "Voting '$_->[0]' on $_->[1]->{header}." for @votes;
- # say $logmsg;
- system $SVN, qw/commit -m/, $logmsg, qw/--/, $STATUS
- if prompt "Commit these votes? ";
+ system "$SVN diff -- $STATUS";
+ printf "[[[\n%s%s]]]\n", $logmsg, ("\n" x ($logmsg !~ /\n\z/));
+ if (prompt "Commit these votes? ") {
+ my ($logmsg_fh, $logmsg_filename) = tempfile();
+ print $logmsg_fh $logmsg;
+ close $logmsg_fh;
+ warn("Tempfile name '$logmsg_filename' not shell-safe; "
+ ."refraining from commit.\n") and return
+ unless $logmsg_filename =~ /^([A-Z0-9._-]|\x2f)+$/i;
+ system("$SVN commit -F $logmsg_filename -- $STATUS") == 0
+ or warn("Committing the votes failed($?): $!") and return;
+ unlink $logmsg_filename;
+
+ # Add to state votes that aren't '+0' or 'edit'
+ $state->{$_->{digest}}++ for grep
+ +{ qw/-1 t -0 t +1 t/ }->{$_->{vote}},
+ @votesarray;
+ }
+}
+
+sub check_local_mods_to_STATUS {
+ if (`$SVN status -q $STATUS`) {
+ die "Local mods to STATUS file $STATUS" if $YES;
+ warn "Local mods to STATUS file $STATUS";
+ system "$SVN diff -- $STATUS";
+ prompt "Press the 'any' key to continue...\n", dontprint => 1;
+ return 1;
+ }
+ return 0;
}
sub revert {
@@ -375,42 +580,85 @@ sub revert {
system "$SVN revert -R ./" . ($YES && $MAY_COMMIT ne 'true'
? " -q" : "");
move "$STATUS.$$.tmp", $STATUS;
+ $MERGED_SOMETHING = 0;
}
sub maybe_revert {
# This is both a SIGINT handler, and the tail end of main() in normal runs.
# @_ is 'INT' in the former case and () in the latter.
delete $SIG{INT} unless @_;
- revert if !$YES and prompt 'Revert? ';
+ revert if !$YES and $MERGED_SOMETHING and prompt 'Revert? ';
(@_ ? exit : return);
}
+sub signal_handler {
+ my $sig = shift;
+
+ # Clean up after prompt()
+ ReadMode 'normal';
+
+ # Fall back to default action
+ delete $SIG{$sig};
+ kill $sig, $$;
+}
+
sub warning_summary {
return unless %ERRORS;
warn "Warning summary\n";
warn "===============\n";
warn "\n";
- for my $header (keys %ERRORS) {
- warn "$header: $ERRORS{$header}\n";
+ for my $id (keys %ERRORS) {
+ my $title = logsummarysummary $ERRORS{$id}->[0];
+ warn "$id ($title): $ERRORS{$id}->[1]\n";
+ }
+}
+
+sub read_state {
+ # die "$0: called read_state() in non-interactive mode!" if $YES;
+
+ open my $fh, '<', $STATEFILE or do {
+ return {} if $!{ENOENT};
+ die "Can't read statefile: $!";
+ };
+
+ my %rv;
+ while (<$fh>) {
+ chomp;
+ $rv{$_}++;
}
+ return \%rv;
+}
+
+sub write_state {
+ my $state = shift;
+ open STATE, '>', $STATEFILE or warn("Can't write state: $!"), return;
+ say STATE for keys %$state;
+ close STATE;
}
sub exit_stage_left {
+ my $state = shift;
maybe_revert;
warning_summary if $YES;
- vote @_;
+ vote $state, @_;
+ write_state $state;
exit scalar keys %ERRORS;
}
sub handle_entry {
my $in_approved = shift;
- my $votes = shift;
my $approved = shift;
- my $lines = shift;
- my %entry = parse_entry $lines, @_;
+ my $votes = shift;
+ my $state = shift;
+ my $raw = shift;
+ my $skip = shift;
+ my %entry = parse_entry $raw, @_;
my @vetoes = grep { /^ -1:/ } @{$entry{votes}};
+ my $match = defined($skip) ? ($raw =~ /\Q$skip\E/ or $raw =~ /$skip/msi) : 0
+ unless $YES;
+
if ($YES) {
# Run a merge if:
unless (@vetoes) {
@@ -421,24 +669,47 @@ sub handle_entry {
# Scan-for-conflicts mode
merge %entry;
- my $output;
- if (($output = `$SVN status`) =~ /^(C|.C|...C)/m) {
- $ERRORS{$entry{id}} //= "Conflicts merging the $entry{header}!";
- say STDERR "Conflicts merging the $entry{header}!";
+ my $output = `$SVN status`;
+ my (@conflicts) = ($output =~ m#^(?:C...|.C..|...C)...\s(.*)#mg);
+ if (@conflicts and !$entry{depends}) {
+ $ERRORS{$entry{id}} //= [\%entry,
+ sprintf "Conflicts on %s%s%s",
+ '[' x !!$#conflicts,
+ (join ', ',
+ map { basename $_ }
+ @conflicts),
+ ']' x !!$#conflicts,
+ ];
+ say STDERR "Conflicts merging $entry{header}!";
say STDERR "";
say STDERR $output;
+ system "$SVN diff -- @conflicts";
+ } elsif (!@conflicts and $entry{depends}) {
+ # Not a warning since svn-role may commit the dependency without
+ # also committing the dependent in the same pass.
+ print "No conflicts merging $entry{header}, but conflicts were "
+ ."expected ('Depends:' header set)\n";
+ } elsif (@conflicts) {
+ say "Conflicts found merging $entry{header}, as expected.";
}
revert;
}
}
- } else {
+ } elsif (defined($skip) ? not $match : $state->{$entry{digest}}) {
+ print "\n\n";
+ my $reason = defined($skip) ? "doesn't match pattern"
+ : "remove $STATEFILE to reset";
+ say "Skipping $entry{header} ($reason):";
+ say logsummarysummary \%entry;
+ } elsif ($match or not defined $skip) {
# This loop is just a hack because 'goto' panics. The goto should be where
# the "next PROMPT;" is; there's a "last;" at the end of the loop body.
PROMPT: while (1) {
say "";
- say "\n>>> The $entry{header}:";
+ say "\n>>> $entry{header_start}:";
say join ", ", map { "r$_" } @{$entry{revisions}} if @{$entry{revisions}};
say "$BRANCHES/$entry{branch}" if $entry{branch};
+ say "--accept=$entry{accept}" if $entry{accept};
say "";
say for @{$entry{logsummary}};
say "";
@@ -446,45 +717,87 @@ sub handle_entry {
say "";
say "Vetoes found!" if @vetoes;
- given (prompt 'Go ahead? [y,±1,±0,q,e,a,N]',
+ # See above for why the while(1).
+ QUESTION: while (1) {
+ my $key = $entry{digest};
+ given (prompt 'Run a merge? [y,l,±1,±0,q,e,a, ,N] ',
verbose => 1, extra => qr/[+-]/) {
when (/^y/i) {
merge %entry;
while (1) {
- given (prompt "Shall I open a subshell? [ydN]", verbose => 1) {
+ given (prompt "Shall I open a subshell? [ydN] ", verbose => 1) {
when (/^y/i) {
- system($ENV{SHELL} // "/bin/sh") == 0
+ system($SHELL) == 0
or warn "Creating an interactive subshell failed ($?): $!"
}
when (/^d/) {
- system($SVN, 'diff') == 0
+ system("$SVN diff | $PAGER") == 0
or warn "diff failed ($?): $!";
next;
}
+ when (/^N/i) {
+ # fall through.
+ }
+ default {
+ next;
+ }
}
revert;
next PROMPT;
}
# NOTREACHED
}
+ when (/^l/i) {
+ if ($entry{branch}) {
+ system "$SVN log --stop-on-copy -v -g -r 0:HEAD -- "
+ ."$BRANCHES/$entry{branch} "
+ ."| $PAGER";
+ } elsif (@{$entry{revisions}}) {
+ system "$SVN log ".(join ' ', map { "-r$_" } @{$entry{revisions}})
+ ." -- ^/subversion | $PAGER";
+ } else {
+ die "Assertion failed: entry has neither branch nor revisions:\n",
+ '[[[', (join ';;', %entry), ']]]';
+ }
+ next PROMPT;
+ }
when (/^q/i) {
- exit_stage_left $approved, $votes;
+ exit_stage_left $state, $approved, $votes;
}
when (/^a/i) {
- $approved->{$.} = \%entry;
+ $approved->{$key} = \%entry;
next PROMPT;
}
when (/^([+-][01])\s*$/i) {
- $votes->{$.} = [$1, \%entry];
+ $votes->{$key} = [$1, \%entry];
say "Your '$1' vote has been recorded." if $VERBOSE;
+ last PROMPT;
}
when (/^e/i) {
- $entry{raw} = edit_string $entry{raw}, $entry{header};
- $votes->{$.} = ['edit', \%entry]; # marker for the 2nd pass
+ my $original = $entry{raw};
+ $entry{raw} = edit_string $entry{raw}, $entry{header},
+ trailing_eol => 2;
+ $votes->{$key} = ['edit', \%entry] # marker for the 2nd pass
+ if $original ne $entry{raw};
+ last PROMPT;
+ }
+ when (/^N/i) {
+ $state->{$entry{digest}}++;
+ last PROMPT;
+ }
+ when (/^\x20/) {
+ last PROMPT; # Fall off the end of the given/when block.
+ }
+ default {
+ say "Please use one of the options in brackets (q to quit)!";
+ next QUESTION;
}
}
- last;
- }
+ last; } # QUESTION
+ last; } # PROMPT
+ } else {
+ # NOTREACHED
+ die "Unreachable code reached.";
}
# TODO: merge() changes ./STATUS, which we're reading below, but
@@ -493,23 +806,31 @@ sub handle_entry {
1;
}
-sub main {
+
+sub backport_main {
my %approved;
my %votes;
+ my $state = read_state;
- usage, exit 0 if @ARGV;
+ backport_usage, exit 0 if @ARGV > ($YES ? 0 : 1) or grep /^--help$/, @ARGV;
+ backport_usage, exit 0 if grep /^(?:-h|-\?|--help|help)$/, @ARGV;
+ my $skip = shift; # maybe undef
+ # assert not defined $skip if $YES;
- open STATUS, "<", $STATUS or (usage, exit 1);
+ open STATUS, "<", $STATUS or (backport_usage, exit 1);
# Because we use the ':normal' command in Vim...
- die "A vim with the +ex_extra feature is required"
- if `${VIM} --version` !~ /[+]ex_extra/;
+ die "A vim with the +ex_extra feature is required for \$MAY_COMMIT mode"
+ if $MAY_COMMIT eq 'true' and `${VIM} --version` !~ /[+]ex_extra/;
# ### TODO: need to run 'revert' here
# ### TODO: both here and in merge(), unlink files that previous merges added
# When running from cron, there shouldn't be local mods. (For interactive
# usage, we preserve local mods to STATUS.)
- die "Local mods to STATUS file $STATUS" if $YES and `$SVN status -q $STATUS`;
+ system("$SVN info $STATUS >/dev/null") == 0
+ or die "$0: svn error; point \$SVN to an appropriate binary";
+
+ check_local_mods_to_STATUS;
# Skip most of the file
$/ = ""; # paragraph mode
@@ -518,6 +839,7 @@ sub main {
}
$SIG{INT} = \&maybe_revert unless $YES;
+ $SIG{TERM} = \&signal_handler unless $YES;
my $in_approved = 0;
while (<STATUS>) {
@@ -542,15 +864,112 @@ sub main {
when (/^ \*/) {
warn "Too many bullets in $lines[0]" and next
if grep /^ \*/, @lines[1..$#lines];
- handle_entry $in_approved, \%approved, \%votes, $lines, @lines;
+ handle_entry $in_approved, \%approved, \%votes, $state, $lines, $skip,
+ @lines;
}
default {
- warn "Unknown entry '$lines[0]' at line $.\n";
+ warn "Unknown entry '$lines[0]'";
}
}
}
- exit_stage_left \%approved, \%votes;
+ exit_stage_left $state, \%approved, \%votes;
+}
+
+sub nominate_main {
+ my $had_local_mods;
+
+ local $Text::Wrap::columns = 79;
+
+ $had_local_mods = check_local_mods_to_STATUS;
+
+ # Argument parsing.
+ nominate_usage, exit 0 if @ARGV != 2;
+ my (@revnums) = (+shift) =~ /(\d+)/g;
+ my $justification = shift;
+
+ @revnums = sort { $a <=> $b } keys %{{ map { $_ => 1 } @revnums }};
+ die "No revision numbers specified" unless @revnums;
+
+ # Determine whether a backport branch exists
+ my ($URL) = `$SVN info` =~ /^URL: (.*)$/m;
+ die "Can't retrieve URL of cwd" unless $URL;
+
+ die if $URL !~ m%^[A-Za-z0-9:_.+/][A-Za-z0-9:_.+/-]*$%;
+ system "$SVN info -- $URL-r$revnums[0] 2>/dev/null";
+ my $branch = ($? == 0) ? basename("$URL-r$revnums[0]") : undef;
+
+ # Construct entry.
+ my $logmsg = `$SVN propget --revprop -r $revnums[0] --strict svn:log '^/'`;
+ die "Can't fetch log message of r$revnums[0]: $!" unless $logmsg;
+
+ unless ($logmsg =~ s/^(.*?)\n\n.*/$1/s) {
+ # "* file\n (symbol): Log message."
+
+ # Strip before and after the first symbol's log message.
+ $logmsg =~ s/^.*?: //s;
+ $logmsg =~ s/^ \x28.*//ms;
+
+ # Undo line wrapping. (We'll re-do it later.)
+ $logmsg =~ s/\s*\n\s+/ /g;
+ }
+
+ my @lines;
+ warn "Wrapping [$logmsg]\n";
+ push @lines, wrap " * ", ' 'x3, join ', ', map "r$_", @revnums;
+ push @lines, wrap ' 'x3, ' 'x3, split /\n/, $logmsg;
+ push @lines, " Justification:";
+ push @lines, wrap ' 'x5, ' 'x5, $justification;
+ push @lines, " Branch: $branch" if defined $branch;
+ push @lines, " Votes:";
+ push @lines, " +1: $AVAILID";
+ push @lines, "";
+ my $raw = join "", map "$_\n", @lines;
+
+ # 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);
+ die "Couldn't find where to add an entry" unless $index;
+
+ # Add an empty line if needed.
+ if ($STATUS[$index-1] =~ /\S/) {
+ splice @STATUS, $index, 0, "";
+ $index++;
+ }
+
+ # Add the entry.
+ splice @STATUS, $index, 0, @lines;
+
+ # Save.
+ untie @STATUS;
+
+ # Done!
+ system "$SVN diff -- $STATUS";
+ if (prompt "Commit this nomination? ") {
+ system "$SVN commit -m 'Nominate r$revnums[0].' -- $STATUS";
+ exit $?;
+ }
+ elsif (!$had_local_mods or prompt "Revert STATUS (destroying local mods)? ") {
+ # TODO: we could be smarter and just un-splice the lines we'd added.
+ system "$SVN revert -- $STATUS";
+ exit $?;
+ }
+
+ exit 0;
}
-&main
+# Dispatch to the appropriate main().
+given (basename($0)) {
+ when (/^b$|backport/) {
+ chdir dirname $0 or die "Can't chdir: $!" if /^b$/;
+ &backport_main(@ARGV);
+ }
+ when (/^n$|nominate/) {
+ chdir dirname $0 or die "Can't chdir: $!" if /^n$/;
+ &nominate_main(@ARGV);
+ }
+ default {
+ &backport_main(@ARGV);
+ }
+}
Modified: subversion/branches/move-tracking-1/tools/examples/blame.py
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-1/tools/examples/blame.py?rev=1515380&r1=1515379&r2=1515380&view=diff
==============================================================================
--- subversion/branches/move-tracking-1/tools/examples/blame.py (original)
+++ subversion/branches/move-tracking-1/tools/examples/blame.py Mon Aug 19 12:07:51 2013
@@ -91,9 +91,9 @@ def blame(path, filename, rev=None):
# print ''.join(diffresult)
# print annotresult
for x in range(len(annotresult.keys())):
- sys.stdout.write("Line %d (rev %d):%s" % (x,
- annotresult[x][0],
- annotresult[x][1]))
+ sys.stdout.write("Line %d (r%d):%s" % (x,
+ annotresult[x][0],
+ annotresult[x][1]))
def usage():
print("USAGE: blame.py [-r REV] repos-path file")
Modified: subversion/branches/move-tracking-1/tools/server-side/fsfs-stats.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-1/tools/server-side/fsfs-stats.c?rev=1515380&r1=1515379&r2=1515380&view=diff
==============================================================================
--- subversion/branches/move-tracking-1/tools/server-side/fsfs-stats.c (original)
+++ subversion/branches/move-tracking-1/tools/server-side/fsfs-stats.c Mon Aug 19 12:07:51 2013
@@ -28,6 +28,7 @@
#include <apr_file_io.h>
#include <apr_poll.h>
+#include "svn_private_config.h"
#include "svn_pools.h"
#include "svn_diff.h"
#include "svn_io.h"
@@ -1240,7 +1241,7 @@ parse_dir(fs_fs_t *fs,
next = current ? strchr(++current, '\n') : NULL;
if (next == NULL)
return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
- _("Corrupt directory representation in rev %ld at offset %ld"),
+ _("Corrupt directory representation in r%ld at offset %ld"),
representation->revision,
(long)representation->offset);
@@ -1573,7 +1574,9 @@ read_revisions(fs_fs_t **fs,
svn_cache__get_global_membuffer_cache(),
NULL, NULL,
sizeof(window_cache_key_t),
- "", FALSE, pool));
+ "",
+ SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY,
+ FALSE, pool));
/* read all packed revs */
for ( revision = start_revision
Modified: subversion/branches/move-tracking-1/tools/server-side/svn-rep-sharing-stats.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-1/tools/server-side/svn-rep-sharing-stats.c?rev=1515380&r1=1515379&r2=1515380&view=diff
==============================================================================
--- subversion/branches/move-tracking-1/tools/server-side/svn-rep-sharing-stats.c (original)
+++ subversion/branches/move-tracking-1/tools/server-side/svn-rep-sharing-stats.c Mon Aug 19 12:07:51 2013
@@ -95,7 +95,8 @@ check_lib_versions(void)
};
SVN_VERSION_DEFINE(my_version);
- return svn_error_trace(svn_ver_check_list(&my_version, checklist));
+ return svn_error_trace(svn_ver_check_list2(&my_version, checklist,
+ svn_ver_equal));
}
Modified: subversion/branches/move-tracking-1/tools/server-side/svnauthz.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-1/tools/server-side/svnauthz.c?rev=1515380&r1=1515379&r2=1515380&view=diff
==============================================================================
--- subversion/branches/move-tracking-1/tools/server-side/svnauthz.c (original)
+++ subversion/branches/move-tracking-1/tools/server-side/svnauthz.c Mon Aug 19 12:07:51 2013
@@ -59,7 +59,9 @@ static const apr_getopt_option_t options
{"repository", svnauthz__repos, 1, ("repository authz name")},
{"transaction", 't', 1, ("transaction id")},
{"is", svnauthz__is, 1,
- ("instead of outputing, tests if the access is ARG\n"
+ ("instead of outputting, test if the access is\n"
+ " "
+ "exactly ARG\n"
" "
"ARG can be one of the following values:\n"
" "
@@ -67,10 +69,12 @@ static const apr_getopt_option_t options
" "
" r read-only access\n"
" "
- " no no access\n")
+ " no no access")
},
- {"groups-file", svnauthz__groups_file, 1, ("path to the global groups file")},
- {"recursive", 'R', 0, ("recursive access to path")},
+ {"groups-file", svnauthz__groups_file, 1,
+ ("use the groups from file ARG")},
+ {"recursive", 'R', 0,
+ ("determine recursive access to PATH")},
{0, 0, 0, 0}
};
@@ -129,27 +133,32 @@ static const svn_opt_subcommand_desc2_t
{'t'} },
{"accessof", subcommand_accessof, {0} /* no aliases */,
("Print or test the permissions set by an authz file.\n"
- "usage: 1. svnauthz accessof [--username USER] [--groups-file GROUPS_FILE] TARGET\n"
- " 2. svnauthz accessof [--username USER] [--groups-file GROUPS_FILE] \\\n"
- " -t TXN REPOS_PATH FILE_PATH\n\n"
- " 1. Prints the access of USER based on TARGET.\n"
+ "usage: 1. svnauthz accessof TARGET\n"
+ " 2. svnauthz accessof -t TXN REPOS_PATH FILE_PATH\n"
+ "\n"
+ " 1. Prints the access of USER to PATH based on authorization 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"
- " 2. Prints the access of USER based on authz file at FILE_PATH in the\n"
- " transaction TXN in the repository at REPOS_PATH.\n\n"
- " If the --username argument is omitted then access of an anonymous user\n"
- " will be printed. If --path argument is omitted prints if any access\n"
- " to the repo is allowed. If --groups-file is specified, the groups from\n"
- " GROUPS_FILE will be used.\n\n"
+ " file in a repository, but cannot be a repository relative URL (^/).\n"
+ "\n"
+ " 2. Prints the access of USER to PATH based on authz file at FILE_PATH in the\n"
+ " transaction TXN in the repository at REPOS_PATH.\n"
+ "\n"
+ " USER is the argument to the --username option; if that option is not\n"
+ " provided, then access of an anonymous user will be printed or tested.\n"
+ "\n"
+ " PATH is the argument to the --path option; if that option is not provided,\n"
+ " the maximal access to any path in the repository will be considered.\n"
+ "\n"
"Outputs one of the following:\n"
" rw write access (which also implies read)\n"
" r read access\n"
- " no no access\n\n"
+ " no no access\n"
+ "\n"
"Returns:\n"
- " 0 when syntax is OK and --is argument (if any) matches.\n"
+ " 0 when syntax is OK and '--is' argument (if any) matches.\n"
" 1 when syntax is invalid.\n"
" 2 operational error\n"
- " 3 when --is argument doesn't match\n"
+ " 3 when '--is' argument doesn't match\n"
),
{'t', svnauthz__username, svnauthz__path, svnauthz__repos, svnauthz__is,
svnauthz__groups_file, 'R'} },
Modified: subversion/branches/move-tracking-1/win-tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-1/win-tests.py?rev=1515380&r1=1515379&r2=1515380&view=diff
==============================================================================
--- subversion/branches/move-tracking-1/win-tests.py (original)
+++ subversion/branches/move-tracking-1/win-tests.py Mon Aug 19 12:07:51 2013
@@ -84,6 +84,8 @@ def _usage_exit():
print(" --disable-bulk-updates : Disable bulk updates on HTTP server")
print(" --ssl-cert : Path to SSL server certificate to trust.")
print(" --javahl : Run the javahl tests instead of the normal tests")
+ print(" --swig=language : Run the swig perl/python/ruby tests instead of")
+ print(" the normal tests")
print(" --list : print test doc strings only")
print(" --milestone-filter=RE : RE is a regular expression pattern that (when")
print(" used with --list) limits the tests listed to")
@@ -108,29 +110,24 @@ CMDLINE_TEST_SCRIPT_NATIVE_PATH = CMDLIN
sys.path.insert(0, os.path.join('build', 'generator'))
sys.path.insert(1, 'build')
-import gen_win
+import gen_win_dependencies
+import gen_base
version_header = os.path.join('subversion', 'include', 'svn_version.h')
cp = configparser.ConfigParser()
cp.read('gen-make.opts')
-gen_obj = gen_win.GeneratorBase('build.conf', version_header,
- cp.items('options'))
+gen_obj = gen_win_dependencies.GenDependenciesBase('build.conf', version_header,
+ cp.items('options'))
all_tests = gen_obj.test_progs + gen_obj.bdb_test_progs \
+ gen_obj.scripts + gen_obj.bdb_scripts
client_tests = [x for x in all_tests if x.startswith(CMDLINE_TEST_SCRIPT_PATH)]
-svn_dlls = []
-for section in gen_obj.sections.values():
- if section.options.get("msvc-export"):
- dll_basename = section.name + "-" + str(gen_obj.version) + ".dll"
- svn_dlls.append(os.path.join("subversion", section.name, dll_basename))
-
opts, args = my_getopt(sys.argv[1:], 'hrdvqct:pu:f:',
['release', 'debug', 'verbose', 'quiet', 'cleanup',
'test=', 'url=', 'svnserve-args=', 'fs-type=', 'asp.net-hack',
'httpd-dir=', 'httpd-port=', 'httpd-daemon',
'httpd-server', 'http-short-circuit', 'httpd-no-log',
'disable-http-v2', 'disable-bulk-updates', 'help',
- 'fsfs-packing', 'fsfs-sharding=', 'javahl',
+ 'fsfs-packing', 'fsfs-sharding=', 'javahl', 'swig=',
'list', 'enable-sasl', 'bin=', 'parallel',
'config-file=', 'server-minor-version=', 'log-level=',
'log-to-stdout', 'mode-filter=', 'milestone-filter=',
@@ -156,6 +153,7 @@ http_bulk_updates = True
list_tests = None
milestone_filter = None
test_javahl = None
+test_swig = None
enable_sasl = None
svn_bin = None
parallel = None
@@ -216,6 +214,11 @@ for opt, val in opts:
fsfs_packing = 1
elif opt == '--javahl':
test_javahl = 1
+ elif opt == '--swig':
+ if val not in ['perl', 'python', 'ruby']:
+ sys.stderr.write('Running \'%s\' swig tests not supported (yet).\n'
+ % (val,))
+ test_swig = val
elif opt == '--list':
list_tests = 1
elif opt == '--milestone-filter':
@@ -289,12 +292,18 @@ def create_target_dir(dirname):
print("mkdir: %s" % tgt_dir)
os.makedirs(tgt_dir)
-def copy_changed_file(src, tgt):
+def copy_changed_file(src, tgt=None, to_dir=None, cleanup=True):
if not os.path.isfile(src):
print('Could not find ' + src)
sys.exit(1)
- if os.path.isdir(tgt):
- tgt = os.path.join(tgt, os.path.basename(src))
+
+ if to_dir and not tgt:
+ tgt = os.path.join(to_dir, os.path.basename(src))
+ elif not tgt or (tgt and to_dir):
+ raise RuntimeError("Using 'tgt' *or* 'to_dir' is required" % (tgt,))
+ elif tgt and os.path.isdir(tgt):
+ raise RuntimeError("'%s' is a directory. Use to_dir=" % (tgt,))
+
if os.path.exists(tgt):
assert os.path.isfile(tgt)
if filecmp.cmp(src, tgt):
@@ -306,57 +315,35 @@ def copy_changed_file(src, tgt):
print("copy: %s" % src)
print(" to: %s" % tgt)
shutil.copy(src, tgt)
- return 1
-def copy_execs(baton, dirname, names):
- copied_execs = baton
- for name in names:
- if not name.endswith('.exe'):
- continue
- src = os.path.join(dirname, name)
- tgt = os.path.join(abs_builddir, dirname, name)
- create_target_dir(dirname)
- if copy_changed_file(src, tgt):
- copied_execs.append(tgt)
+ if cleanup:
+ copied_execs.append(tgt)
def locate_libs():
"Move DLLs to a known location and set env vars"
- dlls = []
-
- # look for APR 1.x dll's and use those if found
- apr_test_path = os.path.join(gen_obj.apr_path, objdir, 'libapr-1.dll')
- if os.path.exists(apr_test_path):
- suffix = "-1"
- else:
- suffix = ""
-
- if cp.has_option('options', '--with-static-apr'):
- dlls.append(os.path.join(gen_obj.apr_path, objdir,
- 'libapr%s.dll' % (suffix)))
- dlls.append(os.path.join(gen_obj.apr_util_path, objdir,
- 'libaprutil%s.dll' % (suffix)))
-
- if gen_obj.libintl_path is not None:
- dlls.append(os.path.join(gen_obj.libintl_path, 'bin', 'intl3_svn.dll'))
+ debug = (objdir == 'Debug')
+
+ for lib in gen_obj._libraries.values():
+
+ if debug:
+ name, dir = lib.debug_dll_name, lib.debug_dll_dir
+ else:
+ name, dir = lib.dll_name, lib.dll_dir
+
+ if name and dir:
+ src = os.path.join(dir, name)
+ if os.path.exists(src):
+ copy_changed_file(src, to_dir=abs_builddir, cleanup=False)
- if gen_obj.bdb_lib is not None:
- partial_path = os.path.join(gen_obj.bdb_path, 'bin', gen_obj.bdb_lib)
- if objdir == 'Debug':
- dlls.append(partial_path + 'd.dll')
- else:
- dlls.append(partial_path + '.dll')
-
- if gen_obj.sasl_path is not None:
- dlls.append(os.path.join(gen_obj.sasl_path, 'lib', 'libsasl.dll'))
-
- for dll in dlls:
- copy_changed_file(dll, abs_objdir)
# Copy the Subversion library DLLs
- if not cp.has_option('options', '--disable-shared'):
- for svn_dll in svn_dlls:
- copy_changed_file(os.path.join(abs_objdir, svn_dll), abs_objdir)
+ for i in gen_obj.graph.get_all_sources(gen_base.DT_INSTALL):
+ if isinstance(i, gen_base.TargetLib) and i.msvc_export:
+ src = os.path.join(abs_objdir, i.filename)
+ if os.path.isfile(src):
+ copy_changed_file(src, to_dir=abs_builddir,
+ cleanup=False)
# Copy the Apache modules
if run_httpd and cp.has_option('options', '--with-httpd'):
@@ -367,11 +354,11 @@ def locate_libs():
mod_dontdothat_path = os.path.join(abs_objdir, 'tools', 'server-side',
'mod_dontdothat', 'mod_dontdothat.so')
- copy_changed_file(mod_dav_svn_path, abs_objdir)
- copy_changed_file(mod_authz_svn_path, abs_objdir)
- copy_changed_file(mod_dontdothat_path, abs_objdir)
+ copy_changed_file(mod_dav_svn_path, to_dir=abs_builddir, cleanup=False)
+ copy_changed_file(mod_authz_svn_path, to_dir=abs_builddir, cleanup=False)
+ copy_changed_file(mod_dontdothat_path, to_dir=abs_builddir, cleanup=False)
- os.environ['PATH'] = abs_objdir + os.pathsep + os.environ['PATH']
+ os.environ['PATH'] = abs_builddir + os.pathsep + os.environ['PATH']
def fix_case(path):
path = os.path.normpath(path)
@@ -608,7 +595,7 @@ class Httpd:
return 'LoadModule ' + name + " " + self._quote(full_path) + '\n'
def _svn_module(self, name, path):
- full_path = os.path.join(self.abs_objdir, path)
+ full_path = os.path.join(self.abs_builddir, path)
return 'LoadModule ' + name + ' ' + self._quote(full_path) + '\n'
def _svn_repo(self, name):
@@ -688,21 +675,17 @@ class Httpd:
print('Httpd.stop_daemon not implemented')
# Move the binaries to the test directory
+create_target_dir(abs_builddir)
locate_libs()
if create_dirs:
- old_cwd = os.getcwd()
- try:
- os.chdir(abs_objdir)
- baton = copied_execs
- for dirpath, dirs, files in os.walk('subversion'):
- copy_execs(baton, dirpath, files)
- for dirpath, dirs, files in os.walk('tools/server-side'):
- copy_execs(baton, dirpath, files)
- except:
- os.chdir(old_cwd)
- raise
- else:
- os.chdir(old_cwd)
+ for i in gen_obj.graph.get_all_sources(gen_base.DT_INSTALL):
+ if isinstance(i, gen_base.TargetExe):
+ src = os.path.join(abs_objdir, i.filename)
+
+ if os.path.isfile(src):
+ dst = os.path.join(abs_builddir, i.filename)
+ create_target_dir(os.path.dirname(dst))
+ copy_changed_file(src, dst)
# Create the base directory for Python tests
create_target_dir(CMDLINE_TEST_SCRIPT_NATIVE_PATH)
@@ -760,7 +743,7 @@ else:
print('Testing %s configuration on %s' % (objdir, repo_loc))
sys.path.insert(0, os.path.join(abs_srcdir, 'build'))
-if not test_javahl:
+if not test_javahl and not test_swig:
import run_tests
if log_to_stdout:
log_file = None
@@ -788,7 +771,7 @@ if not test_javahl:
raise
else:
os.chdir(old_cwd)
-else:
+elif test_javahl:
failed = False
args = (
'java.exe',
@@ -826,6 +809,148 @@ else:
if (r != 0):
print('[Test runner reported failure]')
failed = True
+elif test_swig == 'perl':
+ failed = False
+ swig_dir = os.path.join(abs_builddir, 'swig')
+ swig_pl_dir = os.path.join(swig_dir, 'p5lib')
+ swig_pl_svn = os.path.join(swig_pl_dir, 'SVN')
+ swig_pl_auto_svn = os.path.join(swig_pl_dir, 'auto', 'SVN')
+
+ create_target_dir(swig_pl_svn)
+
+ for i in gen_obj.graph.get_all_sources(gen_base.DT_INSTALL):
+ if isinstance(i, gen_base.TargetSWIG) and i.lang == 'perl':
+ mod_dir = os.path.join(swig_pl_auto_svn, '_' + i.name[5:].capitalize())
+ create_target_dir(mod_dir)
+ copy_changed_file(os.path.join(abs_objdir, i.filename), to_dir=mod_dir)
+
+ elif isinstance(i, gen_base.TargetSWIGLib) and i.lang == 'perl':
+ copy_changed_file(os.path.join(abs_objdir, i.filename),
+ to_dir=abs_builddir)
+
+ pm_src = os.path.join(abs_srcdir, 'subversion', 'bindings', 'swig', 'perl',
+ 'native')
+
+ tests = []
+
+ for root, dirs, files in os.walk(pm_src):
+ for name in files:
+ if name.endswith('.pm'):
+ fn = os.path.join(root, name)
+ copy_changed_file(fn, to_dir=swig_pl_svn)
+ elif name.endswith('.t'):
+ tests.append(os.path.relpath(os.path.join(root, name), pm_src))
+
+ perl5lib = swig_pl_dir
+ if 'PERL5LIB' in os.environ:
+ perl5lib += os.pathsep + os.environ['PERL5LIB']
+
+ perl_exe = 'perl.exe'
+
+ print('-- Running Swig Perl tests --')
+ old_cwd = os.getcwd()
+ try:
+ os.chdir(pm_src)
+
+ os.environ['PERL5LIB'] = perl5lib
+ os.environ["SVN_DBG_NO_ABORT_ON_ERROR_LEAK"] = 'YES'
+
+ r = subprocess.call([
+ perl_exe,
+ '-MExtUtils::Command::MM',
+ '-e', 'test_harness()'
+ ] + tests)
+ finally:
+ os.chdir(old_cwd)
+
+ if (r != 0):
+ print('[Test runner reported failure]')
+ failed = True
+ sys.exit(1)
+elif test_swig == 'python':
+ failed = False
+ swig_dir = os.path.join(abs_builddir, 'swig')
+ swig_py_dir = os.path.join(swig_dir, 'pylib')
+ swig_py_libsvn = os.path.join(swig_py_dir, 'libsvn')
+ swig_py_svn = os.path.join(swig_py_dir, 'svn')
+
+ create_target_dir(swig_py_libsvn)
+ create_target_dir(swig_py_svn)
+
+ for i in gen_obj.graph.get_all_sources(gen_base.DT_INSTALL):
+ if (isinstance(i, gen_base.TargetSWIG)
+ or isinstance(i, gen_base.TargetSWIGLib)) and i.lang == 'python':
+
+ src = os.path.join(abs_objdir, i.filename)
+ copy_changed_file(src, to_dir=swig_py_libsvn)
+
+ py_src = os.path.join(abs_srcdir, 'subversion', 'bindings', 'swig', 'python')
+
+ for py_file in os.listdir(py_src):
+ if py_file.endswith('.py'):
+ copy_changed_file(os.path.join(py_src, py_file),
+ to_dir=swig_py_libsvn)
+
+ py_src_svn = os.path.join(py_src, 'svn')
+ for py_file in os.listdir(py_src_svn):
+ if py_file.endswith('.py'):
+ copy_changed_file(os.path.join(py_src_svn, py_file),
+ to_dir=swig_py_svn)
+
+ print('-- Running Swig Python tests --')
+
+ pythonpath = swig_py_dir
+ if 'PYTHONPATH' in os.environ:
+ pythonpath += os.pathsep + os.environ['PYTHONPATH']
+
+ python_exe = 'python.exe'
+ old_cwd = os.getcwd()
+ try:
+ os.environ['PYTHONPATH'] = pythonpath
+
+ r = subprocess.call([
+ python_exe,
+ os.path.join(py_src, 'tests', 'run_all.py')
+ ])
+ finally:
+ os.chdir(old_cwd)
+
+ if (r != 0):
+ print('[Test runner reported failure]')
+ failed = True
+
+elif test_swig == 'ruby':
+ failed = False
+
+ if 'ruby' not in gen_obj._libraries:
+ print('Ruby not found. Skipping Ruby tests')
+ else:
+ ruby_lib = gen_obj._libraries['ruby']
+
+ ruby_exe = 'ruby.exe'
+ ruby_subdir = os.path.join('subversion', 'bindings', 'swig', 'ruby')
+ ruby_args = [
+ '-I', os.path.join(abs_srcdir, ruby_subdir),
+ os.path.join(abs_srcdir, ruby_subdir, 'test', 'run-test.rb'),
+ '--verbose'
+ ]
+
+ print('-- Running Swig Ruby tests --')
+ old_cwd = os.getcwd()
+ try:
+ os.chdir(ruby_subdir)
+
+ os.environ["BUILD_TYPE"] = objdir
+ os.environ["SVN_DBG_NO_ABORT_ON_ERROR_LEAK"] = 'YES'
+ r = subprocess.call([ruby_exe] + ruby_args)
+ finally:
+ os.chdir(old_cwd)
+
+ sys.stdout.flush()
+ sys.stderr.flush()
+ if (r != 0):
+ print('[Test runner reported failure]')
+ failed = True
# Stop service daemon, if any
if daemon: