📄 update.c
字号:
if (! uc->resource_walk) { const char *elt = apr_psprintf(pool, "<S:absent-%s name=\"%s\"/>" DEBUG_CR, DIR_OR_FILE(is_dir), apr_xml_quote_string (pool, svn_path_basename(path, pool), 1)); SVN_ERR(dav_svn__send_xml(uc->bb, uc->output, "%s", elt)); } return SVN_NO_ERROR;}static svn_error_t * upd_absent_directory(const char *path, void *parent_baton, apr_pool_t *pool){ return absent_helper(TRUE, path, parent_baton, pool);}static svn_error_t * upd_absent_file(const char *path, void *parent_baton, apr_pool_t *pool){ return absent_helper(FALSE, path, parent_baton, pool);}static svn_error_t * add_helper(svn_boolean_t is_dir, const char *path, item_baton_t *parent, const char *copyfrom_path, svn_revnum_t copyfrom_revision, apr_pool_t *pool, void **child_baton){ item_baton_t *child; update_ctx_t *uc = parent->uc; const char *bc_url = NULL; child = make_child_baton(parent, path, pool); child->added = TRUE; if (uc->resource_walk) { SVN_ERR(dav_svn__send_xml(child->uc->bb, child->uc->output, "<S:resource path=\"%s\">" DEBUG_CR, apr_xml_quote_string(pool, child->path3, 1))); } else { const char *qname = apr_xml_quote_string(pool, child->name, 1); const char *elt; const char *real_path = get_real_fs_path(child, pool); if (! is_dir) { /* files have checksums */ unsigned char digest[APR_MD5_DIGESTSIZE]; SVN_ERR(svn_fs_file_md5_checksum (digest, uc->rev_root, real_path, pool)); child->text_checksum = svn_md5_digest_to_cstring(digest, pool); } else { /* we send baseline-collection urls when we add a directory */ svn_revnum_t revision; revision = dav_svn_get_safe_cr(child->uc->rev_root, real_path, pool); bc_url = dav_svn_build_uri(child->uc->resource->info->repos, DAV_SVN_BUILD_URI_BC, revision, real_path, 0 /* add_href */, pool); /* ugh, build_uri ignores the path and just builds the root of the baseline collection. we have to tack the real_path on manually, ignoring its leading slash. */ if (real_path && (! svn_path_is_empty(real_path))) bc_url = svn_path_url_add_component(bc_url, real_path+1, pool); /* make sure that the BC_URL is xml attribute safe. */ bc_url = apr_xml_quote_string(pool, bc_url, 1); } if (copyfrom_path == NULL) { if (bc_url) elt = apr_psprintf(pool, "<S:add-%s name=\"%s\" " "bc-url=\"%s\">" DEBUG_CR, DIR_OR_FILE(is_dir), qname, bc_url); else elt = apr_psprintf(pool, "<S:add-%s name=\"%s\">" DEBUG_CR, DIR_OR_FILE(is_dir), qname); } else { const char *qcopy = apr_xml_quote_string(pool, copyfrom_path, 1); if (bc_url) elt = apr_psprintf(pool, "<S:add-%s name=\"%s\" " "copyfrom-path=\"%s\" copyfrom-rev=\"%ld\" " "bc-url=\"%s\">" DEBUG_CR, DIR_OR_FILE(is_dir), qname, qcopy, copyfrom_revision, bc_url); else elt = apr_psprintf(pool, "<S:add-%s name=\"%s\" " "copyfrom-path=\"%s\"" " copyfrom-rev=\"%ld\">" DEBUG_CR, DIR_OR_FILE(is_dir), qname, qcopy, copyfrom_revision); } /* Resist the temptation to pass 'elt' as the format string. Because it contains URIs, it might have sequences that look like format string insert placeholders. For example, "this%20dir" is a valid printf() format string that means "this[insert an integer of width 20 here]ir". */ SVN_ERR(dav_svn__send_xml(child->uc->bb, child->uc->output, "%s", elt)); } SVN_ERR(send_vsn_url(child, pool)); if (uc->resource_walk) SVN_ERR(dav_svn__send_xml(child->uc->bb, child->uc->output, "</S:resource>" DEBUG_CR)); *child_baton = child; return SVN_NO_ERROR;}static svn_error_t * open_helper(svn_boolean_t is_dir, const char *path, item_baton_t *parent, svn_revnum_t base_revision, apr_pool_t *pool, void **child_baton){ item_baton_t *child = make_child_baton(parent, path, pool); const char *qname = apr_xml_quote_string(pool, child->name, 1); SVN_ERR(dav_svn__send_xml(child->uc->bb, child->uc->output, "<S:open-%s name=\"%s\"" " rev=\"%ld\">" DEBUG_CR, DIR_OR_FILE(is_dir), qname, base_revision)); SVN_ERR(send_vsn_url(child, pool)); *child_baton = child; return SVN_NO_ERROR;}static svn_error_t * close_helper(svn_boolean_t is_dir, item_baton_t *baton){ int i; if (baton->uc->resource_walk) return SVN_NO_ERROR; /* ### ack! binary names won't float here! */ if (baton->removed_props && (! baton->added)) { const char *qname; for (i = 0; i < baton->removed_props->nelts; i++) { /* We already XML-escaped the property name in change_xxx_prop. */ qname = ((const char **)(baton->removed_props->elts))[i]; SVN_ERR(dav_svn__send_xml(baton->uc->bb, baton->uc->output, "<S:remove-prop name=\"%s\"/>" DEBUG_CR, qname)); } } if ((! baton->uc->send_all) && baton->changed_props && (! baton->added)) { /* Tell the client to fetch all the props */ SVN_ERR(dav_svn__send_xml(baton->uc->bb, baton->uc->output, "<S:fetch-props/>" DEBUG_CR)); } SVN_ERR(dav_svn__send_xml(baton->uc->bb, baton->uc->output, "<S:prop>")); /* Both modern and non-modern clients need the checksum... */ if (baton->text_checksum) { SVN_ERR(dav_svn__send_xml(baton->uc->bb, baton->uc->output, "<V:md5-checksum>%s</V:md5-checksum>", baton->text_checksum)); } /* ...but only non-modern clients want the 3 CR-related properties sent like here, because they can't handle receiving these special props inline like any other prop. ### later on, compress via the 'scattered table' solution as discussed with gstein. -bmcs */ if (! baton->uc->send_all) { /* ### grrr, these DAV: property names are already #defined in ra_dav.h, and statically defined in liveprops.c. And now they're hardcoded here. Isn't there some header file that both sides of the network can share?? */ /* ### special knowledge: svn_repos_dir_delta will never send *removals* of the commit-info "entry props". */ if (baton->committed_rev) SVN_ERR(dav_svn__send_xml(baton->uc->bb, baton->uc->output, "<D:version-name>%s</D:version-name>", baton->committed_rev)); if (baton->committed_date) SVN_ERR(dav_svn__send_xml(baton->uc->bb, baton->uc->output, "<D:creationdate>%s</D:creationdate>", baton->committed_date)); if (baton->last_author) SVN_ERR(dav_svn__send_xml(baton->uc->bb, baton->uc->output, "<D:creator-displayname>%s" "</D:creator-displayname>", apr_xml_quote_string(baton->pool, baton->last_author, 1))); } /* Close unconditionally, because we sent checksum unconditionally. */ SVN_ERR(dav_svn__send_xml(baton->uc->bb, baton->uc->output, "</S:prop>\n")); if (baton->added) SVN_ERR(dav_svn__send_xml(baton->uc->bb, baton->uc->output, "</S:add-%s>" DEBUG_CR, DIR_OR_FILE(is_dir))); else SVN_ERR(dav_svn__send_xml(baton->uc->bb, baton->uc->output, "</S:open-%s>" DEBUG_CR, DIR_OR_FILE(is_dir))); return SVN_NO_ERROR;}/* Send the opening tag of the update-report if it hasn't been sent already. Note: because dav_svn__send_xml does not return an error, this function never returns error either. However, its prototype anticipates a day when dav_svn__send_xml() can return error. */static svn_error_t * maybe_start_update_report(update_ctx_t *uc){ if ((! uc->resource_walk) && (! uc->started_update)) { SVN_ERR(dav_svn__send_xml(uc->bb, uc->output, DAV_XML_HEADER DEBUG_CR "<S:update-report xmlns:S=\"" SVN_XML_NAMESPACE "\" " "xmlns:V=\"" SVN_DAV_PROP_NS_DAV "\" " "xmlns:D=\"DAV:\" %s>" DEBUG_CR, uc->send_all ? "send-all=\"true\"" : "")); uc->started_update = TRUE; } return SVN_NO_ERROR;}static svn_error_t * upd_set_target_revision(void *edit_baton, svn_revnum_t target_revision, apr_pool_t *pool){ update_ctx_t *uc = edit_baton; SVN_ERR(maybe_start_update_report(uc)); if (! uc->resource_walk) SVN_ERR(dav_svn__send_xml(uc->bb, uc->output, "<S:target-revision rev=\"%ld" "\"/>" DEBUG_CR, target_revision)); return SVN_NO_ERROR;}static svn_error_t * upd_open_root(void *edit_baton, svn_revnum_t base_revision, apr_pool_t *pool, void **root_baton){ update_ctx_t *uc = edit_baton; item_baton_t *b = apr_pcalloc(pool, sizeof(*b)); /* note that we create a subpool; the root_baton is passed to the close_directory callback, where we will destroy the pool. */ b->uc = uc; b->pool = pool; b->path = uc->anchor; b->path2 = uc->dst_path; b->path3 = ""; *root_baton = b; SVN_ERR(maybe_start_update_report(uc)); if (uc->resource_walk) { const char *qpath = apr_xml_quote_string(pool, b->path3, 1); SVN_ERR(dav_svn__send_xml(uc->bb, uc->output, "<S:resource path=\"%s\">" DEBUG_CR, qpath)); } else { SVN_ERR(dav_svn__send_xml(uc->bb, uc->output, "<S:open-directory rev=\"%ld\">" DEBUG_CR, base_revision)); } /* Only transmit the root directory's Version Resource URL if there's no target. */ if (! *uc->target) SVN_ERR(send_vsn_url(b, pool)); if (uc->resource_walk) SVN_ERR(dav_svn__send_xml(uc->bb, uc->output, "</S:resource>" DEBUG_CR)); return SVN_NO_ERROR;}static svn_error_t * upd_delete_entry(const char *path, svn_revnum_t revision, void *parent_baton, apr_pool_t *pool){ item_baton_t *parent = parent_baton; const char *qname = apr_xml_quote_string(pool, svn_path_basename(path, pool), 1); return dav_svn__send_xml(parent->uc->bb, parent->uc->output, "<S:delete-entry name=\"%s\"/>" DEBUG_CR, qname);}static svn_error_t * upd_add_directory(const char *path, void *parent_baton, const char *copyfrom_path, svn_revnum_t copyfrom_revision, apr_pool_t *pool, void **child_baton){ return add_helper(TRUE /* is_dir */, path, parent_baton, copyfrom_path, copyfrom_revision, pool, child_baton);}static svn_error_t * upd_open_directory(const char *path, void *parent_baton, svn_revnum_t base_revision, apr_pool_t *pool, void **child_baton){ return open_helper(TRUE /* is_dir */, path, parent_baton, base_revision, pool, child_baton);}static svn_error_t * upd_change_xxx_prop(void *baton, const char *name, const svn_string_t *value, apr_pool_t *pool){ item_baton_t *b = baton; const char *qname; /* Resource walks say nothing about props. */ if (b->uc->resource_walk) return SVN_NO_ERROR; /* Else this not a resource walk, so either send props or cache them to send later, depending on whether this is a modern report response or not. */ qname = apr_xml_quote_string(b->pool, name, 1); /* apr_xml_quote_string doesn't realloc if there is nothing to quote, so dup the name, but only if necessary. */ if (qname == name) qname = apr_pstrdup(b->pool, name); if (b->uc->send_all) { if (value) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -