In the command-line client, forbid
[svn.git] / subversion / svn / proplist-cmd.c
blob8cd4281e5e920100bed670dedce478cc6d7d3acf
1 /*
2 * proplist-cmd.c -- List properties of files/dirs
4 * ====================================================================
5 * Copyright (c) 2000-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 /* ==================================================================== */
23 /*** Includes. ***/
25 #include "svn_cmdline.h"
26 #include "svn_pools.h"
27 #include "svn_client.h"
28 #include "svn_error_codes.h"
29 #include "svn_error.h"
30 #include "svn_path.h"
31 #include "svn_xml.h"
32 #include "cl.h"
34 #include "svn_private_config.h"
36 typedef struct
38 svn_cl__opt_state_t *opt_state;
39 svn_boolean_t is_url;
40 } proplist_baton_t;
43 /*** Code. ***/
45 /* This implements the svn_proplist_receiver_t interface, printing XML to
46 stdout. */
47 static svn_error_t *
48 proplist_receiver_xml(void *baton,
49 const char *path,
50 apr_hash_t *prop_hash,
51 apr_pool_t *pool)
53 svn_cl__opt_state_t *opt_state = ((proplist_baton_t *)baton)->opt_state;
54 svn_boolean_t is_url = ((proplist_baton_t *)baton)->is_url;
55 svn_stringbuf_t *sb = NULL;
56 const char *name_local;
58 if (! is_url)
59 name_local = svn_path_local_style(path, pool);
60 else
61 name_local = path;
63 /* "<target ...>" */
64 svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "target",
65 "path", name_local, NULL);
67 SVN_ERR(svn_cl__print_xml_prop_hash(&sb, prop_hash, (! opt_state->verbose),
68 pool));
70 /* "</target>" */
71 svn_xml_make_close_tag(&sb, pool, "target");
73 SVN_ERR(svn_cl__error_checked_fputs(sb->data, stdout));
75 return SVN_NO_ERROR;
79 /* This implements the svn_proplist_receiver_t interface. */
80 static svn_error_t *
81 proplist_receiver(void *baton,
82 const char *path,
83 apr_hash_t *prop_hash,
84 apr_pool_t *pool)
86 svn_cl__opt_state_t *opt_state = ((proplist_baton_t *)baton)->opt_state;
87 svn_boolean_t is_url = ((proplist_baton_t *)baton)->is_url;
88 const char *name_local;
90 if (! is_url)
91 name_local = svn_path_local_style(path, pool);
92 else
93 name_local = path;
95 if (!opt_state->quiet)
96 SVN_ERR(svn_cmdline_printf(pool, _("Properties on '%s':\n"), name_local));
97 SVN_ERR(svn_cl__print_prop_hash(prop_hash, (! opt_state->verbose),
98 pool));
100 return SVN_NO_ERROR;
104 /* This implements the `svn_opt_subcommand_t' interface. */
105 svn_error_t *
106 svn_cl__proplist(apr_getopt_t *os,
107 void *baton,
108 apr_pool_t *pool)
110 svn_cl__opt_state_t *opt_state = ((svn_cl__cmd_baton_t *) baton)->opt_state;
111 svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx;
112 apr_array_header_t *targets;
113 apr_array_header_t *changelist_targets = NULL, *combined_targets = NULL;
114 int i;
116 /* Before allowing svn_opt_args_to_target_array2() to canonicalize
117 all the targets, we need to build a list of targets made of both
118 ones the user typed, as well as any specified by --changelist. */
119 if (opt_state->changelist)
121 SVN_ERR(svn_client_get_changelist(&changelist_targets,
122 opt_state->changelist,
124 ctx,
125 pool));
126 if (apr_is_empty_array(changelist_targets))
127 return svn_error_createf(SVN_ERR_UNKNOWN_CHANGELIST, NULL,
128 _("Unknown changelist '%s'"),
129 opt_state->changelist);
132 if (opt_state->targets && changelist_targets)
133 combined_targets = apr_array_append(pool, opt_state->targets,
134 changelist_targets);
135 else if (opt_state->targets)
136 combined_targets = opt_state->targets;
137 else if (changelist_targets)
138 combined_targets = changelist_targets;
140 SVN_ERR(svn_opt_args_to_target_array2(&targets, os,
141 combined_targets, pool));
143 /* Add "." if user passed 0 arguments */
144 svn_opt_push_implicit_dot_target(targets, pool);
146 if (opt_state->revprop) /* operate on revprops */
148 svn_revnum_t rev;
149 const char *URL;
150 apr_hash_t *proplist;
153 SVN_ERR(svn_cl__revprop_prepare(&opt_state->start_revision, targets,
154 &URL, pool));
156 /* Let libsvn_client do the real work. */
157 SVN_ERR(svn_client_revprop_list(&proplist,
158 URL, &(opt_state->start_revision),
159 &rev, ctx, pool));
161 if (opt_state->xml)
163 svn_stringbuf_t *sb = NULL;
164 char *revstr = apr_psprintf(pool, "%ld", rev);
166 SVN_ERR(svn_cl__xml_print_header("properties", pool));
168 svn_xml_make_open_tag(&sb, pool, svn_xml_normal,
169 "revprops",
170 "rev", revstr, NULL);
171 SVN_ERR(svn_cl__print_xml_prop_hash
172 (&sb, proplist, (! opt_state->verbose), pool));
173 svn_xml_make_close_tag(&sb, pool, "revprops");
175 SVN_ERR(svn_cl__error_checked_fputs(sb->data, stdout));
176 SVN_ERR(svn_cl__xml_print_footer("properties", pool));
178 else
180 SVN_ERR
181 (svn_cmdline_printf(pool,
182 _("Unversioned properties on revision %ld:\n"),
183 rev));
185 SVN_ERR(svn_cl__print_prop_hash
186 (proplist, (! opt_state->verbose), pool));
189 else /* operate on normal, versioned properties (not revprops) */
191 apr_pool_t *subpool = svn_pool_create(pool);
192 svn_proplist_receiver_t pl_receiver;
194 if (opt_state->xml)
196 SVN_ERR(svn_cl__xml_print_header("properties", pool));
197 pl_receiver = proplist_receiver_xml;
199 else
201 pl_receiver = proplist_receiver;
204 if (opt_state->depth == svn_depth_unknown)
205 opt_state->depth = svn_depth_empty;
207 for (i = 0; i < targets->nelts; i++)
209 const char *target = APR_ARRAY_IDX(targets, i, const char *);
210 proplist_baton_t pl_baton;
211 const char *truepath;
212 svn_opt_revision_t peg_revision;
214 svn_pool_clear(subpool);
215 SVN_ERR(svn_cl__check_cancel(ctx->cancel_baton));
217 pl_baton.is_url = svn_path_is_url(target);
218 pl_baton.opt_state = opt_state;
220 /* Check for a peg revision. */
221 SVN_ERR(svn_opt_parse_path(&peg_revision, &truepath, target,
222 subpool));
224 SVN_ERR(svn_cl__try
225 (svn_client_proplist3(truepath, &peg_revision,
226 &(opt_state->start_revision),
227 opt_state->depth,
228 pl_receiver,
229 &pl_baton,
230 ctx, subpool),
231 NULL, opt_state->quiet,
232 SVN_ERR_UNVERSIONED_RESOURCE,
233 SVN_ERR_ENTRY_NOT_FOUND,
234 SVN_NO_ERROR));
237 if (opt_state->xml)
238 SVN_ERR(svn_cl__xml_print_footer("properties", pool));
240 svn_pool_destroy(subpool);
243 return SVN_NO_ERROR;