On Sun, May 24, 2026 at 2:52 AM <[email protected]> wrote:
> Author: brane
> Date: Sun May 24 00:52:17 2026
> New Revision: 1934546
>
> Log:
> Add svnbrowse to the autotools build.
>
> Building svnbrowse is optional and can be enabled with --enable-svnbrowse.
> When enabled, --with-ncurses can be used to find the ncurses installation.
>
> * Makefile.in
> (SVN_NCURSES_LIBS,
> SVN_NCURSES_INCLUDES,
> SVN_BUILD_SVNBROWSE,
> INSTALL_TUI,
> tuidir): Add variabkle expansion placeholders.
> * aclocal.m4.in: Include build/ac-macros/svnbrowse.m4.
> * build.conf (svnbrowse): Add description, conditional-compile symbol
> and compilation command. The latter is required because conditional
> compilation doesn't work without it.
> * configure.ac: Call the SVN_SVNBROWSE function.
> (BUILD_RULES): Include the 'tui' target.
> (INSTALL_STATIC_RULES): Include the 'install-tui' target.
> * build/ac-macros/svnbrowse.m4: New file.
> (SVN_SVNBROWSE, SVN_NCURSES_PREFIX, SVN_NCURSES_PKG_CONFIG): New
> functions.
> * build/generator/templates/build-outputs.mk.ezt
> [for deps]: Fix the scope of the [if-any deps.cmd] conditional.
>
> * subversion/svnbrowse/svnbrowse.h: Make the header idempotent.
> * subversion/svnbrowse/svnbrowse.c:
> Include external library headers before our own headers.
> (view_on_event): Fix compilation error due to using mixed declarations
> and statements, which is a C99 feature.
>
> Added:
> subversion/trunk/build/ac-macros/svnbrowse.m4 (contents, props
> changed)
> Modified:
> subversion/trunk/Makefile.in
> subversion/trunk/aclocal.m4.in
> subversion/trunk/build.conf
> subversion/trunk/build/generator/templates/build-outputs.mk.ezt
> subversion/trunk/configure.ac
> subversion/trunk/subversion/svnbrowse/svnbrowse.c
> subversion/trunk/subversion/svnbrowse/svnbrowse.h
>
> Modified: subversion/trunk/Makefile.in
>
> ==============================================================================
> --- subversion/trunk/Makefile.in Sun May 24 00:00:12 2026
> (r1934545)
> +++ subversion/trunk/Makefile.in Sun May 24 00:52:17 2026
> (r1934546)
> @@ -54,6 +54,7 @@ SVN_SERF_LIBS = @SVN_SERF_LIBS@
> SVN_SQLITE_LIBS = @SVN_SQLITE_LIBS@
> SVN_XML_LIBS = @SVN_XML_LIBS@
> SVN_ZLIB_LIBS = @SVN_ZLIB_LIBS@
> +SVN_NCURSES_LIBS = @SVN_NCURSES_LIBS@
> SVN_LZ4_LIBS = @SVN_LZ4_LIBS@
> SVN_UTF8PROC_LIBS = @SVN_UTF8PROC_LIBS@
> SVN_MACOS_PLIST_LIBS = @SVN_MACOS_PLIST_LIBS@
> @@ -72,6 +73,7 @@ gpg_agent_libdir = @libdir@
> kwallet_libdir = @libdir@
> serf_libdir = @libdir@
> bindir = @bindir@
> +tuidir = @bindir@
> includedir = @includedir@
> mandir = @mandir@
> srcdir = @srcdir@
> @@ -138,7 +140,7 @@ INCLUDES = -I$(top_srcdir)/subversion/in
> @SVN_KWALLET_INCLUDES@ @SVN_MAGIC_INCLUDES@ \
> @SVN_SASL_INCLUDES@ @SVN_SERF_INCLUDES@ @SVN_SQLITE_INCLUDES@
> \
> @SVN_XML_INCLUDES@ @SVN_ZLIB_INCLUDES@ @SVN_LZ4_INCLUDES@ \
> - @SVN_UTF8PROC_INCLUDES@
> + @SVN_UTF8PROC_INCLUDES@ @SVN_NCURSES_INCLUDES@
>
> APACHE_INCLUDES = @APACHE_INCLUDES@
> APACHE_LIBEXECDIR = $(DESTDIR)@APACHE_LIBEXECDIR@
> @@ -171,6 +173,7 @@ CTYPES_PYTHON_SRC_DIR = $(abs_srcdir)/su
> JAVAHL_JAR=subversion/bindings/javahl/svn-javahl.jar
> JAVAHL_INCLUDES= @JNI_INCLUDES@
> -I$(abs_builddir)/subversion/bindings/javahl/include
>
> +SVN_BUILD_SVNBROWSE = @SVN_BUILD_SVNBROWSE@
> SVN_BUILD_SVNXX = @SVN_BUILD_SVNXX@
> SVN_BUILD_SVNXX_TESTS = @SVN_BUILD_SVNXX_TESTS@
> SVNXX_INCLUDES = -I$(abs_srcdir)/subversion/bindings/cxx/include
> @@ -323,6 +326,7 @@ INSTALL_GNOME_KEYRING_LIB = $(INSTALL_LI
> INSTALL_KWALLET_LIB = $(INSTALL_LIB)
> INSTALL_SERF_LIB = $(INSTALL_LIB)
> INSTALL_BIN = $(LIBTOOL) --mode=install $(INSTALL)
> +INSTALL_TUI = $(INSTALL_BIN)
> INSTALL_CONTRIB = $(LIBTOOL) --mode=install $(INSTALL)
> INSTALL_TOOLS = $(LIBTOOL) --mode=install $(INSTALL)
> INSTALL_INCLUDE = $(INSTALL) -m 644
>
> Modified: subversion/trunk/aclocal.m4.in
>
> ==============================================================================
> --- subversion/trunk/aclocal.m4.in Sun May 24 00:00:12 2026
> (r1934545)
> +++ subversion/trunk/aclocal.m4.in Sun May 24 00:52:17 2026
> (r1934546)
> @@ -39,6 +39,7 @@ sinclude(build/ac-macros/ax_boost_base.m
> sinclude(build/ac-macros/ax_boost_unit_test_framework.m4)
> sinclude(build/ac-macros/berkeley-db.m4)
> sinclude(build/ac-macros/compiler.m4)
> +sinclude(build/ac-macros/svnbrowse.m4)
> sinclude(build/ac-macros/ctypesgen.m4)
> sinclude(build/ac-macros/java.m4)
> sinclude(build/ac-macros/sasl.m4)
>
> Modified: subversion/trunk/build.conf
>
> ==============================================================================
> --- subversion/trunk/build.conf Sun May 24 00:00:12 2026 (r1934545)
> +++ subversion/trunk/build.conf Sun May 24 00:52:17 2026 (r1934546)
> @@ -223,7 +223,11 @@ install = bin
> manpages = subversion/svnmucc/svnmucc.1
>
> [svnbrowse]
> +description = Subversion Repository Browser
> type = exe
> +when = SVN_BUILD_SVNBROWSE
> +# 'when' is ignored without 'compile-cmd'
> +compile-cmd = $(LT_COMPILE) -o $@ -c
> path = subversion/svnbrowse
> libs = libsvn_client libsvn_ra libsvn_subr libsvn_delta ncurses
> install = tui
>
> Added: subversion/trunk/build/ac-macros/svnbrowse.m4
>
> ==============================================================================
> --- /dev/null 00:00:00 1970 (empty, because file is newly added)
> +++ subversion/trunk/build/ac-macros/svnbrowse.m4 Sun May 24
> 00:52:17 2026 (r1934546)
> @@ -0,0 +1,126 @@
> +dnl ===================================================================
> +dnl Licensed to the Apache Software Foundation (ASF) under one
> +dnl or more contributor license agreements. See the NOTICE file
> +dnl distributed with this work for additional information
> +dnl regarding copyright ownership. The ASF licenses this file
> +dnl to you under the Apache License, Version 2.0 (the
> +dnl "License"); you may not use this file except in compliance
> +dnl with the License. You may obtain a copy of the License at
> +dnl
> +dnl http://www.apache.org/licenses/LICENSE-2.0
> +dnl
> +dnl Unless required by applicable law or agreed to in writing,
> +dnl software distributed under the License is distributed on an
> +dnl "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
> +dnl KIND, either express or implied. See the License for the
> +dnl specific language governing permissions and limitations
> +dnl under the License.
> +dnl ===================================================================
> +dnl
> +dnl Configure svnbrowse
> +
> +AC_DEFUN(SVN_SVNBROWSE,
> +[
> + AC_ARG_ENABLE(svnbrowse,
> + AS_HELP_STRING([--enable-svnbrowse],
> + [Enable building svnbrowse]),
> + [
> + if test "$enableval" = "yes" ; then
> + AC_MSG_NOTICE([Enabling svnbrowse])
> + do_svnbrowse_build=yes
> + else
> + AC_MSG_NOTICE([Disabling svnbrowse])
> + do_svnbrowse_build=no
> + fi
> + ])
> +
> + ncurses_skip=no
> + AC_ARG_WITH(ncurses,
> + AS_HELP_STRING([--with-ncurses=PREFIX],
> + [ncurses text-based user interface library]),
> + [
> + if test "$withval" = "yes"; then
> + ncurses_skip=no
> + elif test "$withval" = "no"; then
> + ncurses_skip=yes
> + else
> + ncurses_skip=no
> + ncurses_prefix="$withval"
> + fi
> + ])
> +
> + ncurses_found=no
> + if test "$do_svnbrowse_build" = "yes" && test "$ncurses_skip" = "no";
> then
> + if test -n "$ncurses_prefix"; then
> + SVN_NCURSES_PREFIX()
> + else
> + SVN_NCURSES_PKG_CONFIG()
> + fi
> +
> + if test "$ncurses_found" = "no"; then
> + dnl Make sure previously cached values don't leak here
> + unset ac_cv_header_curses_h
> + unset ac_cv_lib_ncurses_termattrs
> + AC_MSG_NOTICE([ncurses library configuration])
> + AC_CHECK_HEADER([curses.h],[
> + AC_CHECK_LIB([ncurses],[termattrs],[
> + ncurses_found="builtin"
> + SVN_NCURSES_LIBS="-lncurses"
> + ])
> + ])
> + fi
> + fi
> +
> + if test "$do_svnbrowse_build" = "yes"; then
> + if test "$ncurses_found" = "no"; then
> + AC_MSG_WARN([svnbrowse requires ncurses, disabling])
> + SVN_BUILD_SVNBROWSE=false
> + else
> + SVN_BUILD_SVNBROWSE=true
> + fi
> + else
> + SVN_BUILD_SVNBROWSE=false
> + fi
> +
> + SVN_DOT_CLANGD([$SVN_ZLIB_INCLUDES])
> + AC_SUBST(SVN_BUILD_SVNBROWSE)
> + AC_SUBST(SVN_NCURSES_INCLUDES)
> + AC_SUBST(SVN_NCURSES_LIBS)
> +])
> +
> +AC_DEFUN(SVN_NCURSES_PREFIX,
> +[
> + AC_MSG_NOTICE([ncurses library configuration via prefix])
> + save_cppflags="$CPPFLAGS"
> + ncurses_includes="-I$ncurses_prefix/include"
> + CPPFLAGS="$CPPFLAGS $ncurses_includes"
> + AC_CHECK_HEADER([curses.h],[
> + save_ldflags="$LDFLAGS"
> +
> ncurses_libs="`SVN_REMOVE_STANDARD_LIB_DIRS(-L$ncurses_prefix/lib)`"
> + LDFLAGS="$LDFLAGS $ncurses_libs"
> + AC_CHECK_LIB([ncurses],[termattrs],[
> + ncurses_found="yes"
> + SVN_NCURSES_INCLUDES="$ncurses_includes"
> + SVN_NCURSES_LIBS="$ncurses_libs -lncurses"
> + ])
> + LDFLAGS="$save_ldflags"
> + ])
> + CPPFLAGS="$save_cppflags"
> +])
> +
> +AC_DEFUN(SVN_NCURSES_PKG_CONFIG,
> +[
> + AC_MSG_NOTICE([ncurses library configuration via pkg-config])
> + if test -n "$PKG_CONFIG"; then
> + AC_MSG_CHECKING([for ncurses library])
> + if $PKG_CONFIG ncurses --exists; then
> + AC_MSG_RESULT([yes])
> + ncurses_found=yes
> + ncurses_libs=`$PKG_CONFIG ncurses --libs`
> + SVN_NCURSES_INCLUDES=`$PKG_CONFIG ncurses --cflags`
> +
> SVN_NCURSES_LIBS="`SVN_REMOVE_STANDARD_LIB_DIRS($ncurses_libs)`"
> + else
> + AC_MSG_RESULT([no])
> + fi
> + fi
> +])
>
> Modified: subversion/trunk/build/generator/templates/build-outputs.mk.ezt
>
> ==============================================================================
> --- subversion/trunk/build/generator/templates/build-outputs.mk.ezt
> Sun May 24 00:00:12 2026 (r1934545)
> +++ subversion/trunk/build/generator/templates/build-outputs.mk.ezt
> Sun May 24 00:52:17 2026 (r1934546)
> @@ -164,5 +164,5 @@ install-include:[for includes] [includes
> ########################################
> [for deps]
> [deps.name]:[for deps.deps] [deps.deps][end][if-any deps.cmd]
> - [if-any deps.when]if $([deps.when]) ; then [else][end][deps.cmd]
> [if-any
> deps.generated][else]$(canonicalized_srcdir)[end][deps.source][end][if-any
> deps.when] ; else echo "fake" > [deps.name] ; fi[else][end]
> + [if-any deps.when]if $([deps.when]) ; then [else][end][deps.cmd]
> [if-any
> deps.generated][else]$(canonicalized_srcdir)[end][deps.source][if-any
> deps.when] ; else echo "fake" > [deps.name] ; fi[else][end][end]
> [end]
>
> Modified: subversion/trunk/configure.ac
>
> ==============================================================================
> --- subversion/trunk/configure.ac Sun May 24 00:00:12 2026
> (r1934545)
> +++ subversion/trunk/configure.ac Sun May 24 00:52:17 2026
> (r1934546)
> @@ -995,10 +995,10 @@ AS_HELP_STRING([--disable-plaintext-pass
>
> dnl Build and install rules -------------------
>
> -INSTALL_STATIC_RULES="install-bin install-docs"
> +INSTALL_STATIC_RULES="install-bin install-tui install-docs"
> INSTALL_RULES="install-fsmod-lib install-ramod-lib install-lib
> install-include install-static"
> INSTALL_RULES="$INSTALL_RULES $INSTALL_APACHE_RULE"
> -BUILD_RULES="fsmod-lib ramod-lib lib bin test sub-test $BUILD_APACHE_RULE
> tools"
> +BUILD_RULES="fsmod-lib ramod-lib lib bin tui test sub-test
> $BUILD_APACHE_RULE tools"
>
> if test "$svn_lib_berkeley_db" = "yes"; then
> BUILD_RULES="$BUILD_RULES bdb-lib bdb-test"
> @@ -1333,6 +1333,8 @@ AS_HELP_STRING([--with-editor=PATH],
>
> ])
>
> +SVN_SVNBROWSE
> +
> SVN_LIB_Z
>
> SVN_LZ4
>
> Modified: subversion/trunk/subversion/svnbrowse/svnbrowse.c
>
> ==============================================================================
> --- subversion/trunk/subversion/svnbrowse/svnbrowse.c Sun May 24
> 00:00:12 2026 (r1934545)
> +++ subversion/trunk/subversion/svnbrowse/svnbrowse.c Sun May 24
> 00:52:17 2026 (r1934546)
> @@ -22,6 +22,8 @@
> * ====================================================================
> */
>
> +#include <curses.h>
> +
> #include <apr.h>
>
> #include "private/svn_utf_private.h"
> @@ -35,8 +37,6 @@
>
> #include "private/svn_cmdline_private.h"
>
> -#include <curses.h>
> -
> #include "svn_private_config.h"
> #include "svn_time.h"
> #include "svnbrowse.h"
> @@ -251,10 +251,11 @@ view_make(svn_browse__model_t *model, sv
> static svn_error_t *
> view_on_event(svn_browse__view_t *view, int ch, apr_pool_t *scratch_pool)
> {
> + int scrollsize;
> view_layout(view);
>
> /* scrollable height is one row less than the whole view */
> - int scrollsize = getmaxy(view->list);
> + scrollsize = getmaxy(view->list);
>
> /* ch is received from getch() which would read the next character/key
> with
> * the following additional rules:
>
> Modified: subversion/trunk/subversion/svnbrowse/svnbrowse.h
>
> ==============================================================================
> --- subversion/trunk/subversion/svnbrowse/svnbrowse.h Sun May 24
> 00:00:12 2026 (r1934545)
> +++ subversion/trunk/subversion/svnbrowse/svnbrowse.h Sun May 24
> 00:52:17 2026 (r1934546)
> @@ -21,6 +21,9 @@
> * ====================================================================
> */
>
> +#ifndef SVN_SVNBROWSE_SVNBROWSE_H
> +#define SVN_SVNBROWSE_SVNBROWSE_H
> +
> #include <apr.h>
>
> #include "svn_client.h"
> @@ -147,3 +150,5 @@ svn_browse__model_create(svn_browse__mod
> const svn_opt_revision_t *revision,
> apr_pool_t *result_pool,
> apr_pool_t *scratch_pool);
> +
> +#endif /* SVN_SVNBROWSE_SVNBROWSE_H */
>
>
Thank you so much for doing that!
I've tested the change and can confirm that it works perfectly on my
machine.
However, I just realised that there is a crash when the program exits and
executes the pool-cleanups (that is also present in cmake build but for
some reason it wasn't printing the error message properly);
[[[
> where
#0 __pthread_kill_implementation
(threadid=<optimized out>, signo=signo@entry=6, no_tid=no_tid@entry=0)
at pthread_kill.c:44
#1 0x00007ffff749a363 in __pthread_kill_internal (threadid=<optimized
out>, signo=6)
at pthread_kill.c:89
#2 0x00007ffff743e7d0 in __GI_raise (sig=sig@entry=6) at
../sysdeps/posix/raise.c:26
#3 0x00007ffff7425681 in __GI_abort () at abort.c:77
#4 0x00007ffff7b3d4e0 in err_abort (data=0x555555758c50) at
subversion/libsvn_subr/error.c:156
#5 0x00007ffff77cc7de in run_cleanups (cref=<optimized out>) at
memory/unix/apr_pools.c:2666
#6 apr_pool_destroy (pool=0x555555758bd8) at memory/unix/apr_pools.c:991
#7 0x00007ffff77cc7bd in apr_pool_destroy (pool=0x555555560528) at
memory/unix/apr_pools.c:988
#8 0x00007ffff77ccaa1 in apr_pool_terminate () at
memory/unix/apr_pools.c:719
#9 apr_pool_terminate () at memory/unix/apr_pools.c:711
#10 0x00007ffff7441101 in __run_exit_handlers
(status=0, listp=0x7ffff7613680 <__exit_funcs>,
run_list_atexit=run_list_atexit@entry=true, run_dtors=run_dtors@entry=true)
at exit.c:118
#11 0x00007ffff74411de in __GI_exit (status=<optimized out>) at exit.c:148
#12 0x00007ffff7427748 in __libc_start_call_main
(main=main@entry=0x55555555a1f0 <main>, argc=argc@entry=1,
argv=argv@entry=0x7fffffffe488)
at ../sysdeps/nptl/libc_start_call_main.h:83
#13 0x00007ffff7427879 in __libc_start_main_impl
(main=0x55555555a1f0 <main>, argc=1, argv=0x7fffffffe488,
init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>,
stack_end=0x7fffffffe478) at ../csu/libc-start.c:360
#14 0x00005555555575b5 in _start ()
]]]
Which is probably caused by this line:
[[[
static svn_browse__view_t *
view_make(svn_browse__model_t *model, svn_browse__style_t *style, WINDOW
*win,
apr_pool_t *result_pool)
{
svn_browse__view_t *view = apr_pcalloc(result_pool, sizeof(*view));
view->model = model;
view->style = style;
view->screen = win;
view_layout(view);
* apr_pool_cleanup_register(result_pool, view, view_cleanup, NULL);*
return view;
}
]]]
I think apr_pool_cleanup_register() doesn't like NULL for child_cleanup and
in the rest of the codebase we use apr_pool_cleanup_null instead.
The following change seem to fix this issue:
[[[
Index: subversion/svnbrowse/svnbrowse.c
===================================================================
--- subversion/svnbrowse/svnbrowse.c (revision 1934577)
+++ subversion/svnbrowse/svnbrowse.c (working copy)
@@ -244,7 +244,8 @@ view_make(svn_browse__model_t *model, svn_browse__
view->style = style;
view->screen = win;
view_layout(view);
- apr_pool_cleanup_register(result_pool, view, view_cleanup, NULL);
+ apr_pool_cleanup_register(result_pool, view, view_cleanup,
+ apr_pool_cleanup_null);
return view;
}
]]]
Also I think it's a common practice with autoconf to enable all possible
features for which there are required dependencies present on the system.
Take swig, javahl, nls, etc. Is it possible to do the same for svnbrowse,
i.e. enable it whenever we have curses?
By the way, an offtopic question: how do you use gdb with
binraries produced by a configure build? The ./subversion/svn/svn files
seem to be shell scripts which cannot be run with the debugger directly.
What is the easiest way to do it? I figured you could 'make install' it but
it's annoying to do after every change and I'm sure there is a more
convenient way.
--
Timofei Zhakov