/* This implements the svn_proplist_receiver_t interface. */ static svn_error_t * proplist_receiver(void *baton, const char *path, apr_hash_t *prop_hash, 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_path_local_style(path, pool); else name_local = path; if (!opt_state->quiet) SVN_ERR(svn_cmdline_printf(pool, _("Properties on '%s':\n"), name_local)); return svn_cl__print_prop_hash(prop_hash, (! opt_state->verbose), pool); }
/* Print the properties in PROPS to the stream OUT. PROPS is a hash mapping * (const char *) path to (svn_string_t) property value. * If IS_URL is true, all paths are URLs, else all paths are local paths. * PNAME_UTF8 is the property name of all the properties. * If PRINT_FILENAMES is true, print the item's path before each property. * If OMIT_NEWLINE is true, don't add a newline at the end of each property. * If LIKE_PROPLIST is true, print everything in a more verbose format * like "svn proplist -v" does. * */ static svn_error_t * print_properties(svn_stream_t *out, svn_boolean_t is_url, const char *pname_utf8, apr_hash_t *props, svn_boolean_t print_filenames, svn_boolean_t omit_newline, svn_boolean_t like_proplist, apr_pool_t *pool) { apr_array_header_t *sorted_props; int i; apr_pool_t *iterpool = svn_pool_create(pool); const char *path_prefix; SVN_ERR(svn_dirent_get_absolute(&path_prefix, "", pool)); sorted_props = svn_sort__hash(props, svn_sort_compare_items_as_paths, pool); for (i = 0; i < sorted_props->nelts; i++) { svn_sort__item_t item = APR_ARRAY_IDX(sorted_props, i, svn_sort__item_t); const char *filename = item.key; svn_string_t *propval = item.value; svn_pool_clear(iterpool); if (print_filenames) { const char *header; /* Print the file name. */ if (! is_url) filename = svn_cl__local_style_skip_ancestor(path_prefix, filename, iterpool); /* In verbose mode, print exactly same as "proplist" does; * otherwise, print a brief header. */ header = apr_psprintf(iterpool, like_proplist ? _("Properties on '%s':\n") : "%s - ", filename); SVN_ERR(svn_cmdline_cstring_from_utf8(&header, header, iterpool)); SVN_ERR(svn_subst_translate_cstring2(header, &header, APR_EOL_STR, /* 'native' eol */ FALSE, /* no repair */ NULL, /* no keywords */ FALSE, /* no expansion */ iterpool)); SVN_ERR(stream_write(out, header, strlen(header))); } if (like_proplist) { /* Print the property name and value just as "proplist -v" does */ apr_hash_t *hash = apr_hash_make(iterpool); apr_hash_set(hash, pname_utf8, APR_HASH_KEY_STRING, propval); SVN_ERR(svn_cl__print_prop_hash(out, hash, FALSE, iterpool)); } else { /* If this is a special Subversion property, it is stored as UTF8, so convert to the native format. */ if (svn_prop_needs_translation(pname_utf8)) SVN_ERR(svn_subst_detranslate_string(&propval, propval, TRUE, iterpool)); SVN_ERR(stream_write(out, propval->data, propval->len)); if (! omit_newline) SVN_ERR(stream_write(out, APR_EOL_STR, strlen(APR_EOL_STR))); } } svn_pool_destroy(iterpool); 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; 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; 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_cl__print_xml_prop_hash (&sb, proplist, (! opt_state->verbose), 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_cl__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_receiver_t pl_receiver; svn_boolean_t had_errors = FALSE; 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_boolean_t success; 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_proplist3(truepath, &peg_revision, &(opt_state->start_revision), opt_state->depth, opt_state->changelists, pl_receiver, &pl_baton, ctx, iterpool), &success, opt_state->quiet, SVN_ERR_UNVERSIONED_RESOURCE, SVN_ERR_ENTRY_NOT_FOUND, SVN_NO_ERROR)); if (!success) had_errors = TRUE; } 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 (had_errors) return svn_error_create(SVN_ERR_ILLEGAL_TARGET, NULL, _("Could not display info for all targets " "because some targets don't exist")); } return SVN_NO_ERROR; }