summaryrefslogtreecommitdiff
path: root/subversion/svn/proplist-cmd.c
diff options
context:
space:
mode:
Diffstat (limited to 'subversion/svn/proplist-cmd.c')
-rw-r--r--subversion/svn/proplist-cmd.c336
1 files changed, 336 insertions, 0 deletions
diff --git a/subversion/svn/proplist-cmd.c b/subversion/svn/proplist-cmd.c
new file mode 100644
index 0000000000000..fe23a67f61430
--- /dev/null
+++ b/subversion/svn/proplist-cmd.c
@@ -0,0 +1,336 @@
+/*
+ * proplist-cmd.c -- List properties of files/dirs
+ *
+ * ====================================================================
+ * 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.
+ * ====================================================================
+ */
+
+/* ==================================================================== */
+
+
+
+/*** Includes. ***/
+
+#include "svn_cmdline.h"
+#include "svn_pools.h"
+#include "svn_client.h"
+#include "svn_error_codes.h"
+#include "svn_error.h"
+#include "svn_dirent_uri.h"
+#include "svn_path.h"
+#include "svn_xml.h"
+#include "svn_props.h"
+#include "cl.h"
+
+#include "private/svn_cmdline_private.h"
+
+#include "svn_private_config.h"
+
+typedef struct proplist_baton_t
+{
+ svn_cl__opt_state_t *opt_state;
+ svn_boolean_t is_url;
+} proplist_baton_t;
+
+
+/*** Code. ***/
+
+/* This implements the svn_proplist_receiver2_t interface, printing XML to
+ stdout. */
+static svn_error_t *
+proplist_receiver_xml(void *baton,
+ const char *path,
+ apr_hash_t *prop_hash,
+ apr_array_header_t *inherited_props,
+ apr_pool_t *pool)
+{
+ svn_cl__opt_state_t *opt_state = ((proplist_baton_t *)baton)->opt_state;
+ svn_boolean_t is_url = ((proplist_baton_t *)baton)->is_url;
+ svn_stringbuf_t *sb;
+ const char *name_local;
+
+ if (inherited_props && inherited_props->nelts)
+ {
+ int i;
+ apr_pool_t *iterpool = svn_pool_create(pool);
+
+ for (i = 0; i < inherited_props->nelts; i++)
+ {
+ svn_prop_inherited_item_t *iprop =
+ APR_ARRAY_IDX(inherited_props, i, svn_prop_inherited_item_t *);
+
+ sb = NULL;
+
+ if (svn_path_is_url(iprop->path_or_url))
+ name_local = iprop->path_or_url;
+ else
+ name_local = svn_dirent_local_style(iprop->path_or_url, iterpool);
+
+ svn_xml_make_open_tag(&sb, iterpool, svn_xml_normal, "target",
+ "path", name_local, NULL);
+ SVN_ERR(svn_cmdline__print_xml_prop_hash(&sb, iprop->prop_hash,
+ (! opt_state->verbose),
+ TRUE, iterpool));
+ svn_xml_make_close_tag(&sb, iterpool, "target");
+ SVN_ERR(svn_cl__error_checked_fputs(sb->data, stdout));
+ }
+ svn_pool_destroy(iterpool);
+ }
+
+ if (! is_url)
+ name_local = svn_dirent_local_style(path, pool);
+ else
+ name_local = path;
+
+ sb = NULL;
+
+
+ if (prop_hash)
+ {
+ /* "<target ...>" */
+ svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "target",
+ "path", name_local, NULL);
+
+ SVN_ERR(svn_cmdline__print_xml_prop_hash(&sb, prop_hash,
+ (! opt_state->verbose),
+ FALSE, pool));
+
+ /* "</target>" */
+ svn_xml_make_close_tag(&sb, pool, "target");
+ SVN_ERR(svn_cl__error_checked_fputs(sb->data, stdout));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+
+/* This implements the svn_proplist_receiver2_t interface. */
+static svn_error_t *
+proplist_receiver(void *baton,
+ const char *path,
+ apr_hash_t *prop_hash,
+ apr_array_header_t *inherited_props,
+ apr_pool_t *pool)
+{
+ svn_cl__opt_state_t *opt_state = ((proplist_baton_t *)baton)->opt_state;
+ svn_boolean_t is_url = ((proplist_baton_t *)baton)->is_url;
+ const char *name_local;
+
+ if (! is_url)
+ name_local = svn_dirent_local_style(path, pool);
+ else
+ name_local = path;
+
+ if (inherited_props)
+ {
+ int i;
+ apr_pool_t *iterpool = svn_pool_create(pool);
+
+ for (i = 0; i < inherited_props->nelts; i++)
+ {
+ svn_prop_inherited_item_t *iprop =
+ APR_ARRAY_IDX(inherited_props, i, svn_prop_inherited_item_t *);
+
+ svn_pool_clear(iterpool);
+
+ if (!opt_state->quiet)
+ {
+ if (svn_path_is_url(iprop->path_or_url))
+ SVN_ERR(svn_cmdline_printf(
+ iterpool, _("Inherited properties on '%s',\nfrom '%s':\n"),
+ name_local, iprop->path_or_url));
+ else
+ SVN_ERR(svn_cmdline_printf(
+ iterpool, _("Inherited properties on '%s',\nfrom '%s':\n"),
+ name_local, svn_dirent_local_style(iprop->path_or_url,
+ iterpool)));
+ }
+
+ SVN_ERR(svn_cmdline__print_prop_hash(NULL, iprop->prop_hash,
+ (! opt_state->verbose),
+ iterpool));
+ }
+ svn_pool_destroy(iterpool);
+ }
+
+ if (prop_hash && apr_hash_count(prop_hash))
+ {
+ if (!opt_state->quiet)
+ SVN_ERR(svn_cmdline_printf(pool, _("Properties on '%s':\n"),
+ name_local));
+ SVN_ERR(svn_cmdline__print_prop_hash(NULL, prop_hash,
+ (! opt_state->verbose), pool));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+
+/* This implements the `svn_opt_subcommand_t' interface. */
+svn_error_t *
+svn_cl__proplist(apr_getopt_t *os,
+ void *baton,
+ apr_pool_t *scratch_pool)
+{
+ svn_cl__opt_state_t *opt_state = ((svn_cl__cmd_baton_t *) baton)->opt_state;
+ svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx;
+ apr_array_header_t *targets;
+ apr_array_header_t *errors = apr_array_make(scratch_pool, 0,
+ sizeof(apr_status_t));
+
+ SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
+ opt_state->targets,
+ ctx, FALSE,
+ scratch_pool));
+
+ /* Add "." if user passed 0 file arguments */
+ svn_opt_push_implicit_dot_target(targets, scratch_pool);
+
+ if (opt_state->revprop) /* operate on revprops */
+ {
+ svn_revnum_t rev;
+ const char *URL;
+ apr_hash_t *proplist;
+
+ if (opt_state->show_inherited_props)
+ return svn_error_create(
+ SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ _("--show-inherited-props can't be used with --revprop"));
+
+ SVN_ERR(svn_cl__revprop_prepare(&opt_state->start_revision, targets,
+ &URL, ctx, scratch_pool));
+
+ /* Let libsvn_client do the real work. */
+ SVN_ERR(svn_client_revprop_list(&proplist,
+ URL, &(opt_state->start_revision),
+ &rev, ctx, scratch_pool));
+
+ if (opt_state->xml)
+ {
+ svn_stringbuf_t *sb = NULL;
+ char *revstr = apr_psprintf(scratch_pool, "%ld", rev);
+
+ SVN_ERR(svn_cl__xml_print_header("properties", scratch_pool));
+
+ svn_xml_make_open_tag(&sb, scratch_pool, svn_xml_normal,
+ "revprops",
+ "rev", revstr, NULL);
+ SVN_ERR(svn_cmdline__print_xml_prop_hash(&sb, proplist,
+ (! opt_state->verbose),
+ FALSE, scratch_pool));
+ svn_xml_make_close_tag(&sb, scratch_pool, "revprops");
+
+ SVN_ERR(svn_cl__error_checked_fputs(sb->data, stdout));
+ SVN_ERR(svn_cl__xml_print_footer("properties", scratch_pool));
+ }
+ else
+ {
+ SVN_ERR
+ (svn_cmdline_printf(scratch_pool,
+ _("Unversioned properties on revision %ld:\n"),
+ rev));
+
+ SVN_ERR(svn_cmdline__print_prop_hash(NULL, proplist,
+ (! opt_state->verbose),
+ scratch_pool));
+ }
+ }
+ else /* operate on normal, versioned properties (not revprops) */
+ {
+ int i;
+ apr_pool_t *iterpool;
+ svn_proplist_receiver2_t pl_receiver;
+
+ if (opt_state->xml)
+ {
+ SVN_ERR(svn_cl__xml_print_header("properties", scratch_pool));
+ pl_receiver = proplist_receiver_xml;
+ }
+ else
+ {
+ pl_receiver = proplist_receiver;
+ }
+
+ if (opt_state->depth == svn_depth_unknown)
+ opt_state->depth = svn_depth_empty;
+
+ iterpool = svn_pool_create(scratch_pool);
+ for (i = 0; i < targets->nelts; i++)
+ {
+ const char *target = APR_ARRAY_IDX(targets, i, const char *);
+ proplist_baton_t pl_baton;
+ const char *truepath;
+ svn_opt_revision_t peg_revision;
+
+ svn_pool_clear(iterpool);
+ SVN_ERR(svn_cl__check_cancel(ctx->cancel_baton));
+
+ pl_baton.is_url = svn_path_is_url(target);
+ pl_baton.opt_state = opt_state;
+
+ /* Check for a peg revision. */
+ SVN_ERR(svn_opt_parse_path(&peg_revision, &truepath, target,
+ iterpool));
+
+ SVN_ERR(svn_cl__try(
+ svn_client_proplist4(truepath, &peg_revision,
+ &(opt_state->start_revision),
+ opt_state->depth,
+ opt_state->changelists,
+ opt_state->show_inherited_props,
+ pl_receiver, &pl_baton,
+ ctx, iterpool),
+ errors, opt_state->quiet,
+ SVN_ERR_UNVERSIONED_RESOURCE,
+ SVN_ERR_ENTRY_NOT_FOUND,
+ SVN_NO_ERROR));
+ }
+ svn_pool_destroy(iterpool);
+
+ if (opt_state->xml)
+ SVN_ERR(svn_cl__xml_print_footer("properties", scratch_pool));
+
+ /* Error out *after* we closed the XML element */
+ if (errors->nelts > 0)
+ {
+ svn_error_t *err;
+
+ err = svn_error_create(SVN_ERR_ILLEGAL_TARGET, NULL, NULL);
+ for (i = 0; i < errors->nelts; i++)
+ {
+ apr_status_t status = APR_ARRAY_IDX(errors, i, apr_status_t);
+
+ if (status == SVN_ERR_ENTRY_NOT_FOUND)
+ err = svn_error_quick_wrap(err,
+ _("Could not display properties "
+ "of all targets because some "
+ "targets don't exist"));
+ else if (status == SVN_ERR_UNVERSIONED_RESOURCE)
+ err = svn_error_quick_wrap(err,
+ _("Could not display properties "
+ "of all targets because some "
+ "targets are not versioned"));
+ }
+
+ return svn_error_trace(err);
+ }
+ }
+
+ return SVN_NO_ERROR;
+}