summaryrefslogtreecommitdiff
path: root/subversion/libsvn_fs_util
diff options
context:
space:
mode:
authorJames McCoy <jamessan@debian.org>2018-07-31 22:26:52 -0400
committerJames McCoy <jamessan@debian.org>2018-07-31 22:26:52 -0400
commite20a507113ff1126aeb4a97b806390ea377fe292 (patch)
tree0260b3a40387d7f994fbadaf22f1e9d3c080b09f /subversion/libsvn_fs_util
parentc64debffb81d2fa17e9a72af7199ccf88b3cc556 (diff)
New upstream version 1.10.2
Diffstat (limited to 'subversion/libsvn_fs_util')
-rw-r--r--subversion/libsvn_fs_util/fs-util.c349
-rw-r--r--subversion/libsvn_fs_util/libsvn_fs_util.pc.in12
2 files changed, 361 insertions, 0 deletions
diff --git a/subversion/libsvn_fs_util/fs-util.c b/subversion/libsvn_fs_util/fs-util.c
new file mode 100644
index 0000000..b9d1de0
--- /dev/null
+++ b/subversion/libsvn_fs_util/fs-util.c
@@ -0,0 +1,349 @@
+/* fs-util.c : internal utility functions used by both FSFS and BDB back
+ * ends.
+ *
+ * ====================================================================
+ * 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 <string.h>
+
+#include <apr_pools.h>
+#include <apr_strings.h>
+
+#include "svn_private_config.h"
+#include "svn_hash.h"
+#include "svn_fs.h"
+#include "svn_dirent_uri.h"
+#include "svn_path.h"
+#include "svn_version.h"
+
+#include "private/svn_fs_util.h"
+#include "private/svn_fspath.h"
+#include "private/svn_subr_private.h"
+#include "../libsvn_fs/fs-loader.h"
+
+
+const svn_version_t *
+svn_fs_util__version(void)
+{
+ SVN_VERSION_BODY;
+}
+
+
+/* Return TRUE, if PATH of PATH_LEN > 0 chars starts with a '/' and does
+ * not end with a '/' and does not contain duplicate '/'.
+ */
+static svn_boolean_t
+is_canonical_abspath(const char *path, size_t path_len)
+{
+ const char *end;
+
+ /* check for leading '/' */
+ if (path[0] != '/')
+ return FALSE;
+
+ /* check for trailing '/' */
+ if (path_len == 1)
+ return TRUE;
+ if (path[path_len - 1] == '/')
+ return FALSE;
+
+ /* check for "//" */
+ end = path + path_len - 1;
+ for (; path != end; ++path)
+ if ((path[0] == '/') && (path[1] == '/'))
+ return FALSE;
+
+ return TRUE;
+}
+
+svn_boolean_t
+svn_fs__is_canonical_abspath(const char *path)
+{
+ /* No PATH? No problem. */
+ if (! path)
+ return TRUE;
+
+ /* Empty PATH? That's just "/". */
+ if (! *path)
+ return FALSE;
+
+ /* detailed checks */
+ return is_canonical_abspath(path, strlen(path));
+}
+
+const char *
+svn_fs__canonicalize_abspath(const char *path, apr_pool_t *pool)
+{
+ char *newpath;
+ size_t path_len;
+ size_t path_i = 0, newpath_i = 0;
+ svn_boolean_t eating_slashes = FALSE;
+
+ /* No PATH? No problem. */
+ if (! path)
+ return NULL;
+
+ /* Empty PATH? That's just "/". */
+ if (! *path)
+ return "/";
+
+ /* Non-trivial cases. Maybe, the path already is canonical after all? */
+ path_len = strlen(path);
+ if (is_canonical_abspath(path, path_len))
+ return apr_pstrmemdup(pool, path, path_len);
+
+ /* Now, the fun begins. Alloc enough room to hold PATH with an
+ added leading '/'. */
+ newpath = apr_palloc(pool, path_len + 2);
+
+ /* No leading slash? Fix that. */
+ if (*path != '/')
+ {
+ newpath[newpath_i++] = '/';
+ }
+
+ for (path_i = 0; path_i < path_len; path_i++)
+ {
+ if (path[path_i] == '/')
+ {
+ /* The current character is a '/'. If we are eating up
+ extra '/' characters, skip this character. Else, note
+ that we are now eating slashes. */
+ if (eating_slashes)
+ continue;
+ eating_slashes = TRUE;
+ }
+ else
+ {
+ /* The current character is NOT a '/'. If we were eating
+ slashes, we need not do that any more. */
+ if (eating_slashes)
+ eating_slashes = FALSE;
+ }
+
+ /* Copy the current character into our new buffer. */
+ newpath[newpath_i++] = path[path_i];
+ }
+
+ /* Did we leave a '/' attached to the end of NEWPATH (other than in
+ the root directory case)? */
+ if ((newpath[newpath_i - 1] == '/') && (newpath_i > 1))
+ newpath[newpath_i - 1] = '\0';
+ else
+ newpath[newpath_i] = '\0';
+
+ return newpath;
+}
+
+svn_error_t *
+svn_fs__check_fs(svn_fs_t *fs,
+ svn_boolean_t expect_open)
+{
+ if ((expect_open && fs->fsap_data)
+ || ((! expect_open) && (! fs->fsap_data)))
+ return SVN_NO_ERROR;
+ if (expect_open)
+ return svn_error_create(SVN_ERR_FS_NOT_OPEN, 0,
+ _("Filesystem object has not been opened yet"));
+ else
+ return svn_error_create(SVN_ERR_FS_ALREADY_OPEN, 0,
+ _("Filesystem object already open"));
+}
+
+char *
+svn_fs__next_entry_name(const char **next_p,
+ const char *path,
+ apr_pool_t *pool)
+{
+ const char *end;
+
+ /* Find the end of the current component. */
+ end = strchr(path, '/');
+
+ if (! end)
+ {
+ /* The path contains only one component, with no trailing
+ slashes. */
+ *next_p = 0;
+ return apr_pstrdup(pool, path);
+ }
+ else
+ {
+ /* There's a slash after the first component. Skip over an arbitrary
+ number of slashes to find the next one. */
+ const char *next = end;
+ while (*next == '/')
+ next++;
+ *next_p = next;
+ return apr_pstrndup(pool, path, end - path);
+ }
+}
+
+svn_fs_path_change2_t *
+svn_fs__path_change_create_internal(const svn_fs_id_t *node_rev_id,
+ svn_fs_path_change_kind_t change_kind,
+ apr_pool_t *pool)
+{
+ svn_fs_path_change2_t *change;
+
+ change = apr_pcalloc(pool, sizeof(*change));
+ change->node_rev_id = node_rev_id;
+ change->change_kind = change_kind;
+ change->mergeinfo_mod = svn_tristate_unknown;
+ change->copyfrom_rev = SVN_INVALID_REVNUM;
+
+ return change;
+}
+
+svn_fs_path_change3_t *
+svn_fs__path_change_create_internal2(svn_fs_path_change_kind_t change_kind,
+ apr_pool_t *result_pool)
+{
+ svn_fs_path_change3_t *change;
+
+ change = apr_pcalloc(result_pool, sizeof(*change));
+ change->path.data = "";
+ change->change_kind = change_kind;
+ change->mergeinfo_mod = svn_tristate_unknown;
+ change->copyfrom_rev = SVN_INVALID_REVNUM;
+
+ return change;
+}
+
+svn_error_t *
+svn_fs__append_to_merged_froms(svn_mergeinfo_t *output,
+ svn_mergeinfo_t input,
+ const char *rel_path,
+ apr_pool_t *pool)
+{
+ apr_hash_index_t *hi;
+
+ *output = apr_hash_make(pool);
+ for (hi = apr_hash_first(pool, input); hi; hi = apr_hash_next(hi))
+ {
+ const char *path = apr_hash_this_key(hi);
+ svn_rangelist_t *rangelist = apr_hash_this_val(hi);
+
+ svn_hash_sets(*output,
+ svn_fspath__join(path, rel_path, pool),
+ svn_rangelist_dup(rangelist, pool));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+/* Set the version info in *VERSION to COMPAT_MAJOR and COMPAT_MINOR, if
+ the current value refers to a newer version than that.
+ */
+static void
+add_compatility(svn_version_t *version,
+ int compat_major,
+ int compat_minor)
+{
+ if ( version->major > compat_major
+ || (version->major == compat_major && version->minor > compat_minor))
+ {
+ version->major = compat_major;
+ version->minor = compat_minor;
+ }
+}
+
+svn_error_t *
+svn_fs__compatible_version(svn_version_t **compatible_version,
+ apr_hash_t *config,
+ apr_pool_t *pool)
+{
+ svn_version_t *version;
+ const char *compatible;
+
+ /* set compatible version according to generic option.
+ Make sure, we are always compatible to the current SVN version
+ (or older). */
+ compatible = svn_hash_gets(config, SVN_FS_CONFIG_COMPATIBLE_VERSION);
+ if (compatible)
+ {
+ SVN_ERR(svn_version__parse_version_string(&version,
+ compatible, pool));
+ add_compatility(version,
+ svn_subr_version()->major,
+ svn_subr_version()->minor);
+ }
+ else
+ {
+ version = apr_pmemdup(pool, svn_subr_version(), sizeof(*version));
+ }
+
+ /* specific options take precedence.
+ Let the lowest version compatibility requirement win */
+ if (svn_hash_gets(config, SVN_FS_CONFIG_PRE_1_4_COMPATIBLE))
+ add_compatility(version, 1, 3);
+ else if (svn_hash_gets(config, SVN_FS_CONFIG_PRE_1_5_COMPATIBLE))
+ add_compatility(version, 1, 4);
+ else if (svn_hash_gets(config, SVN_FS_CONFIG_PRE_1_6_COMPATIBLE))
+ add_compatility(version, 1, 5);
+ else if (svn_hash_gets(config, SVN_FS_CONFIG_PRE_1_8_COMPATIBLE))
+ add_compatility(version, 1, 7);
+
+ /* we ignored the patch level and tag so far.
+ * Give them a defined value. */
+ version->patch = 0;
+ version->tag = "";
+
+ /* done here */
+ *compatible_version = version;
+ return SVN_NO_ERROR;
+}
+
+svn_boolean_t
+svn_fs__prop_lists_equal(apr_hash_t *a,
+ apr_hash_t *b,
+ apr_pool_t *pool)
+{
+ apr_hash_index_t *hi;
+
+ /* Quick checks and special cases. */
+ if (a == b)
+ return TRUE;
+
+ if (a == NULL)
+ return apr_hash_count(b) == 0;
+ if (b == NULL)
+ return apr_hash_count(a) == 0;
+
+ if (apr_hash_count(a) != apr_hash_count(b))
+ return FALSE;
+
+ /* Compare prop by prop. */
+ for (hi = apr_hash_first(pool, a); hi; hi = apr_hash_next(hi))
+ {
+ const char *key;
+ apr_ssize_t klen;
+ svn_string_t *val_a, *val_b;
+
+ apr_hash_this(hi, (const void **)&key, &klen, (void **)&val_a);
+ val_b = apr_hash_get(b, key, klen);
+
+ if (!val_b || !svn_string_compare(val_a, val_b))
+ return FALSE;
+ }
+
+ /* No difference found. */
+ return TRUE;
+}
diff --git a/subversion/libsvn_fs_util/libsvn_fs_util.pc.in b/subversion/libsvn_fs_util/libsvn_fs_util.pc.in
new file mode 100644
index 0000000..05a9b4f
--- /dev/null
+++ b/subversion/libsvn_fs_util/libsvn_fs_util.pc.in
@@ -0,0 +1,12 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: libsvn_fs_util
+Description: Subversion Filesystem Utility Library
+Version: @PACKAGE_VERSION@
+Requires: apr-util-@SVN_APR_MAJOR_VERSION@ apr-@SVN_APR_MAJOR_VERSION@
+Requires.private: libsvn_subr
+Libs: -L${libdir} -lsvn_fs_util
+Cflags: -I${includedir}