Author: rinrab Date: Wed Apr 1 16:52:16 2026 New Revision: 1932705 Log: svnbrowse: Create new blank program to implement a TUI browser for repository directories. i.e. interactive interface for 'svn ls'.
The program itself is an empty application with some boilerplate copied from other command-line tools. Also perform ncurses initialization, and test that everything works great; No real functionality is implemented yet. * CMakeLists.txt (SVN_ENABLE_TUI): New option. (ncurses): Look for the library. (configsummary): Log state of SVN_ENABLE_TUI. * build.conf (svnbrowse): Declare target. * build/generator/gen_cmake.py (get_target_conditions): Add special handling for svnbrowse target so it is enabled only if TUIs are ON. * subversion/svnbrowse/svnbrowse.c: New file. (ui_draw): This function will be rendering everything to the screen. (sub_main): New function, a wrapper around main() with pools and svn-errors. (main): New main. Please follow the discussion on [email protected]. for more info. [1] https://lists.apache.org/thread/knc20xgb6h56jl0tvxbywhgt5yvh90vg Added: subversion/trunk/subversion/svnbrowse/ subversion/trunk/subversion/svnbrowse/svnbrowse.c (contents, props changed) Modified: subversion/trunk/CMakeLists.txt subversion/trunk/build.conf subversion/trunk/build/generator/gen_cmake.py Modified: subversion/trunk/CMakeLists.txt ============================================================================== --- subversion/trunk/CMakeLists.txt Wed Apr 1 16:20:29 2026 (r1932704) +++ subversion/trunk/CMakeLists.txt Wed Apr 1 16:52:16 2026 (r1932705) @@ -88,6 +88,7 @@ option(SVN_ENABLE_FS_FS "Enable Subversi option(SVN_ENABLE_FS_X "Enable Subversion FSX Repository Filesystem Library" ON) option(SVN_ENABLE_FS_BASE "Enable Subversion Filesystem Base Library (NOT IMPLEMENTED and DEPRECATED)" OFF) option(SVN_ENABLE_NLS "Enable gettext functionality" OFF) +option(SVN_ENABLE_TUI "Enable TUI applications (requires ncurses)" OFF) option(SVN_ENABLE_AUTH_KWALLET "Enable KWallet auth library" OFF) option(SVN_ENABLE_AUTH_GNOME_KEYRING "Enable GNOME Keyring for auth credentials" OFF) cmake_dependent_option(SVN_ENABLE_AUTH_GPG_AGENT "Enable GPG Agent support" OFF "WIN32" ON) @@ -483,6 +484,17 @@ if(SVN_ENABLE_AUTH_GNOME_KEYRING) ) endif() +if (SVN_ENABLE_TUI) + add_library(external-ncurses INTERFACE) + + if(SVN_USE_PKG_CONFIG) + pkg_check_modules(ncurses REQUIRED IMPORTED_TARGET ncurses) + target_link_libraries(external-ncurses INTERFACE PkgConfig::ncurses) + else() + message(ERROR "not supported") + endif() +endif() + if(SVN_ENABLE_SWIG_PERL OR SVN_ENABLE_SWIG_PYTHON OR SVN_ENABLE_SWIG_RUBY) find_package(SWIG REQUIRED) include(${SWIG_USE_FILE}) @@ -996,6 +1008,7 @@ message(STATUS " Build type ........... message(STATUS " Build shared libraries ........ : ${BUILD_SHARED_LIBS}") message(STATUS " Build shared FS Modues ........ : ${SVN_BUILD_SHARED_FS}") message(STATUS " Build shared RA Modues ........ : ${SVN_BUILD_SHARED_RA}") +message(STATUS " Build TUI applications ........ : ${SVN_ENABLE_TUI}") message(STATUS " Use pkg-config dependencies ... : ${SVN_USE_PKG_CONFIG}") message(STATUS " Checksum Backend .............. : ${SVN_CHECKSUM_BACKEND}") message(STATUS " FS modules:") Modified: subversion/trunk/build.conf ============================================================================== --- subversion/trunk/build.conf Wed Apr 1 16:20:29 2026 (r1932704) +++ subversion/trunk/build.conf Wed Apr 1 16:52:16 2026 (r1932705) @@ -222,6 +222,12 @@ libs = libsvn_client libsvn_ra libsvn_su install = bin manpages = subversion/svnmucc/svnmucc.1 +[svnbrowse] +type = exe +path = subversion/svnbrowse +libs = libsvn_client libsvn_ra libsvn_subr libsvn_delta ncurses +install = bin + # Support for GNOME Keyring [libsvn_auth_gnome_keyring] description = Subversion GNOME Keyring Library @@ -1505,6 +1511,10 @@ external-lib = $(SVN_SASL_LIBS) type = lib external-lib = $(SVN_OPENSSL_LIBS) $(SVN_LIBCRYPTO_LIBS) +[ncurses] +type = lib +external-lib = $(SVN_NCURSES_LIBS) + [checksum-libs] type = lib external-lib = $(SVN_CHECKSUM_LIBS) Modified: subversion/trunk/build/generator/gen_cmake.py ============================================================================== --- subversion/trunk/build/generator/gen_cmake.py Wed Apr 1 16:20:29 2026 (r1932704) +++ subversion/trunk/build/generator/gen_cmake.py Wed Apr 1 16:52:16 2026 (r1932705) @@ -79,6 +79,8 @@ def get_target_conditions(target): enable_condition.append("SVN_ENABLE_AUTH_KWALLET") elif target.name == "libsvn_auth_gnome_keyring": enable_condition.append("SVN_ENABLE_AUTH_GNOME_KEYRING") + elif target.name == "svnbrowse": + enable_condition.append("SVN_ENABLE_TUI") if isinstance(target, gen_base.TargetExe): if target.install == "test" or target.install == "sub-test": Added: subversion/trunk/subversion/svnbrowse/svnbrowse.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ subversion/trunk/subversion/svnbrowse/svnbrowse.c Wed Apr 1 16:52:16 2026 (r1932705) @@ -0,0 +1,108 @@ +/* + * svnbrowse.c: TUI (terminal user interface) client for browsing and + * exploring remote Subversion targets. + * + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + */ + +#include <apr.h> + +#include "svn_pools.h" +#include "svn_cmdline.h" +#include "svn_error.h" + +#include <ncurses.h> + +/* Control+ASCII character are represented as values 1-26 according to their + * alphabetical order. */ +#define CTRL(ch) (ch - 'a' + 1) + +static void +ui_draw(apr_pool_t *pool) +{ + mvprintw(0, 4, "svnbrowse: work in progress"); +} + +static svn_error_t * +sub_main(int *code, int argc, char *argv[], apr_pool_t *pool) +{ + /* init the display */ + initscr(); + + /* put ncurses into keypad mode to handle arrow inputs */ + intrflush(stdscr, FALSE); + keypad(stdscr, TRUE); + nonl(); + + while (TRUE) + { + int ch; + + clear(); + ui_draw(pool); + refresh(); + + ch = getch(); + + /* getch() reads the next character/key with the following additional + * rules: + * 1. as we configured it to use keypad(), arrows and other special keys + * are handled as KEY_XXX. + * 2. Control (CTRL) version are handled as literal 1-26 values of ch where + * 1 is <C-A> and 26 is <C-Z>. + * 3. The rest of keys remain as their equivalents on the current layout. + * 4. If shift is held, they just become uppercased. + */ + + /* TODO: quit via escape. some say just check for 27, but it I think it's + * a bit ugly. */ + if (ch == 'q') + { + break; + } + } + + endwin(); + + return SVN_NO_ERROR; +} + +int main(int argc, char *argv[]) +{ + apr_pool_t *pool; + int exit_code = EXIT_SUCCESS; + svn_error_t *err; + + if (svn_cmdline_init("svnbrowse", stderr) != EXIT_SUCCESS) + return EXIT_FAILURE; + + pool = apr_allocator_owner_get(svn_pool_create_allocator(FALSE)); + + err = sub_main(&exit_code, argc, argv, pool); + + if (err) + { + exit_code = EXIT_FAILURE; + svn_cmdline_handle_exit_error(err, NULL, "svnbrowse: "); + } + + svn_pool_destroy(pool); + return exit_code; +}
