📄 log-cmd.c
字号:
* </logentry> * </log> * */static svn_error_t *log_message_receiver_xml(void *baton, apr_hash_t *changed_paths, svn_revnum_t rev, const char *author, const char *date, const char *msg, 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; if (lb->cancel_func) SVN_ERR(lb->cancel_func(lb->cancel_baton)); if (rev == 0 && msg == NULL) return SVN_NO_ERROR; revstr = apr_psprintf(pool, "%ld", rev); /* <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_message_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 (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, 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 (! lb->omit_log_message) { if (msg == NULL) msg = ""; /* <msg>xxx</msg> */ svn_cl__xml_tagged_cdata(&sb, pool, "msg", msg); } /* </logentry> */ 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__log(apr_getopt_t *os, void *baton, apr_pool_t *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; struct log_receiver_baton lb; const char *target; int i; svn_opt_revision_t peg_revision; const char *true_path; SVN_ERR(svn_opt_args_to_target_array2(&targets, os, opt_state->targets, pool)); /* Add "." if user passed 0 arguments */ svn_opt_push_implicit_dot_target(targets, pool); target = APR_ARRAY_IDX(targets, 0, const char *); /* Strip peg revision if targets contains an URI. */ SVN_ERR(svn_opt_parse_path(&peg_revision, &true_path, target, pool)); APR_ARRAY_IDX(targets, 0, const char *) = true_path; if ((opt_state->start_revision.kind != svn_opt_revision_unspecified) && (opt_state->end_revision.kind == svn_opt_revision_unspecified)) { /* If the user specified exactly one revision, then start rev is set but end is not. We show the log message for just that revision by making end equal to start. Note that if the user requested a single dated revision, then this will cause the same date to be resolved twice. The extra code complexity to get around this slight inefficiency doesn't seem worth it, however. */ opt_state->end_revision = opt_state->start_revision; } else if (opt_state->start_revision.kind == svn_opt_revision_unspecified) { /* Default to any specified peg revision. Otherwise, if the first target is an URL, then we default to HEAD:0. Lastly, the default is BASE:0 since WC@HEAD may not exist. */ if (peg_revision.kind == svn_opt_revision_unspecified) { if (svn_path_is_url(target)) opt_state->start_revision.kind = svn_opt_revision_head; else opt_state->start_revision.kind = svn_opt_revision_base; } else opt_state->start_revision = peg_revision; if (opt_state->end_revision.kind == svn_opt_revision_unspecified) { opt_state->end_revision.kind = svn_opt_revision_number; opt_state->end_revision.value.number = 0; } } /* Verify that we pass at most one working copy path. */ if (! svn_path_is_url(target) ) { if (targets->nelts > 1) return svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL, _("When specifying working copy paths, only " "one target may be given")); } else { /* Check to make sure there are no other URLs. */ for (i = 1; i < targets->nelts; i++) { target = APR_ARRAY_IDX(targets, i, const char *); if (svn_path_is_url(target)) return svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL, _("Only relative paths can be specified " "after a URL")); } } lb.cancel_func = ctx->cancel_func; lb.cancel_baton = ctx->cancel_baton; lb.omit_log_message = opt_state->quiet; if (! opt_state->quiet) svn_cl__get_notifier(&ctx->notify_func2, &ctx->notify_baton2, FALSE, FALSE, FALSE, pool); if (opt_state->xml) { /* If output is not incremental, output the XML header and wrap everything in a top-level element. This makes the output in its entirety a well-formed XML document. */ if (! opt_state->incremental) { svn_stringbuf_t *sb = svn_stringbuf_create("", pool); /* <?xml version="1.0" encoding="utf-8"?> */ svn_xml_make_header(&sb, pool); /* "<log>" */ svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "log", NULL); SVN_ERR(svn_cl__error_checked_fputs(sb->data, stdout)); } SVN_ERR(svn_client_log3(targets, &peg_revision, &(opt_state->start_revision), &(opt_state->end_revision), opt_state->limit, opt_state->verbose, opt_state->stop_on_copy, log_message_receiver_xml, &lb, ctx, pool)); if (! opt_state->incremental) { svn_stringbuf_t *sb = svn_stringbuf_create("", pool); /* "</log>" */ svn_xml_make_close_tag(&sb, pool, "log"); SVN_ERR(svn_cl__error_checked_fputs(sb->data, stdout)); } } else /* default output format */ { /* ### Ideally, we'd also pass the `quiet' flag through to the * repository code, so we wouldn't waste bandwith sending the * log message bodies back only to have the client ignore them. * However, that's an implementation detail; as far as the user * is concerned, the result of 'svn log --quiet' is the same * either way. */ SVN_ERR(svn_client_log3(targets, &peg_revision, &(opt_state->start_revision), &(opt_state->end_revision), opt_state->limit, opt_state->verbose, opt_state->stop_on_copy, log_message_receiver, &lb, ctx, pool)); if (! opt_state->incremental) SVN_ERR(svn_cmdline_printf(pool, SEP_STRING)); } return SVN_NO_ERROR;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -