/* This implements the svn_proplist_receiver_t interface, printing XML to stdout. */ static svn_error_t * proplist_receiver_xml(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; svn_stringbuf_t *sb = NULL; const char *name_local; if (! is_url) name_local = svn_dirent_local_style(path, pool); else name_local = path; /* "<target ...>" */ svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "target", "path", name_local, NULL); SVN_ERR(svn_cl__print_xml_prop_hash(&sb, prop_hash, (! opt_state->verbose), pool)); /* "</target>" */ svn_xml_make_close_tag(&sb, pool, "target"); return svn_cl__error_checked_fputs(sb->data, stdout); }
/* This implements `svn_log_entry_receiver_t', printing the logs in XML. * * BATON is of type `struct log_receiver_baton'. * * Here is an example of the output; note that the "<log>" and * "</log>" tags are not emitted by this function: * * $ svn log --xml -r 1648:1649 * <log> * <logentry * revision="1648"> * <author>david</author> * <date>2002-04-06T16:34:51.428043Z</date> * <msg> * packages/rpm/subversion.spec : Now requires apache 2.0.36. * </msg> * </logentry> * <logentry * revision="1649"> * <author>cmpilato</author> * <date>2002-04-06T17:01:28.185136Z</date> * <msg>Fix error handling when the $EDITOR is needed but unavailable. Ah * ... now that's *much* nicer. * * * subversion/clients/cmdline/util.c * (svn_cl__edit_externally): Clean up the "no external editor" * error message. * (svn_cl__get_log_message): Wrap "no external editor" * errors with helpful hints about the -m and -F options. * * * subversion/libsvn_client/commit.c * (svn_client_commit): Actually capture and propogate "no external * editor" errors.</msg> * </logentry> * </log> * */ static svn_error_t * log_entry_receiver_xml(void *baton, svn_log_entry_t *log_entry, apr_pool_t *pool) { struct log_receiver_baton *lb = baton; /* Collate whole log message into sb before printing. */ svn_stringbuf_t *sb = svn_stringbuf_create("", pool); char *revstr; const char *author; const char *date; const char *message; if (lb->cancel_func) SVN_ERR(lb->cancel_func(lb->cancel_baton)); svn_compat_log_revprops_out(&author, &date, &message, log_entry->revprops); if (author) author = svn_xml_fuzzy_escape(author, pool); if (date) date = svn_xml_fuzzy_escape(date, pool); if (message) message = svn_xml_fuzzy_escape(message, pool); if (log_entry->revision == 0 && message == NULL) return SVN_NO_ERROR; if (! SVN_IS_VALID_REVNUM(log_entry->revision)) { svn_xml_make_close_tag(&sb, pool, "logentry"); SVN_ERR(svn_cl__error_checked_fputs(sb->data, stdout)); apr_array_pop(lb->merge_stack); return SVN_NO_ERROR; } revstr = apr_psprintf(pool, "%ld", log_entry->revision); /* <logentry revision="xxx"> */ svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "logentry", "revision", revstr, NULL); /* <author>xxx</author> */ svn_cl__xml_tagged_cdata(&sb, pool, "author", author); /* Print the full, uncut, date. This is machine output. */ /* According to the docs for svn_log_entry_receiver_t, either NULL or the empty string represents no date. Avoid outputting an empty date element. */ if (date && date[0] == '\0') date = NULL; /* <date>xxx</date> */ svn_cl__xml_tagged_cdata(&sb, pool, "date", date); if (log_entry->changed_paths) { apr_hash_index_t *hi; char *path; /* <paths> */ svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "paths", NULL); for (hi = apr_hash_first(pool, log_entry->changed_paths); hi != NULL; hi = apr_hash_next(hi)) { void *val; char action[2]; svn_log_changed_path_t *log_item; apr_hash_this(hi, (void *) &path, NULL, &val); log_item = val; action[0] = log_item->action; action[1] = '\0'; if (log_item->copyfrom_path && SVN_IS_VALID_REVNUM(log_item->copyfrom_rev)) { /* <path action="X" copyfrom-path="xxx" copyfrom-rev="xxx"> */ svn_stringbuf_t *escpath = svn_stringbuf_create("", pool); svn_xml_escape_attr_cstring(&escpath, log_item->copyfrom_path, pool); revstr = apr_psprintf(pool, "%ld", log_item->copyfrom_rev); svn_xml_make_open_tag(&sb, pool, svn_xml_protect_pcdata, "path", "action", action, "copyfrom-path", escpath->data, "copyfrom-rev", revstr, NULL); } else { /* <path action="X"> */ svn_xml_make_open_tag(&sb, pool, svn_xml_protect_pcdata, "path", "action", action, NULL); } /* xxx</path> */ svn_xml_escape_cdata_cstring(&sb, path, pool); svn_xml_make_close_tag(&sb, pool, "path"); } /* </paths> */ svn_xml_make_close_tag(&sb, pool, "paths"); } if (message != NULL) { /* <msg>xxx</msg> */ svn_cl__xml_tagged_cdata(&sb, pool, "msg", message); } svn_compat_log_revprops_clear(log_entry->revprops); if (log_entry->revprops && apr_hash_count(log_entry->revprops) > 0) { svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "revprops", NULL); SVN_ERR(svn_cl__print_xml_prop_hash(&sb, log_entry->revprops, FALSE, /* name_only */ pool)); svn_xml_make_close_tag(&sb, pool, "revprops"); } if (log_entry->has_children) APR_ARRAY_PUSH(lb->merge_stack, svn_revnum_t) = log_entry->revision; else svn_xml_make_close_tag(&sb, pool, "logentry"); SVN_ERR(svn_cl__error_checked_fputs(sb->data, stdout)); 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; }