]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/subversion/subversion/libsvn_client/merge_elements.c
Update svn-1.9.7 to 1.10.0.
[FreeBSD/FreeBSD.git] / contrib / subversion / subversion / libsvn_client / merge_elements.c
1 /*
2  * merge_elements.c: element-based merging
3  *
4  * ====================================================================
5  *    Licensed to the Apache Software Foundation (ASF) under one
6  *    or more contributor license agreements.  See the NOTICE file
7  *    distributed with this work for additional information
8  *    regarding copyright ownership.  The ASF licenses this file
9  *    to you under the Apache License, Version 2.0 (the
10  *    "License"); you may not use this file except in compliance
11  *    with the License.  You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  *    Unless required by applicable law or agreed to in writing,
16  *    software distributed under the License is distributed on an
17  *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18  *    KIND, either express or implied.  See the License for the
19  *    specific language governing permissions and limitations
20  *    under the License.
21  * ====================================================================
22  */
23
24 #include <assert.h>
25 #include <apr_strings.h>
26 #include <apr_tables.h>
27 #include <apr_hash.h>
28 #include "svn_types.h"
29 #include "svn_error.h"
30 #include "svn_pools.h"
31 #include "svn_hash.h"
32 #include "svn_wc.h"
33 #include "svn_client.h"
34 #include "svn_dirent_uri.h"
35
36 #include "client.h"
37 #include "private/svn_element.h"
38
39 #include "svn_private_config.h"
40
41
42 /* Print a notification.
43  * ### TODO: Send notifications through ctx->notify_func2().
44  * ### TODO: Only when 'verbose' output is requested.
45  */
46 static
47 __attribute__((format(printf, 1, 2)))
48 void
49 verbose_notify(const char *fmt,
50                ...)
51 {
52   va_list ap;
53
54   va_start(ap, fmt);
55   vprintf(fmt, ap);
56   if (fmt[strlen(fmt) - 1] != '\n')
57     printf("\n");
58   va_end(ap);
59 }
60
61 /* Return a string representation of PATHREV. */
62 static const char *
63 pathrev_str(const svn_client__pathrev_t *pathrev,
64             apr_pool_t *pool)
65 {
66   const char *rrpath
67     = svn_uri_skip_ancestor(pathrev->repos_root_url, pathrev->url, pool);
68
69   return apr_psprintf(pool, "^/%s@%ld", rrpath, pathrev->rev);
70 }
71
72 /* Element matching info.
73  */
74 typedef struct element_matching_info_t
75 {
76   void *info;
77 } element_matching_info_t;
78
79 /* Return a string representation of INFO. */
80 static const char *
81 element_matching_info_str(const element_matching_info_t *info,
82                           apr_pool_t *result_pool)
83 {
84   /* ### */
85   const char *str = "{...}";
86
87   return str;
88 }
89
90 /* Assign EIDs (in memory) to the source-left, source-right and target
91  * trees.
92  */
93 static svn_error_t *
94 assign_eids_to_trees(svn_element__tree_t **tree_left_p,
95                      svn_element__tree_t **tree_right_p,
96                      svn_element__tree_t **tree_target_p,
97                      const svn_client__pathrev_t *src_left,
98                      const svn_client__pathrev_t *src_right,
99                      merge_target_t *target,
100                      svn_ra_session_t *ra_session,
101                      element_matching_info_t *element_matching_info,
102                      svn_client_ctx_t *ctx,
103                      apr_pool_t *result_pool,
104                      apr_pool_t *scratch_pool)
105 {
106   verbose_notify("--- Assigning EIDs to trees");
107
108   /* ### */
109   return SVN_NO_ERROR;
110 }
111
112 /* Perform a three-way tree merge. Write the result to *MERGE_RESULT_P.
113  *
114  * Set *CONFLICTS_P to describe any conflicts, or set *CONFLICTS_P to
115  * null if there are none.
116  */
117 static svn_error_t *
118 merge_trees(svn_element__tree_t **merge_result_p,
119             void **conflicts_p,
120             svn_element__tree_t *tree_left,
121             svn_element__tree_t *tree_right,
122             svn_element__tree_t *tree_target,
123             apr_pool_t *result_pool,
124             apr_pool_t *scratch_pool)
125 {
126   verbose_notify("--- Merging trees");
127
128   /* ### */
129   *merge_result_p = NULL;
130   *conflicts_p = NULL;
131   return SVN_NO_ERROR;
132 }
133
134 /* Convert the MERGE_RESULT to a series of WC edits and apply those to
135  * the WC described in TARGET.
136  */
137 static svn_error_t *
138 apply_merge_result_to_wc(merge_target_t *target,
139                          svn_element__tree_t *merge_result,
140                          svn_client_ctx_t *ctx,
141                          apr_pool_t *scratch_pool)
142 {
143   verbose_notify("--- Writing merge result to WC");
144
145   return SVN_NO_ERROR;
146 }
147
148 /* Do a three-way element-based merge for one merge source range,
149  * SRC_LEFT:SRC_RIGHT. If there are no conflicts, write the result to the
150  * WC described in TARGET.
151  */
152 static svn_error_t *
153 merge_elements_one_source(svn_boolean_t *use_sleep,
154                           const svn_client__pathrev_t *src_left,
155                           const svn_client__pathrev_t *src_right,
156                           merge_target_t *target,
157                           svn_ra_session_t *ra_session,
158                           element_matching_info_t *element_matching_info,
159                           svn_boolean_t diff_ignore_ancestry,
160                           svn_boolean_t force_delete,
161                           svn_boolean_t dry_run,
162                           const apr_array_header_t *merge_options,
163                           svn_client_ctx_t *ctx,
164                           apr_pool_t *scratch_pool)
165 {
166   svn_element__tree_t *tree_left, *tree_right, *tree_target;
167   svn_element__tree_t *merge_result;
168   void *conflicts;
169
170   verbose_notify("--- Merging by elements: "
171                  "left=%s, right=%s, matching=%s",
172                  pathrev_str(src_left, scratch_pool),
173                  pathrev_str(src_right, scratch_pool),
174                  element_matching_info_str(element_matching_info,
175                                            scratch_pool));
176
177   /* assign EIDs (in memory) to the source-left, source-right and target
178      trees */
179   SVN_ERR(assign_eids_to_trees(&tree_left, &tree_right, &tree_target,
180                                src_left, src_right, target, ra_session,
181                                element_matching_info,
182                                ctx, scratch_pool, scratch_pool));
183
184   /* perform a tree merge, creating a temporary result (in memory) */
185   SVN_ERR(merge_trees(&merge_result, &conflicts,
186                       tree_left, tree_right, tree_target,
187                       scratch_pool, scratch_pool));
188
189   /* check for (new style) conflicts in the result; if any, bail out */
190   if (conflicts)
191     {
192       return svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
193                               _("Merge had conflicts; "
194                                 "this is not yet supported"));
195     }
196
197   /* convert the result to a series of WC edits and apply those to the WC */
198   if (dry_run)
199     {
200       verbose_notify("--- Dry run; not writing merge result to WC");
201     }
202   else
203     {
204       SVN_ERR(apply_merge_result_to_wc(target, merge_result,
205                                        ctx, scratch_pool));
206       *use_sleep = TRUE;
207     }
208
209   /* forget all the EID metadata */
210   return SVN_NO_ERROR;
211 }
212
213 svn_error_t *
214 svn_client__merge_elements(svn_boolean_t *use_sleep,
215                            apr_array_header_t *merge_sources,
216                            merge_target_t *target,
217                            svn_ra_session_t *ra_session,
218                            svn_boolean_t diff_ignore_ancestry,
219                            svn_boolean_t force_delete,
220                            svn_boolean_t dry_run,
221                            const apr_array_header_t *merge_options,
222                            svn_client_ctx_t *ctx,
223                            apr_pool_t *result_pool,
224                            apr_pool_t *scratch_pool)
225 {
226   int i;
227
228   /* Merge each source range in turn */
229   for (i = 0; i < merge_sources->nelts; i++)
230     {
231       merge_source_t *source
232         = APR_ARRAY_IDX(merge_sources, i, void *);
233       element_matching_info_t *element_matching_info;
234
235       /* ### TODO: get element matching info from the user */
236       element_matching_info = NULL;
237
238       SVN_ERR(merge_elements_one_source(use_sleep,
239                                         source->loc1, source->loc2,
240                                         target, ra_session,
241                                         element_matching_info,
242                                         diff_ignore_ancestry,
243                                         force_delete, dry_run, merge_options,
244                                         ctx, scratch_pool));
245     }
246
247   return SVN_NO_ERROR;
248 }