2 * mergeinfo-cmd.c -- Query merge-relative info.
4 * ====================================================================
5 * Copyright (c) 2007 CollabNet. All rights reserved.
7 * This software is licensed as described in the file COPYING, which
8 * you should have received as part of this distribution. The terms
9 * are also available at http://subversion.tigris.org/license-1.html.
10 * If newer versions of this license are posted there, you may use a
11 * newer version instead, at your option.
13 * This software consists of voluntary contributions made by many
14 * individuals. For exact contribution history, see the revision
15 * history and logs, available at http://subversion.tigris.org/.
16 * ====================================================================
19 /* ==================================================================== */
25 #include "svn_pools.h"
26 #include "svn_client.h"
27 #include "svn_cmdline.h"
29 #include "svn_error.h"
30 #include "svn_error_codes.h"
31 #include "svn_types.h"
34 #include "svn_private_config.h"
40 print_merge_ranges(apr_array_header_t
*ranges
, apr_pool_t
*pool
)
43 for (i
= 0; i
< ranges
->nelts
; i
++)
45 svn_merge_range_t
*range
= APR_ARRAY_IDX(ranges
, i
, svn_merge_range_t
*);
46 svn_cmdline_printf(pool
, "r%ld:%ld%s", range
->start
, range
->end
,
47 (i
== (ranges
->nelts
- 1)) ? "" : ", ");
49 svn_cmdline_printf(pool
, "\n");
54 relative_path(const char *root_url
,
58 const char *relurl
= svn_path_is_child(root_url
, url
, pool
);
59 return relurl
? apr_pstrcat(pool
, "/",
60 svn_path_uri_decode(relurl
, pool
), NULL
)
66 show_mergeinfo_for_source(const char *merge_source
,
67 apr_array_header_t
*merge_ranges
,
69 svn_opt_revision_t
*peg_revision
,
71 svn_client_ctx_t
*ctx
,
74 apr_array_header_t
*available_ranges
;
77 svn_cmdline_printf(pool
, _(" Source path: %s\n"),
78 relative_path(root_url
, merge_source
, pool
));
79 svn_cmdline_printf(pool
, _(" Merged ranges: "));
80 print_merge_ranges(merge_ranges
, pool
);
82 /* Now fetch the available merges for this source. */
84 /* ### FIXME: There's no reason why this API should fail to
85 ### answer the question (when asked of a 1.5+ server),
86 ### short of something being quite wrong with the
87 ### question. Certainly, that the merge source URL can't
88 ### be found in HEAD shouldn't mean we can't get any
89 ### decent information about it out of the system. It
90 ### may just mean the system has to work harder to
91 ### provide that information.
93 svn_cmdline_printf(pool
, _(" Eligible ranges: "));
94 err
= svn_client_mergeinfo_get_available(&available_ranges
,
102 if ((err
->apr_err
== SVN_ERR_FS_NOT_FOUND
)
103 || (err
->apr_err
== SVN_ERR_RA_DAV_PATH_NOT_FOUND
))
105 svn_error_clear(err
);
106 svn_cmdline_printf(pool
, _("(source no longer available "
111 svn_cmdline_printf(pool
, "\n");
117 print_merge_ranges(available_ranges
, pool
);
122 /* This implements the `svn_opt_subcommand_t' interface. */
124 svn_cl__mergeinfo(apr_getopt_t
*os
,
128 svn_cl__opt_state_t
*opt_state
= ((svn_cl__cmd_baton_t
*) baton
)->opt_state
;
129 svn_client_ctx_t
*ctx
= ((svn_cl__cmd_baton_t
*) baton
)->ctx
;
130 apr_array_header_t
*targets
;
131 apr_pool_t
*subpool
= svn_pool_create(pool
);
134 SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets
, os
,
138 /* Add "." if user passed 0 arguments. */
139 svn_opt_push_implicit_dot_target(targets
, pool
);
141 for (i
= 0; i
< targets
->nelts
; i
++)
143 const char *target
= APR_ARRAY_IDX(targets
, i
, const char *);
144 const char *truepath
;
145 svn_opt_revision_t peg_revision
;
146 svn_mergeinfo_t mergeinfo
;
147 const char *root_url
;
148 apr_hash_index_t
*hi
;
150 svn_pool_clear(subpool
);
151 SVN_ERR(svn_cl__check_cancel(ctx
->cancel_baton
));
153 /* Parse the path into a path and peg revision. */
154 SVN_ERR(svn_opt_parse_path(&peg_revision
, &truepath
, target
, subpool
));
156 /* If no peg-rev was attached to a URL target, then assume HEAD. */
157 if ((peg_revision
.kind
== svn_opt_revision_unspecified
)
158 && svn_path_is_url(target
))
159 peg_revision
.kind
= svn_opt_revision_head
;
161 /* If no peg-rev was attached to a non-URL target, then assume BASE. */
162 if ((peg_revision
.kind
== svn_opt_revision_unspecified
)
163 && (! svn_path_is_url(target
)))
164 peg_revision
.kind
= svn_opt_revision_base
;
166 /* Get the already-merged information. */
167 SVN_ERR(svn_client_mergeinfo_get_merged(&mergeinfo
, truepath
,
168 &peg_revision
, ctx
, subpool
));
170 svn_cmdline_printf(pool
, _("Path: %s\n"),
171 svn_path_local_style(truepath
, pool
));
172 if (mergeinfo
== NULL
)
173 mergeinfo
= apr_hash_make(pool
);
175 SVN_ERR(svn_client_root_url_from_path(&root_url
, truepath
, ctx
, pool
));
177 if (opt_state
->from_source
)
179 apr_array_header_t
*merged_ranges
=
180 apr_hash_get(mergeinfo
, opt_state
->from_source
,
181 APR_HASH_KEY_STRING
);
183 merged_ranges
= apr_array_make(pool
, 1,
184 sizeof(svn_merge_range_t
*));
185 SVN_ERR(show_mergeinfo_for_source(opt_state
->from_source
,
186 merged_ranges
, truepath
,
187 &peg_revision
, root_url
,
190 else if (apr_hash_count(mergeinfo
) > 0)
192 apr_pool_t
*iterpool
= svn_pool_create(subpool
);
193 for (hi
= apr_hash_first(NULL
, mergeinfo
);
194 hi
; hi
= apr_hash_next(hi
))
199 svn_pool_clear(iterpool
);
200 apr_hash_this(hi
, &key
, NULL
, &val
);
201 SVN_ERR(show_mergeinfo_for_source(key
, val
, truepath
,
202 &peg_revision
, root_url
,
205 svn_pool_destroy(iterpool
);
207 svn_cmdline_printf(subpool
, "\n");
210 svn_pool_destroy(subpool
);