aboutsummaryrefslogtreecommitdiff
path: root/subversion/libsvn_client/merge_elements.c
diff options
context:
space:
mode:
Diffstat (limited to 'subversion/libsvn_client/merge_elements.c')
-rw-r--r--subversion/libsvn_client/merge_elements.c248
1 files changed, 248 insertions, 0 deletions
diff --git a/subversion/libsvn_client/merge_elements.c b/subversion/libsvn_client/merge_elements.c
new file mode 100644
index 000000000000..66c21b640593
--- /dev/null
+++ b/subversion/libsvn_client/merge_elements.c
@@ -0,0 +1,248 @@
+/*
+ * merge_elements.c: element-based merging
+ *
+ * ====================================================================
+ * 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 <assert.h>
+#include <apr_strings.h>
+#include <apr_tables.h>
+#include <apr_hash.h>
+#include "svn_types.h"
+#include "svn_error.h"
+#include "svn_pools.h"
+#include "svn_hash.h"
+#include "svn_wc.h"
+#include "svn_client.h"
+#include "svn_dirent_uri.h"
+
+#include "client.h"
+#include "private/svn_element.h"
+
+#include "svn_private_config.h"
+
+
+/* Print a notification.
+ * ### TODO: Send notifications through ctx->notify_func2().
+ * ### TODO: Only when 'verbose' output is requested.
+ */
+static
+__attribute__((format(printf, 1, 2)))
+void
+verbose_notify(const char *fmt,
+ ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ vprintf(fmt, ap);
+ if (fmt[strlen(fmt) - 1] != '\n')
+ printf("\n");
+ va_end(ap);
+}
+
+/* Return a string representation of PATHREV. */
+static const char *
+pathrev_str(const svn_client__pathrev_t *pathrev,
+ apr_pool_t *pool)
+{
+ const char *rrpath
+ = svn_uri_skip_ancestor(pathrev->repos_root_url, pathrev->url, pool);
+
+ return apr_psprintf(pool, "^/%s@%ld", rrpath, pathrev->rev);
+}
+
+/* Element matching info.
+ */
+typedef struct element_matching_info_t
+{
+ void *info;
+} element_matching_info_t;
+
+/* Return a string representation of INFO. */
+static const char *
+element_matching_info_str(const element_matching_info_t *info,
+ apr_pool_t *result_pool)
+{
+ /* ### */
+ const char *str = "{...}";
+
+ return str;
+}
+
+/* Assign EIDs (in memory) to the source-left, source-right and target
+ * trees.
+ */
+static svn_error_t *
+assign_eids_to_trees(svn_element__tree_t **tree_left_p,
+ svn_element__tree_t **tree_right_p,
+ svn_element__tree_t **tree_target_p,
+ const svn_client__pathrev_t *src_left,
+ const svn_client__pathrev_t *src_right,
+ merge_target_t *target,
+ svn_ra_session_t *ra_session,
+ element_matching_info_t *element_matching_info,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ verbose_notify("--- Assigning EIDs to trees");
+
+ /* ### */
+ return SVN_NO_ERROR;
+}
+
+/* Perform a three-way tree merge. Write the result to *MERGE_RESULT_P.
+ *
+ * Set *CONFLICTS_P to describe any conflicts, or set *CONFLICTS_P to
+ * null if there are none.
+ */
+static svn_error_t *
+merge_trees(svn_element__tree_t **merge_result_p,
+ void **conflicts_p,
+ svn_element__tree_t *tree_left,
+ svn_element__tree_t *tree_right,
+ svn_element__tree_t *tree_target,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ verbose_notify("--- Merging trees");
+
+ /* ### */
+ *merge_result_p = NULL;
+ *conflicts_p = NULL;
+ return SVN_NO_ERROR;
+}
+
+/* Convert the MERGE_RESULT to a series of WC edits and apply those to
+ * the WC described in TARGET.
+ */
+static svn_error_t *
+apply_merge_result_to_wc(merge_target_t *target,
+ svn_element__tree_t *merge_result,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *scratch_pool)
+{
+ verbose_notify("--- Writing merge result to WC");
+
+ return SVN_NO_ERROR;
+}
+
+/* Do a three-way element-based merge for one merge source range,
+ * SRC_LEFT:SRC_RIGHT. If there are no conflicts, write the result to the
+ * WC described in TARGET.
+ */
+static svn_error_t *
+merge_elements_one_source(svn_boolean_t *use_sleep,
+ const svn_client__pathrev_t *src_left,
+ const svn_client__pathrev_t *src_right,
+ merge_target_t *target,
+ svn_ra_session_t *ra_session,
+ element_matching_info_t *element_matching_info,
+ svn_boolean_t diff_ignore_ancestry,
+ svn_boolean_t force_delete,
+ svn_boolean_t dry_run,
+ const apr_array_header_t *merge_options,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *scratch_pool)
+{
+ svn_element__tree_t *tree_left, *tree_right, *tree_target;
+ svn_element__tree_t *merge_result;
+ void *conflicts;
+
+ verbose_notify("--- Merging by elements: "
+ "left=%s, right=%s, matching=%s",
+ pathrev_str(src_left, scratch_pool),
+ pathrev_str(src_right, scratch_pool),
+ element_matching_info_str(element_matching_info,
+ scratch_pool));
+
+ /* assign EIDs (in memory) to the source-left, source-right and target
+ trees */
+ SVN_ERR(assign_eids_to_trees(&tree_left, &tree_right, &tree_target,
+ src_left, src_right, target, ra_session,
+ element_matching_info,
+ ctx, scratch_pool, scratch_pool));
+
+ /* perform a tree merge, creating a temporary result (in memory) */
+ SVN_ERR(merge_trees(&merge_result, &conflicts,
+ tree_left, tree_right, tree_target,
+ scratch_pool, scratch_pool));
+
+ /* check for (new style) conflicts in the result; if any, bail out */
+ if (conflicts)
+ {
+ return svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
+ _("Merge had conflicts; "
+ "this is not yet supported"));
+ }
+
+ /* convert the result to a series of WC edits and apply those to the WC */
+ if (dry_run)
+ {
+ verbose_notify("--- Dry run; not writing merge result to WC");
+ }
+ else
+ {
+ SVN_ERR(apply_merge_result_to_wc(target, merge_result,
+ ctx, scratch_pool));
+ *use_sleep = TRUE;
+ }
+
+ /* forget all the EID metadata */
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_client__merge_elements(svn_boolean_t *use_sleep,
+ apr_array_header_t *merge_sources,
+ merge_target_t *target,
+ svn_ra_session_t *ra_session,
+ svn_boolean_t diff_ignore_ancestry,
+ svn_boolean_t force_delete,
+ svn_boolean_t dry_run,
+ const apr_array_header_t *merge_options,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ int i;
+
+ /* Merge each source range in turn */
+ for (i = 0; i < merge_sources->nelts; i++)
+ {
+ merge_source_t *source
+ = APR_ARRAY_IDX(merge_sources, i, void *);
+ element_matching_info_t *element_matching_info;
+
+ /* ### TODO: get element matching info from the user */
+ element_matching_info = NULL;
+
+ SVN_ERR(merge_elements_one_source(use_sleep,
+ source->loc1, source->loc2,
+ target, ra_session,
+ element_matching_info,
+ diff_ignore_ancestry,
+ force_delete, dry_run, merge_options,
+ ctx, scratch_pool));
+ }
+
+ return SVN_NO_ERROR;
+}