You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by fu...@apache.org on 2019/07/08 15:19:05 UTC

svn commit: r1862754 [7/9] - in /subversion/branches/swig-py3: ./ build/ac-macros/ build/generator/ doc/ doc/programmer/ notes/ notes/shelving/ subversion/bindings/cxx/ subversion/bindings/cxxhl/ subversion/bindings/javahl/native/ subversion/bindings/j...

Modified: subversion/branches/swig-py3/subversion/libsvn_repos/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/subversion/libsvn_repos/deprecated.c?rev=1862754&r1=1862753&r2=1862754&view=diff
==============================================================================
--- subversion/branches/swig-py3/subversion/libsvn_repos/deprecated.c (original)
+++ subversion/branches/swig-py3/subversion/libsvn_repos/deprecated.c Mon Jul  8 15:19:03 2019
@@ -1273,6 +1273,21 @@ svn_repos_fs_begin_txn_for_update(svn_fs
 /*** From authz.c ***/
 
 svn_error_t *
+svn_repos_authz_read3(svn_authz_t **authz_p,
+                      const char *path,
+                      const char *groups_path,
+                      svn_boolean_t must_exist,
+                      svn_repos_t *repos_hint,
+                      apr_pool_t *result_pool,
+                      apr_pool_t *scratch_pool)
+{
+  return svn_error_trace(svn_repos_authz_read4(authz_p, path, groups_path,
+                                               must_exist, repos_hint,
+                                               NULL, NULL, result_pool,
+                                               scratch_pool));
+}
+
+svn_error_t *
 svn_repos_authz_read2(svn_authz_t **authz_p,
                       const char *path,
                       const char *groups_path,
@@ -1300,3 +1315,17 @@ svn_repos_authz_read(svn_authz_t **authz
   return svn_error_trace(svn_repos_authz_read2(authz_p, file, NULL,
                                                must_exist, pool));
 }
+
+svn_error_t *
+svn_repos_authz_parse(svn_authz_t **authz_p,
+                      svn_stream_t *stream,
+                      svn_stream_t *groups_stream,
+                      apr_pool_t *pool)
+{
+  apr_pool_t *scratch_pool = svn_pool_create(pool);
+  svn_error_t *err = svn_repos_authz_parse2(authz_p, stream, groups_stream,
+                                            NULL, NULL, pool, scratch_pool);
+  svn_pool_destroy(scratch_pool);
+
+  return svn_error_trace(err);
+}

Modified: subversion/branches/swig-py3/subversion/libsvn_repos/dump.c
URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/subversion/libsvn_repos/dump.c?rev=1862754&r1=1862753&r2=1862754&view=diff
==============================================================================
--- subversion/branches/swig-py3/subversion/libsvn_repos/dump.c (original)
+++ subversion/branches/swig-py3/subversion/libsvn_repos/dump.c Mon Jul  8 15:19:03 2019
@@ -44,6 +44,7 @@
 #include "private/svn_sorts_private.h"
 #include "private/svn_utf_private.h"
 #include "private/svn_cache.h"
+#include "private/svn_fspath.h"
 
 #define ARE_VALID_COPY_ARGS(p,r) ((p) && SVN_IS_VALID_REVNUM(r))
 
@@ -1996,6 +1997,11 @@ dump_filter_authz_func(svn_boolean_t *al
 {
   dump_filter_baton_t *b = baton;
 
+  /* For some nodes (e.g. files under copied directory) PATH may be
+   * non-canonical (missing leading '/').  Canonicalize PATH before
+   * passing it to FILTER_FUNC. */
+  path = svn_fspath__canonicalize(path, pool);
+
   return svn_error_trace(b->filter_func(allowed, root, path, b->filter_baton,
                                         pool));
 }

Modified: subversion/branches/swig-py3/subversion/libsvn_repos/replay.c
URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/subversion/libsvn_repos/replay.c?rev=1862754&r1=1862753&r2=1862754&view=diff
==============================================================================
--- subversion/branches/swig-py3/subversion/libsvn_repos/replay.c (original)
+++ subversion/branches/swig-py3/subversion/libsvn_repos/replay.c Mon Jul  8 15:19:03 2019
@@ -126,9 +126,6 @@ struct copy_info
 
 struct path_driver_cb_baton
 {
-  const svn_delta_editor_t *editor;
-  void *edit_baton;
-
   /* The root of the revision we're replaying. */
   svn_fs_root_t *root;
 
@@ -454,14 +451,14 @@ fill_copyfrom(svn_fs_root_t **copyfrom_r
 
 static svn_error_t *
 path_driver_cb_func(void **dir_baton,
+                    const svn_delta_editor_t *editor,
+                    void *edit_baton,
                     void *parent_baton,
                     void *callback_baton,
                     const char *edit_path,
                     apr_pool_t *pool)
 {
   struct path_driver_cb_baton *cb = callback_baton;
-  const svn_delta_editor_t *editor = cb->editor;
-  void *edit_baton = cb->edit_baton;
   svn_fs_root_t *root = cb->root;
   svn_fs_path_change3_t *change;
   svn_boolean_t do_add = FALSE, do_delete = FALSE;
@@ -957,8 +954,6 @@ svn_repos_replay2(svn_fs_root_t *root,
     low_water_mark = 0;
 
   /* Initialize our callback baton. */
-  cb_baton.editor = editor;
-  cb_baton.edit_baton = edit_baton;
   cb_baton.root = root;
   cb_baton.changed_paths = changed_paths;
   cb_baton.authz_read_func = authz_read_func;
@@ -989,7 +984,7 @@ svn_repos_replay2(svn_fs_root_t *root,
     }
 
   /* Call the path-based editor driver. */
-  return svn_delta_path_driver2(editor, edit_baton,
+  return svn_delta_path_driver3(editor, edit_baton,
                                 paths, TRUE,
                                 path_driver_cb_func, &cb_baton, pool);
 #else

Modified: subversion/branches/swig-py3/subversion/libsvn_subr/dirent_uri.c
URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/subversion/libsvn_subr/dirent_uri.c?rev=1862754&r1=1862753&r2=1862754&view=diff
==============================================================================
--- subversion/branches/swig-py3/subversion/libsvn_subr/dirent_uri.c (original)
+++ subversion/branches/swig-py3/subversion/libsvn_subr/dirent_uri.c Mon Jul  8 15:19:03 2019
@@ -37,6 +37,7 @@
 #include "svn_ctype.h"
 
 #include "dirent_uri.h"
+#include "private/svn_dirent_uri_private.h"
 #include "private/svn_fspath.h"
 #include "private/svn_cert.h"
 
@@ -934,14 +935,18 @@ svn_dirent_local_style(const char *diren
   return dirent;
 }
 
-const char *
-svn_relpath__internal_style(const char *relpath,
-                            apr_pool_t *pool)
+svn_error_t *
+svn_relpath__make_internal(const char **internal_style_relpath,
+                           const char *relpath,
+                           apr_pool_t *result_pool,
+                           apr_pool_t *scratch_pool)
 {
-  return svn_relpath_canonicalize(internal_style(relpath, pool), pool);
+  return svn_error_trace(
+      svn_relpath_canonicalize_safe(internal_style_relpath, NULL,
+                                    internal_style(relpath, scratch_pool),
+                                    result_pool, scratch_pool));
 }
 
-
 /* We decided against using apr_filepath_root here because of the negative
    performance impact (creating a pool and converting strings ). */
 svn_boolean_t

Modified: subversion/branches/swig-py3/subversion/libsvn_subr/error.c
URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/subversion/libsvn_subr/error.c?rev=1862754&r1=1862753&r2=1862754&view=diff
==============================================================================
--- subversion/branches/swig-py3/subversion/libsvn_subr/error.c (original)
+++ subversion/branches/swig-py3/subversion/libsvn_subr/error.c Mon Jul  8 15:19:03 2019
@@ -146,6 +146,7 @@ svn_error__locate(const char *file, long
 
 /* Cleanup function for errors.  svn_error_clear () removes this so
    errors that are properly handled *don't* hit this code. */
+#ifdef SVN_DEBUG
 static apr_status_t err_abort(void *data)
 {
   svn_error_t *err = data;  /* For easy viewing in a debugger */
@@ -155,6 +156,7 @@ static apr_status_t err_abort(void *data
     abort();
   return APR_SUCCESS;
 }
+#endif
 
 
 static svn_error_t *

Modified: subversion/branches/swig-py3/subversion/libsvn_subr/io.c
URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/subversion/libsvn_subr/io.c?rev=1862754&r1=1862753&r2=1862754&view=diff
==============================================================================
--- subversion/branches/swig-py3/subversion/libsvn_subr/io.c (original)
+++ subversion/branches/swig-py3/subversion/libsvn_subr/io.c Mon Jul  8 15:19:03 2019
@@ -155,8 +155,14 @@ typedef struct _FILE_DISPOSITION_INFO {
   BOOL DeleteFile;
 } FILE_DISPOSITION_INFO, *PFILE_DISPOSITION_INFO;
 
+typedef struct _FILE_ATTRIBUTE_TAG_INFO {
+  DWORD FileAttributes;
+  DWORD ReparseTag;
+} FILE_ATTRIBUTE_TAG_INFO, *PFILE_ATTRIBUTE_TAG_INFO;
+
 #define FileRenameInfo 3
 #define FileDispositionInfo 4
+#define FileAttributeTagInfo 9
 #endif /* WIN32 < Vista */
 
 /* One-time initialization of the late bound Windows API functions. */
@@ -169,19 +175,30 @@ typedef DWORD (WINAPI *GETFINALPATHNAMEB
                DWORD cchFilePath,
                DWORD dwFlags);
 
+typedef BOOL (WINAPI *GetFileInformationByHandleEx_t)(HANDLE hFile,
+                                                      int FileInformationClass,
+                                                      LPVOID lpFileInformation,
+                                                      DWORD dwBufferSize);
+
 typedef BOOL (WINAPI *SetFileInformationByHandle_t)(HANDLE hFile,
                                                     int FileInformationClass,
                                                     LPVOID lpFileInformation,
                                                     DWORD dwBufferSize);
 
 static GETFINALPATHNAMEBYHANDLE get_final_path_name_by_handle_proc = NULL;
+static GetFileInformationByHandleEx_t get_file_information_by_handle_ex_proc = NULL;
 static SetFileInformationByHandle_t set_file_information_by_handle_proc = NULL;
 
-/* Forward declaration. */
+/* Forward declarations. */
 static svn_error_t * io_win_read_link(svn_string_t **dest,
                                       const char *path,
                                       apr_pool_t *pool);
 
+static svn_error_t * io_win_check_path(svn_node_kind_t *kind_p,
+                                       svn_boolean_t *is_symlink_p,
+                                       const char *path,
+                                       apr_pool_t *pool);
+
 #endif
 
 /* Forward declaration */
@@ -342,13 +359,7 @@ io_check_path(const char *path,
   /* Not using svn_io_stat() here because we want to check the
      apr_err return explicitly. */
   SVN_ERR(cstring_from_utf8(&path_apr, path, pool));
-#ifdef WIN32
-  /* on Windows, svn does not handle reparse points or hard links.
-     So ignore the 'resolve_symlinks' flag. */
-  flags = APR_FINFO_MIN;
-#else
   flags = resolve_symlinks ? APR_FINFO_MIN : (APR_FINFO_MIN | APR_FINFO_LINK);
-#endif
   apr_err = apr_stat(&finfo, path_apr, flags, pool);
 
   if (APR_STATUS_IS_ENOENT(apr_err))
@@ -410,8 +421,12 @@ svn_io_check_resolved_path(const char *p
                            svn_node_kind_t *kind,
                            apr_pool_t *pool)
 {
+#if WIN32
+  return io_win_check_path(kind, NULL, path, pool);
+#else
   svn_boolean_t ignored;
   return io_check_path(path, TRUE, &ignored, kind, pool);
+#endif
 }
 
 svn_error_t *
@@ -419,8 +434,19 @@ svn_io_check_path(const char *path,
                   svn_node_kind_t *kind,
                   apr_pool_t *pool)
 {
+#if WIN32
+  svn_boolean_t is_symlink;
+
+  SVN_ERR(io_win_check_path(kind, &is_symlink, path, pool));
+
+  if (is_symlink)
+    *kind = svn_node_file;
+
+  return SVN_NO_ERROR;
+#else
   svn_boolean_t ignored;
   return io_check_path(path, FALSE, &ignored, kind, pool);
+#endif
 }
 
 svn_error_t *
@@ -429,7 +455,23 @@ svn_io_check_special_path(const char *pa
                           svn_boolean_t *is_special,
                           apr_pool_t *pool)
 {
+#ifdef WIN32
+  svn_boolean_t is_symlink;
+
+  SVN_ERR(io_win_check_path(kind, &is_symlink, path, pool));
+
+  if (is_symlink)
+    {
+      *is_special = TRUE;
+      *kind = svn_node_file;
+    }
+  else
+    *is_special = FALSE;
+
+  return SVN_NO_ERROR;
+#else
   return io_check_path(path, FALSE, is_special, kind, pool);
+#endif
 }
 
 struct temp_file_cleanup_s
@@ -1622,13 +1664,14 @@ merge_default_file_perms(apr_file_t *fd,
    that attempts to honor the users umask when dealing with
    permission changes.  It is a no-op when invoked on a symlink. */
 static svn_error_t *
-io_set_file_perms(const char *path,
-                  svn_boolean_t change_readwrite,
-                  svn_boolean_t enable_write,
-                  svn_boolean_t change_executable,
-                  svn_boolean_t executable,
-                  svn_boolean_t ignore_enoent,
-                  apr_pool_t *pool)
+io_set_perms(const char *path,
+             svn_boolean_t is_file,
+             svn_boolean_t change_readwrite,
+             svn_boolean_t enable_write,
+             svn_boolean_t change_executable,
+             svn_boolean_t executable,
+             svn_boolean_t ignore_enoent,
+             apr_pool_t *pool)
 {
   apr_status_t status;
   const char *path_apr;
@@ -1648,9 +1691,16 @@ io_set_file_perms(const char *path,
                             || SVN__APR_STATUS_IS_ENOTDIR(status)))
         return SVN_NO_ERROR;
       else if (status != APR_ENOTIMPL)
-        return svn_error_wrap_apr(status,
-                                  _("Can't change perms of file '%s'"),
-                                  svn_dirent_local_style(path, pool));
+        {
+          if (is_file)
+            return svn_error_wrap_apr(status,
+                                      _("Can't change perms of file '%s'"),
+                                      svn_dirent_local_style(path, pool));
+          else
+            return svn_error_wrap_apr(status,
+                                      _("Can't change perms of directory '%s'"),
+                                      svn_dirent_local_style(path, pool));
+        }
       return SVN_NO_ERROR;
     }
 
@@ -1750,10 +1800,50 @@ io_set_file_perms(const char *path,
       status = apr_file_attrs_set(path_apr, attrs, attrs_values, pool);
     }
 
-  return svn_error_wrap_apr(status,
-                            _("Can't change perms of file '%s'"),
-                            svn_dirent_local_style(path, pool));
+  if (is_file)
+    {
+      return svn_error_wrap_apr(status,
+                                _("Can't change perms of file '%s'"),
+                                svn_dirent_local_style(path, pool));
+    }
+  else
+    {
+      return svn_error_wrap_apr(status,
+                                _("Can't change perms of directory '%s'"),
+                                svn_dirent_local_style(path, pool));
+    }
+}
+
+static svn_error_t *
+io_set_file_perms(const char *path,
+                  svn_boolean_t change_readwrite,
+                  svn_boolean_t enable_write,
+                  svn_boolean_t change_executable,
+                  svn_boolean_t executable,
+                  svn_boolean_t ignore_enoent,
+                  apr_pool_t *pool)
+{
+  return svn_error_trace(io_set_perms(path, TRUE,
+                                      change_readwrite, enable_write,
+                                      change_executable, executable,
+                                      ignore_enoent, pool));
+}
+
+static svn_error_t *
+io_set_dir_perms(const char *path,
+                 svn_boolean_t change_readwrite,
+                 svn_boolean_t enable_write,
+                 svn_boolean_t change_executable,
+                 svn_boolean_t executable,
+                 svn_boolean_t ignore_enoent,
+                 apr_pool_t *pool)
+{
+  return svn_error_trace(io_set_perms(path, FALSE,
+                                      change_readwrite, enable_write,
+                                      change_executable, executable,
+                                      ignore_enoent, pool));
 }
+
 #endif /* !WIN32 && !__OS2__ */
 
 #ifdef WIN32
@@ -1902,6 +1992,9 @@ static svn_error_t *win_init_dynamic_imp
       get_final_path_name_by_handle_proc = (GETFINALPATHNAMEBYHANDLE)
         GetProcAddress(kernel32, "GetFinalPathNameByHandleW");
 
+      get_file_information_by_handle_ex_proc = (GetFileInformationByHandleEx_t)
+        GetProcAddress(kernel32, "GetFileInformationByHandleEx");
+
       set_file_information_by_handle_proc = (SetFileInformationByHandle_t)
         GetProcAddress(kernel32, "SetFileInformationByHandle");
     }
@@ -1978,6 +2071,33 @@ static svn_error_t * io_win_read_link(sv
       }
 }
 
+/* Wrapper around Windows API function GetFileInformationByHandleEx() that
+ * returns APR status instead of boolean flag. */
+static apr_status_t
+win32_get_file_information_by_handle(HANDLE hFile,
+                                     int FileInformationClass,
+                                     LPVOID lpFileInformation,
+                                     DWORD dwBufferSize)
+{
+  svn_error_clear(svn_atomic__init_once(&win_dynamic_imports_state,
+                                        win_init_dynamic_imports,
+                                        NULL, NULL));
+
+  if (!get_file_information_by_handle_ex_proc)
+    {
+      return SVN_ERR_UNSUPPORTED_FEATURE;
+    }
+
+  if (!get_file_information_by_handle_ex_proc(hFile, FileInformationClass,
+                                              lpFileInformation,
+                                              dwBufferSize))
+    {
+      return apr_get_os_error();
+    }
+
+  return APR_SUCCESS;
+}
+
 /* Wrapper around Windows API function SetFileInformationByHandle() that
  * returns APR status instead of boolean flag. */
 static apr_status_t
@@ -2005,6 +2125,105 @@ win32_set_file_information_by_handle(HAN
   return APR_SUCCESS;
 }
 
+/* Fast Win32-specific helper for svn_io_check_path() and related functions
+ * that only requires a single GetFileAttributes() call in most cases.
+ */
+static svn_error_t * io_win_check_path(svn_node_kind_t *kind_p,
+                                       svn_boolean_t *is_symlink_p,
+                                       const char *path,
+                                       apr_pool_t *pool)
+{
+  DWORD attrs;
+  const WCHAR *wpath;
+  apr_status_t status;
+
+  if (path[0] == '\0')
+    path = ".";
+
+  SVN_ERR(svn_io__utf8_to_unicode_longpath(&wpath, path, pool));
+
+  attrs = GetFileAttributesW(wpath);
+  if (attrs == INVALID_FILE_ATTRIBUTES)
+    {
+      status = apr_get_os_error();
+      if (APR_STATUS_IS_ENOENT(status) || SVN__APR_STATUS_IS_ENOTDIR(status))
+        {
+          *kind_p = svn_node_none;
+          if (is_symlink_p)
+            *is_symlink_p = FALSE;
+          return SVN_NO_ERROR;
+        }
+      else
+        {
+          return svn_error_wrap_apr(status, _("Can't stat '%s'"),
+                                    svn_dirent_local_style(path, pool));
+        }
+    }
+
+  if (attrs & FILE_ATTRIBUTE_DIRECTORY)
+    *kind_p = svn_node_dir;
+  else
+    *kind_p = svn_node_file;
+
+  /* If this is a reparse point, and if we've been asked to check whether
+     we are dealing with a symlink, then open the file and check that.
+
+     Otherwise, it's either definitely not a symlink or the caller
+     doesn't care about this distinction.
+   */
+  if (is_symlink_p && (attrs & FILE_ATTRIBUTE_REPARSE_POINT))
+    {
+      const WCHAR *wfname;
+      HANDLE hFile;
+      FILE_ATTRIBUTE_TAG_INFO taginfo = { 0 };
+
+      SVN_ERR(svn_io__utf8_to_unicode_longpath(&wfname, path, pool));
+
+      hFile = CreateFileW(wfname, FILE_READ_ATTRIBUTES,
+                          FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+                          NULL, OPEN_EXISTING,
+                          FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS,
+                          NULL);
+      if (hFile == INVALID_HANDLE_VALUE)
+        {
+          status = apr_get_os_error();
+          if (APR_STATUS_IS_ENOENT(status) || SVN__APR_STATUS_IS_ENOTDIR(status))
+            {
+              *kind_p = svn_node_none;
+              *is_symlink_p = FALSE;
+              return SVN_NO_ERROR;
+            }
+          else
+            {
+              return svn_error_wrap_apr(status, _("Can't stat '%s'"),
+                                        svn_dirent_local_style(path, pool));
+            }
+        }
+
+      status = win32_get_file_information_by_handle(hFile, FileAttributeTagInfo,
+                                                    &taginfo, sizeof(taginfo));
+      CloseHandle(hFile);
+
+      if (status)
+        return svn_error_wrap_apr(status, _("Can't stat '%s'"),
+                                  svn_dirent_local_style(path, pool));
+
+      /* The surrogate bit in the reparse tag specifies if "the file or directory
+         represents another named entity in the system" which is used to determine
+         if this reparse point behaves like a symlink.
+
+         https://docs.microsoft.com/en-us/windows/desktop/fileio/reparse-point-tags
+       */
+      *is_symlink_p = IsReparseTagNameSurrogate(taginfo.ReparseTag);
+    }
+  else if (is_symlink_p)
+    {
+      *is_symlink_p = FALSE;
+    }
+
+  return SVN_NO_ERROR;
+}
+
 svn_error_t *
 svn_io__win_delete_file_on_close(apr_file_t *file,
                                  const char *path,
@@ -2115,6 +2334,55 @@ svn_io_set_file_read_write_carefully(con
   return svn_io_set_file_read_only(path, ignore_enoent, pool);
 }
 
+#if defined(WIN32) || defined(__OS2__)
+/* Helper for svn_io_set_file_read_* */
+static svn_error_t *
+io_set_readonly_flag(const char *path_apr, /* file-system path */
+                     const char *path,     /* UTF-8 path */
+                     svn_boolean_t set_flag,
+                     svn_boolean_t is_file,
+                     svn_boolean_t ignore_enoent,
+                     apr_pool_t *pool)
+{
+  apr_status_t status;
+
+  status = apr_file_attrs_set(path_apr,
+                              (set_flag ? APR_FILE_ATTR_READONLY : 0),
+                              APR_FILE_ATTR_READONLY,
+                              pool);
+
+  if (status && status != APR_ENOTIMPL)
+    if (!(ignore_enoent && (APR_STATUS_IS_ENOENT(status)
+                            || SVN__APR_STATUS_IS_ENOTDIR(status))))
+      {
+        if (is_file)
+          {
+            if (set_flag)
+              return svn_error_wrap_apr(status,
+                                        _("Can't set file '%s' read-only"),
+                                        svn_dirent_local_style(path, pool));
+            else
+              return svn_error_wrap_apr(status,
+                                        _("Can't set file '%s' read-write"),
+                                        svn_dirent_local_style(path, pool));
+          }
+        else
+          {
+            if (set_flag)
+              return svn_error_wrap_apr(status,
+                                        _("Can't set directory '%s' read-only"),
+                                        svn_dirent_local_style(path, pool));
+            else
+              return svn_error_wrap_apr(status,
+                                        _("Can't set directory '%s' read-write"),
+                                        svn_dirent_local_style(path, pool));
+          }
+      }
+  return SVN_NO_ERROR;
+}
+#endif
+
+
 svn_error_t *
 svn_io_set_file_read_only(const char *path,
                           svn_boolean_t ignore_enoent,
@@ -2126,24 +2394,11 @@ svn_io_set_file_read_only(const char *pa
   return io_set_file_perms(path, TRUE, FALSE, FALSE, FALSE,
                            ignore_enoent, pool);
 #else
-  apr_status_t status;
   const char *path_apr;
 
   SVN_ERR(cstring_from_utf8(&path_apr, path, pool));
-
-  status = apr_file_attrs_set(path_apr,
-                              APR_FILE_ATTR_READONLY,
-                              APR_FILE_ATTR_READONLY,
-                              pool);
-
-  if (status && status != APR_ENOTIMPL)
-    if (!(ignore_enoent && (APR_STATUS_IS_ENOENT(status)
-                            || SVN__APR_STATUS_IS_ENOTDIR(status))))
-      return svn_error_wrap_apr(status,
-                                _("Can't set file '%s' read-only"),
-                                svn_dirent_local_style(path, pool));
-
-  return SVN_NO_ERROR;
+  return io_set_readonly_flag(path_apr, path,
+                              TRUE, TRUE, ignore_enoent, pool);
 #endif
 }
 
@@ -2159,23 +2414,11 @@ svn_io_set_file_read_write(const char *p
   return io_set_file_perms(path, TRUE, TRUE, FALSE, FALSE,
                            ignore_enoent, pool);
 #else
-  apr_status_t status;
   const char *path_apr;
 
   SVN_ERR(cstring_from_utf8(&path_apr, path, pool));
-
-  status = apr_file_attrs_set(path_apr,
-                              0,
-                              APR_FILE_ATTR_READONLY,
-                              pool);
-
-  if (status && status != APR_ENOTIMPL)
-    if (!ignore_enoent || !APR_STATUS_IS_ENOENT(status))
-      return svn_error_wrap_apr(status,
-                                _("Can't set file '%s' read-write"),
-                                svn_dirent_local_style(path, pool));
-
-  return SVN_NO_ERROR;
+  return io_set_readonly_flag(path_apr, path,
+                              FALSE, TRUE, ignore_enoent, pool);
 #endif
 }
 
@@ -2761,6 +3004,12 @@ svn_io_remove_dir2(const char *path, svn
       return svn_error_trace(err);
     }
 
+  /* On Unix, nothing can be removed from a non-writable directory. */
+#if !defined(WIN32) && !defined(__OS2__)
+  SVN_ERR(io_set_dir_perms(path, TRUE, TRUE, FALSE, FALSE,
+                           ignore_enoent, pool));
+#endif
+
   for (hi = apr_hash_first(subpool, dirents); hi; hi = apr_hash_next(hi))
     {
       const char *name = apr_hash_this_key(hi);
@@ -4499,8 +4748,17 @@ svn_io_dir_remove_nonrecursive(const cha
   {
     svn_boolean_t retry = TRUE;
 
+    if (APR_STATUS_IS_EACCES(status) || APR_STATUS_IS_EEXIST(status))
+      {
+        /* Make the destination directory writable because Windows
+           forbids deleting read-only items. */
+        SVN_ERR(io_set_readonly_flag(dirname_apr, dirname,
+                                     FALSE, FALSE, TRUE, pool));
+        status = apr_dir_remove(dirname_apr, pool);
+      }
+
     if (status == APR_FROM_OS_ERROR(ERROR_DIR_NOT_EMPTY))
-    {
+      {
         apr_status_t empty_status = dir_is_empty(dirname_apr, pool);
 
         if (APR_STATUS_IS_ENOTEMPTY(empty_status))

Modified: subversion/branches/swig-py3/subversion/libsvn_subr/pool.c
URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/subversion/libsvn_subr/pool.c?rev=1862754&r1=1862753&r2=1862754&view=diff
==============================================================================
--- subversion/branches/swig-py3/subversion/libsvn_subr/pool.c (original)
+++ subversion/branches/swig-py3/subversion/libsvn_subr/pool.c Mon Jul  8 15:19:03 2019
@@ -133,7 +133,7 @@ svn_pool_create_allocator(svn_boolean_t
 #endif
 
   /* By default, allocators are *not* thread-safe. We must provide a mutex
-   * if we want thread-safety for that mutex. */
+   * if we want thread-safety for that pool. */
 
 #if APR_HAS_THREADS
   if (thread_safe)

Modified: subversion/branches/swig-py3/subversion/libsvn_subr/version.c
URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/subversion/libsvn_subr/version.c?rev=1862754&r1=1862753&r2=1862754&view=diff
==============================================================================
--- subversion/branches/swig-py3/subversion/libsvn_subr/version.c (original)
+++ subversion/branches/swig-py3/subversion/libsvn_subr/version.c Mon Jul  8 15:19:03 2019
@@ -143,7 +143,7 @@ svn_version_extended(svn_boolean_t verbo
   info->build_time = __TIME__;
   info->build_host = SVN_BUILD_HOST;
   info->copyright = apr_pstrdup
-    (pool, _("Copyright (C) 2018 The Apache Software Foundation.\n"
+    (pool, _("Copyright (C) 2019 The Apache Software Foundation.\n"
              "This software consists of contributions made by many people;\n"
              "see the NOTICE file for more information.\n"
              "Subversion is open source software, see "

Modified: subversion/branches/swig-py3/subversion/libsvn_wc/node.c
URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/subversion/libsvn_wc/node.c?rev=1862754&r1=1862753&r2=1862754&view=diff
==============================================================================
--- subversion/branches/swig-py3/subversion/libsvn_wc/node.c (original)
+++ subversion/branches/swig-py3/subversion/libsvn_wc/node.c Mon Jul  8 15:19:03 2019
@@ -1140,3 +1140,17 @@ svn_wc__find_working_nodes_with_basename
                            abspaths, wc_ctx->db, wri_abspath, basename, kind,
                            result_pool, scratch_pool));
 }
+
+svn_error_t *
+svn_wc__find_copies_of_repos_path(apr_array_header_t **abspaths,
+                                  const char *wri_abspath,
+                                  const char *repos_relpath,
+                                  svn_node_kind_t kind,
+                                  svn_wc_context_t *wc_ctx,
+                                  apr_pool_t *result_pool,
+                                  apr_pool_t *scratch_pool)
+{
+  return svn_error_trace(svn_wc__db_find_copies_of_repos_path(
+                           abspaths, wc_ctx->db, wri_abspath, repos_relpath,
+                           kind, result_pool, scratch_pool));
+}

Modified: subversion/branches/swig-py3/subversion/libsvn_wc/revert.c
URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/subversion/libsvn_wc/revert.c?rev=1862754&r1=1862753&r2=1862754&view=diff
==============================================================================
--- subversion/branches/swig-py3/subversion/libsvn_wc/revert.c (original)
+++ subversion/branches/swig-py3/subversion/libsvn_wc/revert.c Mon Jul  8 15:19:03 2019
@@ -62,6 +62,18 @@
       the addition of all the directory's children.  Again,
       svn_wc_remove_from_revision_control() should do the trick.
 
+    - For a copy, we remove the item from disk as well. The thinking here
+      is that Subversion is responsible for the existence of the item: it
+      must have been created by something like 'svn copy' or 'svn merge'.
+
+    - For a plain add, removing the file or directory from disk is optional.
+      The user's idea of Subversion's involvement could be either that
+      Subversion was just responsible for adding an existing item to version
+      control, as with 'svn add', and so should not be responsible for
+      deleting it from disk; or that Subversion is responsible for the
+      existence of the item, e.g. if created by 'svn patch' or svn mkdir'.
+      It depends on the use case.
+
     Deletes
 
     - Restore properties to their unmodified state.

Modified: subversion/branches/swig-py3/subversion/libsvn_wc/update_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/subversion/libsvn_wc/update_editor.c?rev=1862754&r1=1862753&r2=1862754&view=diff
==============================================================================
--- subversion/branches/swig-py3/subversion/libsvn_wc/update_editor.c (original)
+++ subversion/branches/swig-py3/subversion/libsvn_wc/update_editor.c Mon Jul  8 15:19:03 2019
@@ -1458,7 +1458,7 @@ check_tree_conflict(svn_skel_t **pconfli
          * Therefore, we need to start a separate crawl here. */
 
         SVN_ERR(svn_wc__node_has_local_mods(&modified, NULL,
-                                            eb->db, local_abspath, FALSE,
+                                            eb->db, local_abspath, TRUE,
                                             eb->cancel_func, eb->cancel_baton,
                                             scratch_pool));
 

Modified: subversion/branches/swig-py3/subversion/libsvn_wc/wc-queries.sql
URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/subversion/libsvn_wc/wc-queries.sql?rev=1862754&r1=1862753&r2=1862754&view=diff
==============================================================================
--- subversion/branches/swig-py3/subversion/libsvn_wc/wc-queries.sql (original)
+++ subversion/branches/swig-py3/subversion/libsvn_wc/wc-queries.sql Mon Jul  8 15:19:03 2019
@@ -1796,6 +1796,17 @@ WHERE wc_id = ?1
 SELECT 1 FROM sqlite_master WHERE name='sqlite_stat1' AND type='table'
 LIMIT 1
 
+-- STMT_SELECT_COPIES_OF_REPOS_RELPATH
+SELECT local_relpath
+FROM nodes n
+WHERE wc_id = ?1 AND repos_path = ?2 AND kind = ?3
+  AND presence = MAP_NORMAL
+  AND op_depth = (SELECT MAX(op_depth)
+                  FROM NODES w
+                  WHERE w.wc_id = ?1
+                    AND w.local_relpath = n.local_relpath)
+ORDER BY local_relpath ASC
+
 /* ------------------------------------------------------------------------- */
 
 /* Grab all the statements related to the schema.  */

Modified: subversion/branches/swig-py3/subversion/libsvn_wc/wc_db.c
URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/subversion/libsvn_wc/wc_db.c?rev=1862754&r1=1862753&r2=1862754&view=diff
==============================================================================
--- subversion/branches/swig-py3/subversion/libsvn_wc/wc_db.c (original)
+++ subversion/branches/swig-py3/subversion/libsvn_wc/wc_db.c Mon Jul  8 15:19:03 2019
@@ -16663,3 +16663,47 @@ svn_wc__db_find_working_nodes_with_basen
 
   return svn_error_trace(svn_sqlite__reset(stmt));
 }
+
+svn_error_t *
+svn_wc__db_find_copies_of_repos_path(apr_array_header_t **local_abspaths,
+                                     svn_wc__db_t *db,
+                                     const char *wri_abspath,
+                                     const char *repos_relpath,
+                                     svn_node_kind_t kind,
+                                     apr_pool_t *result_pool,
+                                     apr_pool_t *scratch_pool)
+{
+  svn_wc__db_wcroot_t *wcroot;
+  const char *wri_relpath;
+  svn_sqlite__stmt_t *stmt;
+  svn_boolean_t have_row;
+
+  SVN_ERR_ASSERT(svn_dirent_is_absolute(wri_abspath));
+
+  SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &wri_relpath, db,
+                                                wri_abspath, scratch_pool,
+                                                scratch_pool));
+  VERIFY_USABLE_WCROOT(wcroot);
+
+  SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb,
+            STMT_SELECT_COPIES_OF_REPOS_RELPATH));
+  SVN_ERR(svn_sqlite__bindf(stmt, "ist", wcroot->wc_id, repos_relpath,
+                            kind_map, kind));
+  SVN_ERR(svn_sqlite__step(&have_row, stmt));
+
+  *local_abspaths = apr_array_make(result_pool, 1, sizeof(const char *));
+
+  while (have_row)
+    {
+      const char *local_relpath;
+      const char *local_abspath;
+
+      local_relpath = svn_sqlite__column_text(stmt, 0, NULL);
+      local_abspath = svn_dirent_join(wcroot->abspath, local_relpath,
+                                      result_pool);
+      APR_ARRAY_PUSH(*local_abspaths, const char *) = local_abspath;
+      SVN_ERR(svn_sqlite__step(&have_row, stmt));
+    }
+
+  return svn_error_trace(svn_sqlite__reset(stmt));
+}

Modified: subversion/branches/swig-py3/subversion/libsvn_wc/wc_db.h
URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/subversion/libsvn_wc/wc_db.h?rev=1862754&r1=1862753&r2=1862754&view=diff
==============================================================================
--- subversion/branches/swig-py3/subversion/libsvn_wc/wc_db.h (original)
+++ subversion/branches/swig-py3/subversion/libsvn_wc/wc_db.h Mon Jul  8 15:19:03 2019
@@ -3520,6 +3520,24 @@ svn_wc__db_find_working_nodes_with_basen
                                             svn_node_kind_t kind,
                                             apr_pool_t *result_pool,
                                             apr_pool_t *scratch_pool);
+
+/* Return an array of const char * elements, which represent local absolute
+ * paths for nodes, within the working copy indicated by WRI_ABSPATH, which
+ * are copies of REPOS_RELPATH and have node kind KIND.
+ * If no such nodes exist, return an empty array.
+ *
+ * This function returns only paths to nodes which are present in the highest
+ * layer of the WC. In other words, paths to deleted and/or excluded nodes are
+ * never returned.
+ */
+svn_error_t *
+svn_wc__db_find_copies_of_repos_path(apr_array_header_t **local_abspaths,
+                                     svn_wc__db_t *db,
+                                     const char *wri_abspath,
+                                     const char *repos_relpath,
+                                     svn_node_kind_t kind,
+                                     apr_pool_t *result_pool,
+                                     apr_pool_t *scratch_pool);
 /* @} */
 
 typedef svn_error_t * (*svn_wc__db_verify_cb_t)(void *baton,

Modified: subversion/branches/swig-py3/subversion/libsvn_wc/wc_db_update_move.c
URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/subversion/libsvn_wc/wc_db_update_move.c?rev=1862754&r1=1862753&r2=1862754&view=diff
==============================================================================
--- subversion/branches/swig-py3/subversion/libsvn_wc/wc_db_update_move.c (original)
+++ subversion/branches/swig-py3/subversion/libsvn_wc/wc_db_update_move.c Mon Jul  8 15:19:03 2019
@@ -2175,11 +2175,12 @@ suitable_for_move(svn_wc__db_wcroot_t *w
   while (have_row)
     {
       svn_revnum_t node_revision = svn_sqlite__column_revnum(stmt, 2);
-      const char *child_relpath = svn_sqlite__column_text(stmt, 0, NULL);
+      const char *child_relpath;
       const char *relpath;
 
       svn_pool_clear(iterpool);
 
+      child_relpath = svn_sqlite__column_text(stmt, 0, iterpool);
       relpath = svn_relpath_skip_ancestor(local_relpath, child_relpath);
       relpath = svn_relpath_join(repos_relpath, relpath, iterpool);
 

Modified: subversion/branches/swig-py3/subversion/libsvn_wc/wcroot_anchor.c
URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/subversion/libsvn_wc/wcroot_anchor.c?rev=1862754&r1=1862753&r2=1862754&view=diff
==============================================================================
--- subversion/branches/swig-py3/subversion/libsvn_wc/wcroot_anchor.c (original)
+++ subversion/branches/swig-py3/subversion/libsvn_wc/wcroot_anchor.c Mon Jul  8 15:19:03 2019
@@ -183,21 +183,20 @@ svn_wc__get_wcroot(const char **wcroot_a
 
 
 svn_error_t *
-svn_wc__get_shelves_dir(char **dir,
-                        svn_wc_context_t *wc_ctx,
-                        const char *local_abspath,
-                        apr_pool_t *result_pool,
-                        apr_pool_t *scratch_pool)
+svn_wc__get_experimental_dir(char **dir,
+                             svn_wc_context_t *wc_ctx,
+                             const char *local_abspath,
+                             apr_pool_t *result_pool,
+                             apr_pool_t *scratch_pool)
 {
   const char *wcroot_abspath;
 
   SVN_ERR(svn_wc__get_wcroot(&wcroot_abspath, wc_ctx, local_abspath,
                              scratch_pool, scratch_pool));
   *dir = svn_dirent_join(wcroot_abspath,
-                         SVN_WC_ADM_DIR_NAME "/" SVN_WC__ADM_EXPERIMENTAL "/"
-                           "shelves/v2",
+                         SVN_WC_ADM_DIR_NAME "/" SVN_WC__ADM_EXPERIMENTAL,
                          result_pool);
-  
+
   /* Ensure the directory exists. (Other versions of svn don't create it.) */
   SVN_ERR(svn_io_make_dir_recursively(*dir, scratch_pool));
 

Modified: subversion/branches/swig-py3/subversion/mod_authz_svn/mod_authz_svn.c
URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/subversion/mod_authz_svn/mod_authz_svn.c?rev=1862754&r1=1862753&r2=1862754&view=diff
==============================================================================
--- subversion/branches/swig-py3/subversion/mod_authz_svn/mod_authz_svn.c (original)
+++ subversion/branches/swig-py3/subversion/mod_authz_svn/mod_authz_svn.c Mon Jul  8 15:19:03 2019
@@ -327,16 +327,17 @@ log_access_verdict(LOG_ARGS_SIGNATURE,
     }
 }
 
-/* Log a message indiciating the ERR encountered during the request R.
+/* Log a message at LOG_LEVEL indiciating the ERR encountered during
+ * the request R.
  * LOG_ARGS_SIGNATURE expands as in log_access_verdict() above.
  * PREFIX is inserted at the start of the message.  The rest of the
  * message is generated by combining the message for each error in the
  * chain of ERR, excluding for trace errors.  ERR will be cleared
  * when finished. */
 static void
-log_svn_error(LOG_ARGS_SIGNATURE,
-              request_rec *r, const char *prefix,
-              svn_error_t *err, apr_pool_t *scratch_pool)
+log_svn_message(LOG_ARGS_SIGNATURE, int log_level,
+                request_rec *r, const char *prefix,
+                svn_error_t *err, apr_pool_t *scratch_pool)
 {
   svn_error_t *err_pos = svn_error_purge_tracing(err);
   svn_stringbuf_t *buff = svn_stringbuf_create(prefix, scratch_pool);
@@ -360,7 +361,7 @@ log_svn_error(LOG_ARGS_SIGNATURE,
       err_pos = err_pos->child;
     }
 
-  ap_log_rerror(LOG_ARGS_CASCADE, APLOG_ERR,
+  ap_log_rerror(LOG_ARGS_CASCADE, log_level,
                 /* If it is an error code that APR can make sense of, then
                    show it, otherwise, pass zero to avoid putting "APR does
                    not understand this error code" in the error log. */
@@ -372,6 +373,40 @@ log_svn_error(LOG_ARGS_SIGNATURE,
   svn_error_clear(err);
 }
 
+/* Log the error error ERR encountered during the request R.
+ * LOG_ARGS_SIGNATURE expands as in log_access_verdict() above.
+ * PREFIX is inserted at the start of the message.  The rest of the
+ * message is generated by combining the message for each error in the
+ * chain of ERR, excluding for trace errors.  ERR will be cleared
+ * when finished. */
+static APR_INLINE void
+log_svn_error(LOG_ARGS_SIGNATURE,
+              request_rec *r, const char *prefix,
+              svn_error_t *err, apr_pool_t *scratch_pool)
+{
+  log_svn_message(LOG_ARGS_CASCADE, APLOG_ERR,
+                  r, prefix, err, scratch_pool);
+}
+
+/* Baton for log_authz_warning. */
+typedef struct authz_warning_baton_t
+{
+  request_rec *r;
+  const char *prefix;
+} authz_warning_baton_t;
+
+/* Handle an authz parser warning. ERR will *not* be cleared.*/
+static APR_INLINE void
+log_authz_warning(void *baton,
+                  const svn_error_t *err,
+                  apr_pool_t *scratch_pool)
+{
+  const authz_warning_baton_t *const warning_baton = baton;
+  log_svn_message(APLOG_MARK, APLOG_WARNING,
+                  warning_baton->r, warning_baton->prefix,
+                  svn_error_dup(err), scratch_pool);
+}
+
 /* Resolve *PATH into an absolute canonical URL iff *PATH is a repos-relative
  * URL.  If *REPOS_URL is NULL convert REPOS_PATH into a file URL stored
  * in *REPOS_URL, if *REPOS_URL is not null REPOS_PATH is ignored.  The
@@ -472,8 +507,13 @@ get_access_conf(request_rec *r, authz_sv
   access_conf = user_data;
   if (access_conf == NULL)
     {
-      svn_err = svn_repos_authz_read3(&access_conf, access_file,
+      authz_warning_baton_t warning_baton;
+      warning_baton.r = r;
+      warning_baton.prefix = "mod_authz_svn: warning:";
+
+      svn_err = svn_repos_authz_read4(&access_conf, access_file,
                                       groups_file, TRUE, NULL,
+                                      log_authz_warning, &warning_baton,
                                       r->connection->pool,
                                       scratch_pool);
 

Modified: subversion/branches/swig-py3/subversion/mod_dav_svn/reports/list.c
URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/subversion/mod_dav_svn/reports/list.c?rev=1862754&r1=1862753&r2=1862754&view=diff
==============================================================================
--- subversion/branches/swig-py3/subversion/mod_dav_svn/reports/list.c (original)
+++ subversion/branches/swig-py3/subversion/mod_dav_svn/reports/list.c Mon Jul  8 15:19:03 2019
@@ -201,7 +201,7 @@ dav_svn__list_report(const dav_resource
   dav_svn__authz_read_baton arb;
   const dav_svn_repos *repos = resource->info->repos;
   int ns;
-  const char *full_path;
+  const char *full_path = NULL;
   svn_boolean_t path_info_only;
   svn_fs_root_t *root;
   svn_depth_t depth = svn_depth_unknown;
@@ -280,6 +280,12 @@ dav_svn__list_report(const dav_resource
       /* else unknown element; skip it */
     }
 
+  if (! full_path)
+    {
+      return dav_svn__new_error_svn(resource->pool, HTTP_BAD_REQUEST, 0, 0,
+                                    "Request was missing the path argument");
+    }
+
   /* Build authz read baton */
   arb.r = resource->info->r;
   arb.repos = resource->info->repos;

Modified: subversion/branches/swig-py3/subversion/mod_dav_svn/repos.c
URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/subversion/mod_dav_svn/repos.c?rev=1862754&r1=1862753&r2=1862754&view=diff
==============================================================================
--- subversion/branches/swig-py3/subversion/mod_dav_svn/repos.c (original)
+++ subversion/branches/swig-py3/subversion/mod_dav_svn/repos.c Mon Jul  8 15:19:03 2019
@@ -1225,25 +1225,32 @@ create_private_resource(const dav_resour
   return &comb->res;
 }
 
-
-static void log_warning(void *baton, svn_error_t *err)
+static void log_warning_req(void *baton, svn_error_t *err)
 {
   request_rec *r = baton;
   const char *continuation = "";
 
-  /* ### hmm. the FS is cleaned up at request cleanup time. "r" might
-     ### not really be valid. we should probably put the FS into a
-     ### subpool to ensure it gets cleaned before the request.
+  /* Not showing file/line so no point in tracing */
+  err = svn_error_purge_tracing(err);
+  while (err)
+    {
+      ap_log_rerror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, r, "%s%s",
+                    continuation, err->message);
+      continuation = "-";
+      err = err->child;
+    }
+}
 
-     ### is there a good way to create and use a subpool for all
-     ### of our functions ... ??
-  */
+static void log_warning_conn(void *baton, svn_error_t *err)
+{
+  conn_rec *c = baton;
+  const char *continuation = "";
 
   /* Not showing file/line so no point in tracing */
   err = svn_error_purge_tracing(err);
   while (err)
     {
-      ap_log_rerror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, r, "%s%s",
+      ap_log_cerror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, c, "%s%s",
                     continuation, err->message);
       continuation = "-";
       err = err->child;
@@ -1547,6 +1554,24 @@ cleanup_fs_access(void *data)
   return APR_SUCCESS;
 }
 
+/* Context for cleanup handler. */
+struct cleanup_req_logging_baton
+{
+  svn_fs_t *fs;
+  conn_rec *connection;
+};
+
+static apr_status_t
+cleanup_req_logging(void *data)
+{
+  struct cleanup_req_logging_baton *baton = data;
+
+  /* The request about to be freed. Log future warnings with a connection
+   * context instead of a request context. */
+  svn_fs_set_warning_func(baton->fs, log_warning_conn, baton->connection);
+
+  return APR_SUCCESS;
+}
 
 /* Helper func to construct a special 'parentpath' private resource. */
 static dav_error *
@@ -2180,6 +2205,7 @@ get_resource(request_rec *r,
   int had_slash;
   dav_locktoken_list *ltl;
   struct cleanup_fs_access_baton *cleanup_baton;
+  struct cleanup_req_logging_baton *cleanup_req_logging_baton;
   void *userdata;
   apr_hash_t *fs_config;
 
@@ -2486,7 +2512,7 @@ get_resource(request_rec *r,
   repos->fs = svn_repos_fs(repos->repos);
 
   /* capture warnings during cleanup of the FS */
-  svn_fs_set_warning_func(repos->fs, log_warning, r);
+  svn_fs_set_warning_func(repos->fs, log_warning_req, r);
 
   /* if an authenticated username is present, attach it to the FS */
   if (r->user)
@@ -2503,6 +2529,14 @@ get_resource(request_rec *r,
       apr_pool_cleanup_register(r->pool, cleanup_baton, cleanup_fs_access,
                                 apr_pool_cleanup_null);
 
+      /* We must degrade the logging context when the request is freed. */
+      cleanup_req_logging_baton =
+        apr_pcalloc(r->pool, sizeof(*cleanup_req_logging_baton));
+      cleanup_req_logging_baton->fs = repos->fs;
+      cleanup_req_logging_baton->connection = r->connection;
+      apr_pool_pre_cleanup_register(r->pool, cleanup_req_logging_baton,
+                                    cleanup_req_logging);
+
       /* Create an access context based on the authenticated username. */
       serr = svn_fs_create_access(&access_ctx, r->user, r->pool);
       if (serr)

Modified: subversion/branches/swig-py3/subversion/svn/blame-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/subversion/svn/blame-cmd.c?rev=1862754&r1=1862753&r2=1862754&view=diff
==============================================================================
--- subversion/branches/swig-py3/subversion/svn/blame-cmd.c (original)
+++ subversion/branches/swig-py3/subversion/svn/blame-cmd.c Mon Jul  8 15:19:03 2019
@@ -44,6 +44,7 @@ typedef struct blame_baton_t
   svn_stream_t *out;
   svn_stringbuf_t *sbuf;
 
+  svn_revnum_t start_revnum, end_revnum;
   int rev_maxlength;
 } blame_baton_t;
 
@@ -54,15 +55,13 @@ typedef struct blame_baton_t
    XML to stdout. */
 static svn_error_t *
 blame_receiver_xml(void *baton,
-                   svn_revnum_t start_revnum,
-                   svn_revnum_t end_revnum,
                    apr_int64_t line_no,
                    svn_revnum_t revision,
                    apr_hash_t *rev_props,
                    svn_revnum_t merged_revision,
                    apr_hash_t *merged_rev_props,
                    const char *merged_path,
-                   const char *line,
+                   const svn_string_t *line,
                    svn_boolean_t local_change,
                    apr_pool_t *pool)
 {
@@ -170,15 +169,13 @@ print_line_info(svn_stream_t *out,
 /* This implements the svn_client_blame_receiver3_t interface. */
 static svn_error_t *
 blame_receiver(void *baton,
-               svn_revnum_t start_revnum,
-               svn_revnum_t end_revnum,
                apr_int64_t line_no,
                svn_revnum_t revision,
                apr_hash_t *rev_props,
                svn_revnum_t merged_revision,
                apr_hash_t *merged_rev_props,
                const char *merged_path,
-               const char *line,
+               const svn_string_t *line,
                svn_boolean_t local_change,
                apr_pool_t *pool)
 {
@@ -188,19 +185,19 @@ blame_receiver(void *baton,
   svn_boolean_t use_merged = FALSE;
 
   if (!bb->rev_maxlength)
-    {
-      svn_revnum_t max_revnum = MAX(start_revnum, end_revnum);
-      /* The standard column width for the revision number is 6 characters.
-         If the revision number can potentially be larger (i.e. if the end_revnum
-          is larger than 1000000), we increase the column width as needed. */
-
-      bb->rev_maxlength = 6;
-      while (max_revnum >= 1000000)
-        {
-          bb->rev_maxlength++;
-          max_revnum = max_revnum / 10;
-        }
-    }
+  {
+    svn_revnum_t max_revnum = MAX(bb->start_revnum, bb->end_revnum);
+    /* The standard column width for the revision number is 6 characters.
+       If the revision number can potentially be larger (i.e. if the end_revnum
+        is larger than 1000000), we increase the column width as needed. */
+
+    bb->rev_maxlength = 6;
+    while (max_revnum >= 1000000)
+      {
+        bb->rev_maxlength++;
+        max_revnum = max_revnum / 10;
+      }
+  }
 
   if (opt_state->use_merge_history)
     {
@@ -237,7 +234,7 @@ blame_receiver(void *baton,
                             bb->rev_maxlength,
                             pool));
 
-  return svn_stream_printf(out, pool, "%s%s", line, APR_EOL_STR);
+  return svn_stream_printf(out, pool, "%s%s", line->data, APR_EOL_STR);
 }
 
 
@@ -333,7 +330,7 @@ svn_cl__blame(apr_getopt_t *os,
       const char *target = APR_ARRAY_IDX(targets, i, const char *);
       const char *truepath;
       svn_opt_revision_t peg_revision;
-      svn_client_blame_receiver3_t receiver;
+      svn_client_blame_receiver4_t receiver;
 
       svn_pool_clear(subpool);
       SVN_ERR(svn_cl__check_cancel(ctx->cancel_baton));
@@ -368,7 +365,8 @@ svn_cl__blame(apr_getopt_t *os,
       else
         receiver = blame_receiver;
 
-      err = svn_client_blame5(truepath,
+      err = svn_client_blame6(&bl.start_revnum, &bl.end_revnum,
+                              truepath,
                               &peg_revision,
                               &opt_state->start_revision,
                               &opt_state->end_revision,

Modified: subversion/branches/swig-py3/subversion/svn/cl.h
URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/subversion/svn/cl.h?rev=1862754&r1=1862753&r2=1862754&view=diff
==============================================================================
--- subversion/branches/swig-py3/subversion/svn/cl.h (original)
+++ subversion/branches/swig-py3/subversion/svn/cl.h Mon Jul  8 15:19:03 2019
@@ -261,6 +261,7 @@ typedef struct svn_cl__opt_state_t
   svn_boolean_t mergeinfo_log;     /* show log message in mergeinfo command */
   svn_boolean_t remove_unversioned;/* remove unversioned items */
   svn_boolean_t remove_ignored;    /* remove ignored items */
+  svn_boolean_t remove_added;      /* reverting added item also removes it */
   svn_boolean_t no_newline;        /* do not output the trailing newline */
   svn_boolean_t show_passwords;    /* show cached passwords */
   svn_boolean_t pin_externals;     /* pin externals to last-changed revisions */
@@ -329,6 +330,7 @@ svn_opt_subcommand_t
   svn_cl__shelf_save,
   svn_cl__shelf_shelve,
   svn_cl__shelf_unshelve,
+  svn_cl__wc_copy_mods,
   svn_cl__status,
   svn_cl__switch,
   svn_cl__unlock,

Modified: subversion/branches/swig-py3/subversion/svn/conflict-callbacks.c
URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/subversion/svn/conflict-callbacks.c?rev=1862754&r1=1862753&r2=1862754&view=diff
==============================================================================
--- subversion/branches/swig-py3/subversion/svn/conflict-callbacks.c (original)
+++ subversion/branches/swig-py3/subversion/svn/conflict-callbacks.c Mon Jul  8 15:19:03 2019
@@ -449,6 +449,8 @@ static const resolver_option_t builtin_r
   /* Options for incoming move vs local move. */
   { "m", svn_client_conflict_option_both_moved_file_merge },
   { "M", svn_client_conflict_option_both_moved_file_move_merge },
+  { "m", svn_client_conflict_option_both_moved_dir_merge },
+  { "M", svn_client_conflict_option_both_moved_dir_move_merge },
 
   { NULL }
 };

Modified: subversion/branches/swig-py3/subversion/svn/revert-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/subversion/svn/revert-cmd.c?rev=1862754&r1=1862753&r2=1862754&view=diff
==============================================================================
--- subversion/branches/swig-py3/subversion/svn/revert-cmd.c (original)
+++ subversion/branches/swig-py3/subversion/svn/revert-cmd.c Mon Jul  8 15:19:03 2019
@@ -71,7 +71,7 @@ svn_cl__revert(apr_getopt_t *os,
                            opt_state->changelists,
                            FALSE /* clear_changelists */,
                            FALSE /* metadata_only */,
-                           TRUE /*added_keep_local*/,
+                           !opt_state->remove_added /*added_keep_local*/,
                            ctx, scratch_pool);
   if (err
       && (err->apr_err == SVN_ERR_WC_INVALID_OPERATION_DEPTH)

Modified: subversion/branches/swig-py3/subversion/svn/shelf-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/subversion/svn/shelf-cmd.c?rev=1862754&r1=1862753&r2=1862754&view=diff
==============================================================================
--- subversion/branches/swig-py3/subversion/svn/shelf-cmd.c (original)
+++ subversion/branches/swig-py3/subversion/svn/shelf-cmd.c Mon Jul  8 15:19:03 2019
@@ -1207,3 +1207,27 @@ svn_cl__shelf_log(apr_getopt_t *os,
 
   return SVN_NO_ERROR;
 }
+
+/**************************************************************************/
+
+/* This implements the `svn_opt_subcommand_t' interface. */
+svn_error_t *
+svn_cl__wc_copy_mods(apr_getopt_t *os,
+                     void *baton,
+                     apr_pool_t *pool)
+{
+  svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx;
+  const char *src_wc_abspath, *dst_wc_abspath;
+
+  SVN_ERR(get_next_argument(&src_wc_abspath, os, pool, pool));
+  SVN_ERR(svn_dirent_get_absolute(&src_wc_abspath, src_wc_abspath, pool));
+
+  SVN_ERR(get_next_argument(&dst_wc_abspath, os, pool, pool));
+  SVN_ERR(svn_dirent_get_absolute(&dst_wc_abspath, dst_wc_abspath, pool));
+
+  SVN_ERR(svn_client__wc_copy_mods(src_wc_abspath, dst_wc_abspath,
+                                   ctx->notify_func2, ctx->notify_baton2,
+                                   ctx, pool));
+
+  return SVN_NO_ERROR;
+}

Modified: subversion/branches/swig-py3/subversion/svn/svn.c
URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/subversion/svn/svn.c?rev=1862754&r1=1862753&r2=1862754&view=diff
==============================================================================
--- subversion/branches/swig-py3/subversion/svn/svn.c (original)
+++ subversion/branches/swig-py3/subversion/svn/svn.c Mon Jul  8 15:19:03 2019
@@ -140,6 +140,7 @@ typedef enum svn_cl__longopt_t {
   opt_mergeinfo_log,
   opt_remove_unversioned,
   opt_remove_ignored,
+  opt_remove_added,
   opt_no_newline,
   opt_show_passwords,
   opt_pin_externals,
@@ -421,6 +422,8 @@ const apr_getopt_option_t svn_cl__option
   {"remove-unversioned", opt_remove_unversioned, 0,
                        N_("remove unversioned items")},
   {"remove-ignored", opt_remove_ignored, 0, N_("remove ignored items")},
+  {"remove-added", opt_remove_added, 0,
+                       N_("reverting an added item will remove it from disk")},
   {"no-newline", opt_no_newline, 0, N_("do not output the trailing newline")},
   {"show-passwords", opt_show_passwords, 0, N_("show cached passwords")},
   {"pin-externals", opt_pin_externals, 0,
@@ -1765,7 +1768,8 @@ const svn_opt_subcommand_desc3_t svn_cl_
      "  For information about undoing already committed changes, search\n"
      "  the output of 'svn help merge' for 'undo'.\n"
     )},
-    {opt_targets, 'R', opt_depth, 'q', opt_changelist} },
+    {opt_targets, 'R', opt_depth, 'q', opt_changelist,
+     opt_remove_added} },
 
   { "status", svn_cl__status, {"stat", "st"}, {N_(
      "Print the status of working copy files and directories.\n"
@@ -2134,6 +2138,18 @@ const svn_opt_subcommand_desc3_t svn_cl_
     )},
     {opt_drop, 'q', opt_dry_run, opt_force} },
 
+  { "x-wc-copy-mods", svn_cl__wc_copy_mods, {0}, {N_(
+     "Copy local modifications from one WC to another.\n"
+     "usage: x-wc-copy-mods SRC_WC_PATH DST_WC_PATH\n"
+     "\n"), N_(
+     "  The source and destination WC paths may be in the same WC or in different"
+     "  WCs.\n"
+     "\n"), N_(
+     "  This feature is EXPERIMENTAL. This command is likely to change\n"
+     "  in the next release, and there is no promise of backward compatibility.\n"
+    )},
+  },
+
   { NULL, NULL, {0}, {NULL}, {0} }
 };
 
@@ -2637,7 +2653,8 @@ sub_main(int *exit_code, int argc, const
         break;
       case opt_config_dir:
         SVN_ERR(svn_utf_cstring_to_utf8(&utf8_opt_arg, opt_arg, pool));
-        opt_state.config_dir = svn_dirent_internal_style(utf8_opt_arg, pool);
+        SVN_ERR(svn_dirent_internal_style_safe(&opt_state.config_dir, NULL,
+                                               utf8_opt_arg, pool, pool));
         break;
       case opt_config_options:
         if (!opt_state.config_options)
@@ -2806,6 +2823,9 @@ sub_main(int *exit_code, int argc, const
       case opt_remove_ignored:
         opt_state.remove_ignored = TRUE;
         break;
+      case opt_remove_added:
+        opt_state.remove_added = TRUE;
+        break;
       case opt_no_newline:
       case opt_strict:          /* ### DEPRECATED */
         opt_state.no_newline = TRUE;
@@ -3220,7 +3240,10 @@ sub_main(int *exit_code, int argc, const
         {
           svn_node_kind_t kind;
           const char *local_abspath;
-          const char *fname = svn_dirent_internal_style(dash_F_arg, pool);
+          const char *fname;
+
+          SVN_ERR(svn_dirent_internal_style_safe(&fname, NULL, dash_F_arg,
+                                                 pool, pool));
 
           err = svn_dirent_get_absolute(&local_abspath, fname, pool);
 

Modified: subversion/branches/swig-py3/subversion/svn/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/subversion/svn/util.c?rev=1862754&r1=1862753&r2=1862754&view=diff
==============================================================================
--- subversion/branches/swig-py3/subversion/svn/util.c (original)
+++ subversion/branches/swig-py3/subversion/svn/util.c Mon Jul  8 15:19:03 2019
@@ -163,6 +163,8 @@ svn_cl__merge_file_externally(const char
     arguments[5] = wc_path;
     arguments[6] = NULL;
 
+    /* Presumably apr_filepath_get() returns a valid path, so we don't have
+       to use the safe version of svn_dirent_internal_style() here. */
     SVN_ERR(svn_io_run_cmd(svn_dirent_internal_style(cwd, pool), merge_tool,
                            arguments, &exitcode, NULL, TRUE, NULL, NULL, NULL,
                            pool));

Modified: subversion/branches/swig-py3/subversion/svnadmin/svnadmin.c
URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/subversion/svnadmin/svnadmin.c?rev=1862754&r1=1862753&r2=1862754&view=diff
==============================================================================
--- subversion/branches/swig-py3/subversion/svnadmin/svnadmin.c (original)
+++ subversion/branches/swig-py3/subversion/svnadmin/svnadmin.c Mon Jul  8 15:19:03 2019
@@ -42,6 +42,7 @@
 #include "svn_time.h"
 #include "svn_user.h"
 #include "svn_xml.h"
+#include "svn_fs.h"
 
 #include "private/svn_cmdline_private.h"
 #include "private/svn_opt_private.h"
@@ -49,6 +50,7 @@
 #include "private/svn_subr_private.h"
 #include "private/svn_cmdline_private.h"
 #include "private/svn_fspath.h"
+#include "private/svn_fs_fs_private.h"
 
 #include "svn_private_config.h"
 
@@ -114,6 +116,7 @@ static svn_opt_subcommand_t
   subcommand_lstxns,
   subcommand_pack,
   subcommand_recover,
+  subcommand_rev_size,
   subcommand_rmlocks,
   subcommand_rmtxns,
   subcommand_setlog,
@@ -518,6 +521,17 @@ static const svn_opt_subcommand_desc3_t
    )},
    {svnadmin__wait} },
 
+  {"rev-size", subcommand_rev_size, {0}, {N_(
+    "usage: svnadmin rev-size REPOS_PATH -r REVISION\n"
+    "\n"), N_(
+    "Print the total size in bytes of the representation on disk of\n"
+    "revision REVISION.\n"
+    "\n"), N_(
+    "The size includes revision properties and excludes FSFS indexes.\n"
+   )},
+   {'r', 'q', 'M'},
+   { {'q', "print only the size and a newline"} } },
+
   {"rmlocks", subcommand_rmlocks, {0}, {N_(
     "usage: svnadmin rmlocks REPOS_PATH LOCKED_PATH...\n"
     "\n"), N_(
@@ -2847,6 +2861,68 @@ subcommand_delrevprop(apr_getopt_t *os,
 }
 
 
+/* Set *REV_SIZE to the total size in bytes of the representation on disk
+ * of revision REVISION in FS.
+ *
+ * This is implemented only for FSFS repositories, and otherwise returns
+ * an SVN_ERR_UNSUPPORTED_FEATURE error.
+ *
+ * The size includes revision properties and excludes FSFS indexes.
+ */
+static svn_error_t *
+revision_size(apr_off_t *rev_size,
+              svn_fs_t *fs,
+              svn_revnum_t revision,
+              apr_pool_t *scratch_pool)
+{
+  svn_error_t *err;
+  svn_fs_fs__ioctl_revision_size_input_t input = {0};
+  svn_fs_fs__ioctl_revision_size_output_t *output;
+
+  input.revision = revision;
+  err = svn_fs_ioctl(fs, SVN_FS_FS__IOCTL_REVISION_SIZE,
+                     &input, (void **)&output,
+                     check_cancel, NULL, scratch_pool, scratch_pool);
+  if (err && err->apr_err == SVN_ERR_FS_UNRECOGNIZED_IOCTL_CODE)
+    {
+      return svn_error_quick_wrapf(err,
+                                   _("Revision size query is not implemented "
+                                     "for the filesytem type found in '%s'"),
+                                   svn_fs_path(fs, scratch_pool));
+    }
+  SVN_ERR(err);
+
+  *rev_size = output->rev_size;
+  return SVN_NO_ERROR;
+}
+
+/* This implements `svn_opt_subcommand_t'. */
+svn_error_t *
+subcommand_rev_size(apr_getopt_t *os, void *baton, apr_pool_t *pool)
+{
+  struct svnadmin_opt_state *opt_state = baton;
+  svn_revnum_t revision;
+  apr_off_t rev_size;
+  svn_repos_t *repos;
+
+  if (opt_state->start_revision.kind != svn_opt_revision_number
+      || opt_state->end_revision.kind != svn_opt_revision_unspecified)
+    return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                            _("Invalid revision specifier"));
+  revision = opt_state->start_revision.value.number;
+
+  SVN_ERR(open_repos(&repos, opt_state->repository_path, opt_state, pool));
+  SVN_ERR(revision_size(&rev_size, svn_repos_fs(repos), revision, pool));
+
+  if (opt_state->quiet)
+    SVN_ERR(svn_cmdline_printf(pool, "%"APR_OFF_T_FMT"\n", rev_size));
+  else
+    SVN_ERR(svn_cmdline_printf(pool, _("%12"APR_OFF_T_FMT" bytes in revision %ld\n"),
+                               rev_size, revision));
+
+  return SVN_NO_ERROR;
+}
+
 
 /** Main. **/
 

Modified: subversion/branches/swig-py3/subversion/svndumpfilter/svndumpfilter.c
URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/subversion/svndumpfilter/svndumpfilter.c?rev=1862754&r1=1862753&r2=1862754&view=diff
==============================================================================
--- subversion/branches/swig-py3/subversion/svndumpfilter/svndumpfilter.c (original)
+++ subversion/branches/swig-py3/subversion/svndumpfilter/svndumpfilter.c Mon Jul  8 15:19:03 2019
@@ -43,6 +43,7 @@
 #include "svn_mergeinfo.h"
 #include "svn_version.h"
 
+#include "private/svn_dirent_uri_private.h"
 #include "private/svn_repos_private.h"
 #include "private/svn_mergeinfo_private.h"
 #include "private/svn_cmdline_private.h"
@@ -1467,7 +1468,7 @@ sub_main(int *exit_code, int argc, const
           /* Ensure that each prefix is UTF8-encoded, in internal
              style, and absolute. */
           SVN_ERR(svn_utf_cstring_to_utf8(&prefix, os->argv[i], pool));
-          prefix = svn_relpath__internal_style(prefix, pool);
+          SVN_ERR(svn_relpath__make_internal(&prefix, prefix, pool, pool));
           if (prefix[0] != '/')
             prefix = apr_pstrcat(pool, "/", prefix, SVN_VA_NULL);
           APR_ARRAY_PUSH(opt_state.prefixes, const char *) = prefix;

Modified: subversion/branches/swig-py3/subversion/svnfsfs/dump-index-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/subversion/svnfsfs/dump-index-cmd.c?rev=1862754&r1=1862753&r2=1862754&view=diff
==============================================================================
--- subversion/branches/swig-py3/subversion/svnfsfs/dump-index-cmd.c (original)
+++ subversion/branches/swig-py3/subversion/svnfsfs/dump-index-cmd.c Mon Jul  8 15:19:03 2019
@@ -79,6 +79,7 @@ dump_index(const char *path,
            apr_pool_t *pool)
 {
   svn_fs_t *fs;
+  svn_fs_fs__ioctl_dump_index_input_t input = {0};
 
   /* Check repository type and open it. */
   SVN_ERR(open_fs(&fs, path, pool));
@@ -87,8 +88,10 @@ dump_index(const char *path,
   printf("       Start       Length Type   Revision     Item Checksum\n");
 
   /* Dump the whole index contents */
-  SVN_ERR(svn_fs_fs__dump_index(fs, revision, dump_index_entry, NULL,
-                                check_cancel, NULL, pool));
+  input.revision = revision;
+  input.callback_func = dump_index_entry;
+  SVN_ERR(svn_fs_ioctl(fs, SVN_FS_FS__IOCTL_DUMP_INDEX, &input, NULL,
+                       check_cancel, NULL, pool, pool));
 
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/swig-py3/subversion/svnfsfs/load-index-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/subversion/svnfsfs/load-index-cmd.c?rev=1862754&r1=1862753&r2=1862754&view=diff
==============================================================================
--- subversion/branches/swig-py3/subversion/svnfsfs/load-index-cmd.c (original)
+++ subversion/branches/swig-py3/subversion/svnfsfs/load-index-cmd.c Mon Jul  8 15:19:03 2019
@@ -135,6 +135,7 @@ load_index(const char *path,
   svn_revnum_t revision = SVN_INVALID_REVNUM;
   apr_array_header_t *entries = apr_array_make(pool, 16, sizeof(void*));
   apr_pool_t *iterpool = svn_pool_create(pool);
+  svn_fs_fs__ioctl_load_index_input_t ioctl_input = {0};
 
   /* Check repository type and open it. */
   SVN_ERR(open_fs(&fs, path, pool));
@@ -173,7 +174,10 @@ load_index(const char *path,
     }
 
   /* Rewrite the indexes. */
-  SVN_ERR(svn_fs_fs__load_index(fs, revision, entries, iterpool));
+  ioctl_input.revision = revision;
+  ioctl_input.entries = entries;
+  SVN_ERR(svn_fs_ioctl(fs, SVN_FS_FS__IOCTL_LOAD_INDEX, &ioctl_input, NULL,
+                       NULL, NULL, pool, pool));
   svn_pool_destroy(iterpool);
 
   return SVN_NO_ERROR;

Modified: subversion/branches/swig-py3/subversion/svnfsfs/stats-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/subversion/svnfsfs/stats-cmd.c?rev=1862754&r1=1862753&r2=1862754&view=diff
==============================================================================
--- subversion/branches/swig-py3/subversion/svnfsfs/stats-cmd.c (original)
+++ subversion/branches/swig-py3/subversion/svnfsfs/stats-cmd.c Mon Jul  8 15:19:03 2019
@@ -500,15 +500,17 @@ svn_error_t *
 subcommand__stats(apr_getopt_t *os, void *baton, apr_pool_t *pool)
 {
   svnfsfs__opt_state *opt_state = baton;
-  svn_fs_fs__stats_t *stats;
   svn_fs_t *fs;
+  svn_fs_fs__ioctl_get_stats_input_t input = {0};
+  svn_fs_fs__ioctl_get_stats_output_t *output;
 
   printf("Reading revisions\n");
   SVN_ERR(open_fs(&fs, opt_state->repository_path, pool));
-  SVN_ERR(svn_fs_fs__get_stats(&stats, fs, print_progress, NULL,
-                               check_cancel, NULL, pool, pool));
 
-  print_stats(stats, pool);
+  input.progress_func = print_progress;
+  SVN_ERR(svn_fs_ioctl(fs, SVN_FS_FS__IOCTL_GET_STATS, &input, (void **)&output,
+                       check_cancel, NULL, pool, pool));
+  print_stats(output->stats, pool);
 
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/swig-py3/subversion/svnserve/logger.c
URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/subversion/svnserve/logger.c?rev=1862754&r1=1862753&r2=1862754&view=diff
==============================================================================
--- subversion/branches/swig-py3/subversion/svnserve/logger.c (original)
+++ subversion/branches/swig-py3/subversion/svnserve/logger.c Mon Jul  8 15:19:03 2019
@@ -88,19 +88,21 @@ logger__create(logger_t **logger,
   return SVN_NO_ERROR;
 }
 
-void
-logger__log_error(logger_t *logger,
-                  svn_error_t *err,
-                  repository_t *repository,
-                  client_info_t *client_info)
+static void
+log_message(logger_t *logger,
+            const svn_error_t *err,
+            const char *prefix,
+            repository_t *repository,
+            client_info_t *client_info)
 {
   if (logger && err)
     {
       const char *timestr, *continuation;
       const char *user, *repos, *remote_host;
-      char errbuf[256];
+
       /* 8192 from MAX_STRING_LEN in from httpd-2.2.4/include/httpd.h */
-      char errstr[8192];
+      const apr_size_t errstr_size = 8192;
+      char *errstr = apr_palloc(logger->pool, errstr_size);
 
       svn_error_clear(svn_mutex__lock(logger->mutex));
 
@@ -118,21 +120,22 @@ logger__log_error(logger_t *logger,
       continuation = "";
       while (err)
         {
+          char errbuf[256];
           const char *message = svn_err_best_message(err, errbuf, sizeof(errbuf));
           /* based on httpd-2.2.4/server/log.c:log_error_core */
-          apr_size_t len = apr_snprintf(errstr, sizeof(errstr),
+          apr_size_t len = apr_snprintf(errstr, errstr_size,
                                         "%" APR_PID_T_FMT
-                                        " %s %s %s %s ERR%s %s %ld %d ",
+                                        " %s %s %s %s %s%s %s %ld %d ",
                                         getpid(), timestr, remote_host, user,
-                                        repos, continuation,
+                                        repos, prefix, continuation,
                                         err->file ? err->file : "-", err->line,
                                         err->apr_err);
 
           len += escape_errorlog_item(errstr + len, message,
-                                      sizeof(errstr) - len);
+                                      errstr_size - len);
           /* Truncate for the terminator (as apr_snprintf does) */
-          if (len > sizeof(errstr) - sizeof(APR_EOL_STR)) {
-            len = sizeof(errstr) - sizeof(APR_EOL_STR);
+          if (len > errstr_size - sizeof(APR_EOL_STR)) {
+            len = errstr_size - sizeof(APR_EOL_STR);
           }
 
           memcpy(errstr + len, APR_EOL_STR, sizeof(APR_EOL_STR));
@@ -150,6 +153,24 @@ logger__log_error(logger_t *logger,
     }
 }
 
+void
+logger__log_error(logger_t *logger,
+                  const svn_error_t *err,
+                  repository_t *repository,
+                  client_info_t *client_info)
+{
+  log_message(logger, err, "ERR", repository, client_info);
+}
+
+void
+logger__log_warning(logger_t *logger,
+                    const svn_error_t *err,
+                    repository_t *repository,
+                    client_info_t *client_info)
+{
+  log_message(logger, err, "WARN", repository, client_info);
+}
+
 svn_error_t *
 logger__write(logger_t *logger,
               const char *errstr,

Modified: subversion/branches/swig-py3/subversion/svnserve/logger.h
URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/subversion/svnserve/logger.h?rev=1862754&r1=1862753&r2=1862754&view=diff
==============================================================================
--- subversion/branches/swig-py3/subversion/svnserve/logger.h (original)
+++ subversion/branches/swig-py3/subversion/svnserve/logger.h Mon Jul  8 15:19:03 2019
@@ -64,14 +64,21 @@ logger__write(logger_t *logger,
 /* Write a description of ERR with additional information from REPOSITORY
  * and CLIENT_INFO to the log file managed by LOGGER.  REPOSITORY as well
  * as CLIENT_INFO may be NULL.  If either ERR or LOGGER are NULL, this
- * becomes a no-op.
+ * becomes a no-op. Does not clear ERR.
  */
 void
 logger__log_error(logger_t *logger,
-                  svn_error_t *err,
+                  const svn_error_t *err,
                   repository_t *repository,
                   client_info_t *client_info);
 
+/* Like logger__log_error() but for warnings. */
+void
+logger__log_warning(logger_t *logger,
+                    const svn_error_t *err,
+                    repository_t *repository,
+                    client_info_t *client_info);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */

Modified: subversion/branches/swig-py3/subversion/svnserve/serve.c
URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/subversion/svnserve/serve.c?rev=1862754&r1=1862753&r2=1862754&view=diff
==============================================================================
--- subversion/branches/swig-py3/subversion/svnserve/serve.c (original)
+++ subversion/branches/swig-py3/subversion/svnserve/serve.c Mon Jul  8 15:19:03 2019
@@ -107,15 +107,22 @@ typedef struct authz_baton_t {
   svn_ra_svn_conn_t *conn;
 } authz_baton_t;
 
-/* svn_error_create() a new error, log_server_error() it, and
-   return it. */
+/* Log an error. */
 static void
-log_error(svn_error_t *err, server_baton_t *server)
+log_error(const svn_error_t *err, server_baton_t *server)
 {
   logger__log_error(server->logger, err, server->repository,
                     server->client_info);
 }
 
+/* Log a warning. */
+static void
+log_warning(const svn_error_t *err, server_baton_t *server)
+{
+  logger__log_warning(server->logger, err, server->repository,
+                      server->client_info);
+}
+
 /* svn_error_create() a new error, log_server_error() it, and
    return it. */
 static svn_error_t *
@@ -294,7 +301,10 @@ static svn_error_t *
 load_authz_config(repository_t *repository,
                   const char *repos_root,
                   svn_config_t *cfg,
-                  apr_pool_t *pool)
+                  svn_repos_authz_warning_func_t warning_func,
+                  void *warning_baton,
+                  apr_pool_t *result_pool,
+                  apr_pool_t *scratch_pool)
 {
   const char *authzdb_path;
   const char *groupsdb_path;
@@ -313,17 +323,18 @@ load_authz_config(repository_t *reposito
 
       /* Canonicalize and add the base onto the authzdb_path (if needed). */
       err = canonicalize_access_file(&authzdb_path, repository,
-                                     repos_root, pool);
+                                     repos_root, scratch_pool);
 
       /* Same for the groupsdb_path if it is present. */
       if (groupsdb_path && !err)
         err = canonicalize_access_file(&groupsdb_path, repository,
-                                       repos_root, pool);
+                                       repos_root, scratch_pool);
 
       if (!err)
-        err = svn_repos_authz_read3(&repository->authzdb, authzdb_path,
+        err = svn_repos_authz_read4(&repository->authzdb, authzdb_path,
                                     groupsdb_path, TRUE, repository->repos,
-                                    pool, pool);
+                                    warning_func, warning_baton,
+                                    result_pool, scratch_pool);
 
       if (err)
         return svn_error_create(SVN_ERR_AUTHZ_INVALID_CONFIG, err, NULL);
@@ -3505,8 +3516,21 @@ get_deleted_rev(svn_ra_svn_conn_t *conn,
                                svn_relpath_canonicalize(path, pool), pool);
   SVN_ERR(log_command(b, conn, pool, "get-deleted-rev"));
   SVN_ERR(trivial_auth_request(conn, pool, b));
-  SVN_ERR(svn_repos_deleted_rev(b->repository->fs, full_path, peg_revision,
-                                end_revision, &revision_deleted, pool));
+  SVN_CMD_ERR(svn_repos_deleted_rev(b->repository->fs, full_path, peg_revision,
+                                    end_revision, &revision_deleted, pool));
+
+  /* The protocol does not allow for a reply of SVN_INVALID_REVNUM directly.
+     Instead, return SVN_ERR_ENTRY_MISSING_REVISION. A new enough client
+     knows that this means the answer to the query is SVN_INVALID_REVNUM.
+     (An older client reports this as an error.) */
+  if (revision_deleted == SVN_INVALID_REVNUM)
+    SVN_CMD_ERR(svn_error_createf(SVN_ERR_ENTRY_MISSING_REVISION, NULL,
+                                  "svn protocol command 'get-deleted-rev': "
+                                  "path '%s' was not deleted in r%ld-%ld; "
+                                  "NOTE: newer clients handle this case "
+                                  "and do not report it as an error",
+                                  full_path, peg_revision, end_revision));
+
   SVN_ERR(svn_ra_svn__write_cmd_response(conn, pool, "r", revision_deleted));
   return SVN_NO_ERROR;
 }
@@ -3793,6 +3817,8 @@ find_repos(const char *url,
            repository_t *repository,
            svn_repos__config_pool_t *config_pool,
            apr_hash_t *fs_config,
+           svn_repos_authz_warning_func_t authz_warning_func,
+           void *authz_warning_baton,
            apr_pool_t *result_pool,
            apr_pool_t *scratch_pool)
 {
@@ -3870,7 +3896,8 @@ find_repos(const char *url,
 
   SVN_ERR(load_pwdb_config(repository, cfg, config_pool, result_pool));
   SVN_ERR(load_authz_config(repository, repository->repos_root, cfg,
-                            result_pool));
+                            authz_warning_func, authz_warning_baton,
+                            result_pool, scratch_pool));
 
   /* Should we use Cyrus SASL? */
   SVN_ERR(svn_config_get_bool(cfg, &sasl_requested,
@@ -4092,6 +4119,16 @@ get_client_info(svn_ra_svn_conn_t *conn,
   return client_info;
 }
 
+static void
+handle_authz_warning(void *baton,
+                     const svn_error_t *err,
+                     apr_pool_t *scratch_pool)
+{
+  server_baton_t *const server_baton = baton;
+  log_warning(err, server_baton);
+  SVN_UNUSED(scratch_pool);
+}
+
 /* Construct the server baton for CONN using PARAMS and return it in *BATON.
  * It's lifetime is the same as that of CONN.  SCRATCH_POOL
  */
@@ -4101,7 +4138,7 @@ construct_server_baton(server_baton_t **
                        serve_params_t *params,
                        apr_pool_t *scratch_pool)
 {
-  svn_error_t *err, *io_err;
+  svn_error_t *err;
   apr_uint64_t ver;
   const char *client_url, *ra_client_string, *client_string;
   svn_ra_svn__list_t *caplist;
@@ -4214,10 +4251,14 @@ construct_server_baton(server_baton_t **
       }
   }
 
+  /* (*b) has the logger, repository and client_info set, so it can
+     be used as the authz_warning_baton that eventyally gets passed
+     to log_warning(). */
   err = handle_config_error(find_repos(client_url, params->root, b->vhost,
                                        b->read_only, params->cfg,
                                        b->repository, params->config_pool,
                                        params->fs_config,
+                                       handle_authz_warning, b,
                                        conn_pool, scratch_pool),
                             b);
   if (!err)
@@ -4239,11 +4280,12 @@ construct_server_baton(server_baton_t **
     }
   if (err)
     {
-      log_error(err, b);
-      io_err = svn_ra_svn__write_cmd_failure(conn, scratch_pool, err);
-      svn_error_clear(err);
-      SVN_ERR(io_err);
-      return svn_ra_svn__flush(conn, scratch_pool);
+      /* Report these errors to the client before closing the connection. */
+      err = svn_error_compose_create(err,
+              svn_ra_svn__write_cmd_failure(conn, scratch_pool, err));
+      err = svn_error_compose_create(err,
+              svn_ra_svn__flush(conn, scratch_pool));
+      return err;
     }
 
   SVN_ERR(svn_fs_get_uuid(b->repository->fs, &b->repository->uuid,

Propchange: subversion/branches/swig-py3/subversion/tests/
------------------------------------------------------------------------------
--- svn:ignore (original)
+++ svn:ignore Mon Jul  8 15:19:03 2019
@@ -6,4 +6,3 @@ Release
 *.o
 *~
 .*~
-svnserveautocheck.pid

Propchange: subversion/branches/swig-py3/subversion/tests/cmdline/
------------------------------------------------------------------------------
--- svn:ignore (original)
+++ svn:ignore Mon Jul  8 15:19:03 2019
@@ -1,5 +1,6 @@
 svn-test-work
 httpd-*
+svnserve-*
 .gdb_history
 *.pyc
 *.o

Modified: subversion/branches/swig-py3/subversion/tests/cmdline/authz_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/subversion/tests/cmdline/authz_tests.py?rev=1862754&r1=1862753&r2=1862754&view=diff
==============================================================================
--- subversion/branches/swig-py3/subversion/tests/cmdline/authz_tests.py (original)
+++ subversion/branches/swig-py3/subversion/tests/cmdline/authz_tests.py Mon Jul  8 15:19:03 2019
@@ -1694,7 +1694,7 @@ def inverted_group_membership(sbox):
 
 @Skip(svntest.main.is_ra_type_file)
 def group_member_empty_string(sbox):
-  "group definition ignores with empty member"
+  "group definition ignores empty member"
 
   sbox.build(create_wc = False)
 
@@ -1710,6 +1710,27 @@ def group_member_empty_string(sbox):
                                      '--username', svntest.main.wc_author,
                                      sbox.repo_url)
 
+@Issue(4802)
+@Skip(svntest.main.is_ra_type_file)
+def empty_group(sbox):
+  "empty group is ignored"
+
+  sbox.build(create_wc = False)
+
+  write_restrictive_svnserve_conf(sbox.repo_dir)
+  write_authz_file(sbox,
+                   {"/" : ("$anonymous =\n"
+                           "@empty = rw\n"
+                           "@readonly = r\n")},
+                   {"groups": ("empty = \n"
+                               "readonly = %s\n" % svntest.main.wc_author)})
+
+  expected_output = svntest.verify.UnorderedOutput(['A/\n', 'iota\n'])
+  svntest.actions.run_and_verify_svn(expected_output, [],
+                                     'list',
+                                     '--username', svntest.main.wc_author,
+                                     sbox.repo_url)
+
 
 ########################################################################
 # Run the tests
@@ -1749,6 +1770,7 @@ test_list = [ None,
               remove_access_after_commit,
               inverted_group_membership,
               group_member_empty_string,
+              empty_group,
              ]
 serial_only = True
 

Modified: subversion/branches/swig-py3/subversion/tests/cmdline/commit_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/subversion/tests/cmdline/commit_tests.py?rev=1862754&r1=1862753&r2=1862754&view=diff
==============================================================================
--- subversion/branches/swig-py3/subversion/tests/cmdline/commit_tests.py (original)
+++ subversion/branches/swig-py3/subversion/tests/cmdline/commit_tests.py Mon Jul  8 15:19:03 2019
@@ -3146,6 +3146,40 @@ def commit_issue4722_checksum(sbox):
       fp.write('abcdefghijklmnopqrstuvwxyz')
   sbox.simple_commit()
 
+@XFail()
+def commit_sees_tree_conflict_on_unversioned_path(sbox):
+  "commit sees tree conflict on unversioned path"
+
+  sbox.build(empty=True)
+  was_cwd = os.getcwd()
+  os.chdir(sbox.wc_dir)
+  sbox.wc_dir = '.'
+
+  # create a tree conflict victim at an unversioned path
+  sbox.simple_mkdir('topdir')
+  sbox.simple_commit()
+  sbox.simple_mkdir('topdir/subdir')
+  sbox.simple_commit()
+  sbox.simple_update()
+  sbox.simple_rm('topdir')
+  sbox.simple_commit()
+  sbox.simple_update()
+  svntest.actions.run_and_verify_svn(
+    None, [],
+    'merge', '-c2', sbox.wc_dir, '--ignore-ancestry', '--accept', 'postpone')
+  # check that we did create a conflict
+  svntest.actions.run_and_verify_svn(
+    None, 'svn: E155015:.*existing.*conflict.*',
+    'merge', '-c1', sbox.wc_dir, '--ignore-ancestry', '--accept', 'postpone')
+
+  # attempt to commit; should fail
+  expected_err = "svn: E155015: .* '.*topdir' remains in conflict"
+  svntest.actions.run_and_verify_commit(sbox.wc_dir, None, None,
+                                        expected_err,
+                                        sbox.wc_dir)
+
+  os.chdir(was_cwd)
+
 
 ########################################################################
 # Run the tests
@@ -3225,6 +3259,7 @@ test_list = [ None,
               mkdir_conflict_proper_error,
               commit_xml,
               commit_issue4722_checksum,
+              commit_sees_tree_conflict_on_unversioned_path,
              ]
 
 if __name__ == '__main__':

Modified: subversion/branches/swig-py3/subversion/tests/cmdline/dav_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/subversion/tests/cmdline/dav_tests.py?rev=1862754&r1=1862753&r2=1862754&view=diff
==============================================================================
--- subversion/branches/swig-py3/subversion/tests/cmdline/dav_tests.py (original)
+++ subversion/branches/swig-py3/subversion/tests/cmdline/dav_tests.py Mon Jul  8 15:19:03 2019
@@ -69,12 +69,14 @@ def connect_other_dav_server(sbox):
 
 #----------------------------------------------------------------------
 
-@XFail()
 @SkipUnless(svntest.main.is_remote_http_connection_allowed)
 def connect_to_github_server(sbox):
   "connect to GitHub's SVN bridge"
 
-  github_mirror_url = 'https://github.com/apache/subversion/trunk'
+  #github_mirror_url = 'https://github.com/apache/subversion/trunk'
+  # FIXME: Subversion's mirror on GitHub seems to randomly return gateway
+  #        errors (status 504), so use this more stable one instead.
+  github_mirror_url = 'https://github.com/apache/serf/trunk'
 
   # Skip this test if we can't connect to the GitHub server.
   # We check this here instead of in a SkipUnless() predicate decorator,

Modified: subversion/branches/swig-py3/subversion/tests/cmdline/getopt_tests_data/svn--help_stdout
URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/subversion/tests/cmdline/getopt_tests_data/svn--help_stdout?rev=1862754&r1=1862753&r2=1862754&view=diff
==============================================================================
--- subversion/branches/swig-py3/subversion/tests/cmdline/getopt_tests_data/svn--help_stdout (original)
+++ subversion/branches/swig-py3/subversion/tests/cmdline/getopt_tests_data/svn--help_stdout Mon Jul  8 15:19:03 2019
@@ -55,6 +55,7 @@ Available subcommands:
    x-shelf-save
    x-shelve
    x-unshelve
+   x-wc-copy-mods
 
 Subversion is a tool for version control.
 For additional information, see http://subversion.apache.org/

Modified: subversion/branches/swig-py3/subversion/tests/cmdline/getopt_tests_data/svn_help_stdout
URL: http://svn.apache.org/viewvc/subversion/branches/swig-py3/subversion/tests/cmdline/getopt_tests_data/svn_help_stdout?rev=1862754&r1=1862753&r2=1862754&view=diff
==============================================================================
--- subversion/branches/swig-py3/subversion/tests/cmdline/getopt_tests_data/svn_help_stdout (original)
+++ subversion/branches/swig-py3/subversion/tests/cmdline/getopt_tests_data/svn_help_stdout Mon Jul  8 15:19:03 2019
@@ -55,6 +55,7 @@ Available subcommands:
    x-shelf-save
    x-shelve
    x-unshelve
+   x-wc-copy-mods
 
 Subversion is a tool for version control.
 For additional information, see http://subversion.apache.org/