svn_error_t * svn_ra_serf__get_file_revs(svn_ra_session_t *ra_session, const char *path, svn_revnum_t start, svn_revnum_t end, svn_boolean_t include_merged_revisions, svn_file_rev_handler_t rev_handler, void *rev_handler_baton, apr_pool_t *pool) { blame_context_t *blame_ctx; svn_ra_serf__session_t *session = ra_session->priv; svn_ra_serf__handler_t *handler; svn_ra_serf__xml_context_t *xmlctx; const char *req_url; svn_revnum_t peg_rev; blame_ctx = apr_pcalloc(pool, sizeof(*blame_ctx)); blame_ctx->pool = pool; blame_ctx->path = path; blame_ctx->file_rev = rev_handler; blame_ctx->file_rev_baton = rev_handler_baton; blame_ctx->start = start; blame_ctx->end = end; blame_ctx->include_merged_revisions = include_merged_revisions; /* Since Subversion 1.8 we allow retrieving blames backwards. So we can't just unconditionally use end_rev as the peg revision as before */ if (end > start) peg_rev = end; else peg_rev = start; SVN_ERR(svn_ra_serf__get_stable_url(&req_url, NULL /* latest_revnum */, session, NULL /* url */, peg_rev, pool, pool)); xmlctx = svn_ra_serf__xml_context_create(blame_ttable, blame_opened, blame_closed, blame_cdata, blame_ctx, pool); handler = svn_ra_serf__create_expat_handler(session, xmlctx, NULL, pool); handler->method = "REPORT"; handler->path = req_url; handler->body_type = "text/xml"; handler->body_delegate = create_file_revs_body; handler->body_delegate_baton = blame_ctx; SVN_ERR(svn_ra_serf__context_run_one(handler, pool)); if (handler->sline.code != 200) return svn_error_trace(svn_ra_serf__unexpected_status(handler)); return SVN_NO_ERROR; }
svn_error_t * svn_ra_serf__create_propfind_handler(svn_ra_serf__handler_t **propfind_handler, svn_ra_serf__session_t *sess, const char *path, svn_revnum_t rev, const char *depth, const svn_ra_serf__dav_props_t *find_props, svn_ra_serf__prop_func_t prop_func, void *prop_func_baton, apr_pool_t *pool) { propfind_context_t *new_prop_ctx; svn_ra_serf__handler_t *handler; svn_ra_serf__xml_context_t *xmlctx; new_prop_ctx = apr_pcalloc(pool, sizeof(*new_prop_ctx)); new_prop_ctx->path = path; new_prop_ctx->find_props = find_props; new_prop_ctx->prop_func = prop_func; new_prop_ctx->prop_func_baton = prop_func_baton; new_prop_ctx->depth = depth; if (SVN_IS_VALID_REVNUM(rev)) { new_prop_ctx->label = apr_ltoa(pool, rev); } else { new_prop_ctx->label = NULL; } xmlctx = svn_ra_serf__xml_context_create(propfind_ttable, propfind_opened, propfind_closed, NULL, new_prop_ctx, pool); handler = svn_ra_serf__create_expat_handler(sess, xmlctx, propfind_expected_status, pool); handler->method = "PROPFIND"; handler->path = path; handler->body_delegate = create_propfind_body; handler->body_type = "text/xml"; handler->body_delegate_baton = new_prop_ctx; handler->header_delegate = setup_propfind_headers; handler->header_delegate_baton = new_prop_ctx; handler->no_dav_headers = TRUE; new_prop_ctx->handler = handler; *propfind_handler = handler; return SVN_NO_ERROR; }
svn_error_t * svn_ra_serf__list(svn_ra_session_t *ra_session, const char *path, svn_revnum_t revision, const apr_array_header_t *patterns, svn_depth_t depth, apr_uint32_t dirent_fields, svn_ra_dirent_receiver_t receiver, void *receiver_baton, apr_pool_t *scratch_pool) { list_context_t *list_ctx; svn_ra_serf__session_t *session = ra_session->priv; svn_ra_serf__handler_t *handler; svn_ra_serf__xml_context_t *xmlctx; const char *req_url; list_ctx = apr_pcalloc(scratch_pool, sizeof(*list_ctx)); list_ctx->pool = scratch_pool; list_ctx->receiver = receiver; list_ctx->receiver_baton = receiver_baton; list_ctx->path = path; list_ctx->revision = revision; list_ctx->patterns = patterns; list_ctx->depth = depth; list_ctx->dirent_fields = dirent_fields; list_ctx->props = svn_ra_serf__get_dirent_props(dirent_fields, session, scratch_pool); list_ctx->author_buf = svn_stringbuf_create_empty(scratch_pool); /* At this point, we may have a deleted file. So, we'll match ra_neon's * behavior and use the larger of start or end as our 'peg' rev. */ SVN_ERR(svn_ra_serf__get_stable_url(&req_url, NULL /* latest_revnum */, session, NULL /* url */, revision, scratch_pool, scratch_pool)); xmlctx = svn_ra_serf__xml_context_create(log_ttable, NULL, item_closed, NULL, list_ctx, scratch_pool); handler = svn_ra_serf__create_expat_handler(session, xmlctx, NULL, scratch_pool); handler->method = "REPORT"; handler->path = req_url; handler->body_delegate = create_list_body; handler->body_delegate_baton = list_ctx; handler->body_type = "text/xml"; SVN_ERR(svn_ra_serf__context_run_one(handler, scratch_pool)); if (handler->sline.code != 200) SVN_ERR(svn_ra_serf__unexpected_status(handler)); return SVN_NO_ERROR; }
svn_error_t * svn_ra_serf__get_file_revs(svn_ra_session_t *ra_session, const char *path, svn_revnum_t start, svn_revnum_t end, svn_boolean_t include_merged_revisions, svn_file_rev_handler_t rev_handler, void *rev_handler_baton, apr_pool_t *pool) { blame_context_t *blame_ctx; svn_ra_serf__session_t *session = ra_session->priv; svn_ra_serf__handler_t *handler; svn_ra_serf__xml_context_t *xmlctx; const char *req_url; svn_error_t *err; blame_ctx = apr_pcalloc(pool, sizeof(*blame_ctx)); blame_ctx->pool = pool; blame_ctx->path = path; blame_ctx->file_rev = rev_handler; blame_ctx->file_rev_baton = rev_handler_baton; blame_ctx->start = start; blame_ctx->end = end; blame_ctx->include_merged_revisions = include_merged_revisions; SVN_ERR(svn_ra_serf__get_stable_url(&req_url, NULL /* latest_revnum */, session, NULL /* conn */, NULL /* url */, end, pool, pool)); xmlctx = svn_ra_serf__xml_context_create(blame_ttable, blame_opened, blame_closed, blame_cdata, blame_ctx, pool); handler = svn_ra_serf__create_expat_handler(xmlctx, pool); handler->method = "REPORT"; handler->path = req_url; handler->body_type = "text/xml"; handler->body_delegate = create_file_revs_body; handler->body_delegate_baton = blame_ctx; handler->conn = session->conns[0]; handler->session = session; err = svn_ra_serf__context_run_one(handler, pool); err = svn_error_compose_create( svn_ra_serf__error_on_status(handler->sline, handler->path, handler->location), err); return svn_error_trace(err); }
svn_error_t * svn_ra_serf__get_locations(svn_ra_session_t *ra_session, apr_hash_t **locations, const char *path, svn_revnum_t peg_revision, const apr_array_header_t *location_revisions, apr_pool_t *pool) { loc_context_t *loc_ctx; svn_ra_serf__session_t *session = ra_session->priv; svn_ra_serf__handler_t *handler; svn_ra_serf__xml_context_t *xmlctx; const char *req_url; svn_error_t *err; loc_ctx = apr_pcalloc(pool, sizeof(*loc_ctx)); loc_ctx->pool = pool; loc_ctx->path = path; loc_ctx->peg_revision = peg_revision; loc_ctx->location_revisions = location_revisions; loc_ctx->paths = apr_hash_make(loc_ctx->pool); *locations = loc_ctx->paths; SVN_ERR(svn_ra_serf__get_stable_url(&req_url, NULL /* latest_revnum */, session, NULL /* conn */, NULL /* url */, peg_revision, pool, pool)); xmlctx = svn_ra_serf__xml_context_create(getloc_ttable, NULL, getloc_closed, NULL, loc_ctx, pool); handler = svn_ra_serf__create_expat_handler(xmlctx, pool); handler->method = "REPORT"; handler->path = req_url; handler->body_delegate = create_get_locations_body; handler->body_delegate_baton = loc_ctx; handler->body_type = "text/xml"; handler->conn = session->conns[0]; handler->session = session; err = svn_ra_serf__context_run_one(handler, pool); SVN_ERR(svn_error_compose_create( svn_ra_serf__error_on_status(handler->sline.code, req_url, handler->location), err)); return SVN_NO_ERROR; }
svn_error_t * svn_ra_serf__get_locks(svn_ra_session_t *ra_session, apr_hash_t **locks, const char *path, svn_depth_t depth, apr_pool_t *pool) { lock_context_t *lock_ctx; svn_ra_serf__session_t *session = ra_session->priv; svn_ra_serf__handler_t *handler; svn_ra_serf__xml_context_t *xmlctx; const char *req_url, *rel_path; req_url = svn_path_url_add_component2(session->session_url.path, path, pool); SVN_ERR(svn_ra_serf__get_relative_path(&rel_path, req_url, session, NULL, pool)); lock_ctx = apr_pcalloc(pool, sizeof(*lock_ctx)); lock_ctx->pool = pool; lock_ctx->path = apr_pstrcat(pool, "/", rel_path, (char *)NULL); lock_ctx->requested_depth = depth; lock_ctx->hash = apr_hash_make(pool); xmlctx = svn_ra_serf__xml_context_create(getlocks_ttable, NULL, getlocks_closed, NULL, lock_ctx, pool); handler = svn_ra_serf__create_expat_handler(xmlctx, pool); handler->method = "REPORT"; handler->path = req_url; handler->body_type = "text/xml"; handler->conn = session->conns[0]; handler->session = session; handler->body_delegate = create_getlocks_body; handler->body_delegate_baton = lock_ctx; SVN_ERR(svn_ra_serf__context_run_one(handler, pool)); /* We get a 404 when a path doesn't exist in HEAD, but it might have existed earlier (E.g. 'svn ls http://s/svn/trunk/file@1' */ if (handler->sline.code != 404) { SVN_ERR(svn_ra_serf__error_on_status(handler->sline, handler->path, handler->location)); } *locks = lock_ctx->hash; return SVN_NO_ERROR; }
svn_error_t * svn_ra_serf__get_deleted_rev(svn_ra_session_t *session, const char *path, svn_revnum_t peg_revision, svn_revnum_t end_revision, svn_revnum_t *revision_deleted, apr_pool_t *pool) { drev_context_t *drev_ctx; svn_ra_serf__session_t *ras = session->priv; svn_ra_serf__handler_t *handler; svn_ra_serf__xml_context_t *xmlctx; const char *req_url; svn_error_t *err; drev_ctx = apr_pcalloc(pool, sizeof(*drev_ctx)); drev_ctx->path = path; drev_ctx->peg_revision = peg_revision; drev_ctx->end_revision = end_revision; drev_ctx->revision_deleted = revision_deleted; SVN_ERR(svn_ra_serf__get_stable_url(&req_url, NULL /* latest_revnum */, ras, NULL /* conn */, NULL /* url */, peg_revision, pool, pool)); xmlctx = svn_ra_serf__xml_context_create(getdrev_ttable, NULL, getdrev_closed, NULL, drev_ctx, pool); handler = svn_ra_serf__create_expat_handler(xmlctx, pool); handler->method = "REPORT"; handler->path = req_url; handler->body_type = "text/xml"; handler->body_delegate = create_getdrev_body; handler->body_delegate_baton = drev_ctx; handler->conn = ras->conns[0]; handler->session = ras; err = svn_ra_serf__context_run_one(handler, pool); /* Map status 501: Method Not Implemented to our not implemented error. 1.5.x servers and older don't support this report. */ if (handler->sline.code == 501) return svn_error_createf(SVN_ERR_RA_NOT_IMPLEMENTED, err, _("'%s' REPORT not implemented"), "get-deleted-rev"); SVN_ERR(err); return SVN_NO_ERROR; }
svn_error_t * svn_ra_serf__get_dated_revision(svn_ra_session_t *ra_session, svn_revnum_t *revision, apr_time_t tm, apr_pool_t *pool) { date_context_t *date_ctx; svn_ra_serf__session_t *session = ra_session->priv; svn_ra_serf__handler_t *handler; svn_ra_serf__xml_context_t *xmlctx; const char *report_target; date_ctx = apr_palloc(pool, sizeof(*date_ctx)); date_ctx->time = tm; date_ctx->revision = revision; SVN_ERR(svn_ra_serf__report_resource(&report_target, session, pool)); xmlctx = svn_ra_serf__xml_context_create(date_ttable, NULL, date_closed, NULL, date_ctx, pool); handler = svn_ra_serf__create_expat_handler(session, xmlctx, NULL, pool); handler->method = "REPORT"; handler->path = report_target; handler->body_type = "text/xml"; handler->body_delegate = create_getdate_body; handler->body_delegate_baton = date_ctx; *date_ctx->revision = SVN_INVALID_REVNUM; SVN_ERR(svn_ra_serf__context_run_one(handler, pool)); if (handler->sline.code != 200) return svn_error_trace(svn_ra_serf__unexpected_status(handler)); if (!SVN_IS_VALID_REVNUM(*revision)) return svn_error_create(SVN_ERR_RA_DAV_PROPS_NOT_FOUND, NULL, _("The REPORT response did not include " "the requested properties")); return SVN_NO_ERROR; }
svn_error_t * svn_ra_serf__run_merge(const svn_commit_info_t **commit_info, svn_ra_serf__session_t *session, const char *merge_resource_url, apr_hash_t *lock_tokens, svn_boolean_t keep_locks, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { merge_context_t *merge_ctx; svn_ra_serf__handler_t *handler; svn_ra_serf__xml_context_t *xmlctx; merge_ctx = apr_pcalloc(scratch_pool, sizeof(*merge_ctx)); merge_ctx->pool = result_pool; merge_ctx->session = session; merge_ctx->merge_resource_url = merge_resource_url; merge_ctx->lock_tokens = lock_tokens; merge_ctx->keep_locks = keep_locks; /* We don't need the full merge response when working over HTTPv2. * Over HTTPv1, this response is only required with a non-null * svn_ra_push_wc_prop_func_t callback. */ merge_ctx->disable_merge_response = SVN_RA_SERF__HAVE_HTTPV2_SUPPORT(session) || session->wc_callbacks->push_wc_prop == NULL; merge_ctx->commit_info = svn_create_commit_info(result_pool); merge_ctx->merge_url = session->session_url.path; xmlctx = svn_ra_serf__xml_context_create(merge_ttable, NULL, merge_closed, NULL, merge_ctx, scratch_pool); handler = svn_ra_serf__create_expat_handler(session, xmlctx, NULL, scratch_pool); handler->method = "MERGE"; handler->path = merge_ctx->merge_url; handler->body_delegate = create_merge_body; handler->body_delegate_baton = merge_ctx; handler->body_type = "text/xml"; handler->header_delegate = setup_merge_headers; handler->header_delegate_baton = merge_ctx; merge_ctx->handler = handler; SVN_ERR(svn_ra_serf__context_run_one(handler, scratch_pool)); if (handler->sline.code != 200) return svn_error_trace(svn_ra_serf__unexpected_status(handler)); *commit_info = merge_ctx->commit_info; /* Sanity check (Reported to be triggered by CodePlex's svnbridge) */ if (! SVN_IS_VALID_REVNUM(merge_ctx->commit_info->revision)) { return svn_error_create(SVN_ERR_RA_DAV_PROPS_NOT_FOUND, NULL, _("The MERGE response did not include " "a new revision")); } merge_ctx->commit_info->repos_root = apr_pstrdup(result_pool, session->repos_root_str); return SVN_NO_ERROR; }
svn_error_t * svn_ra_serf__run_merge(const svn_commit_info_t **commit_info, svn_ra_serf__session_t *session, const char *merge_resource_url, apr_hash_t *lock_tokens, svn_boolean_t keep_locks, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { merge_context_t *merge_ctx; svn_ra_serf__handler_t *handler; svn_ra_serf__xml_context_t *xmlctx; merge_ctx = apr_pcalloc(scratch_pool, sizeof(*merge_ctx)); merge_ctx->pool = result_pool; merge_ctx->session = session; merge_ctx->merge_resource_url = merge_resource_url; merge_ctx->lock_tokens = lock_tokens; merge_ctx->keep_locks = keep_locks; merge_ctx->commit_info = svn_create_commit_info(result_pool); merge_ctx->merge_url = session->session_url.path; xmlctx = svn_ra_serf__xml_context_create(merge_ttable, NULL, merge_closed, NULL, merge_ctx, scratch_pool); handler = svn_ra_serf__create_expat_handler(session, xmlctx, NULL, scratch_pool); handler->method = "MERGE"; handler->path = merge_ctx->merge_url; handler->body_delegate = create_merge_body; handler->body_delegate_baton = merge_ctx; handler->header_delegate = setup_merge_headers; handler->header_delegate_baton = merge_ctx; merge_ctx->handler = handler; SVN_ERR(svn_ra_serf__context_run_one(handler, scratch_pool)); if (handler->sline.code != 200) return svn_error_trace(svn_ra_serf__unexpected_status(handler)); *commit_info = merge_ctx->commit_info; /* Sanity check (Reported to be triggered by CodePlex's svnbridge) */ if (! SVN_IS_VALID_REVNUM(merge_ctx->commit_info->revision)) { return svn_error_create(SVN_ERR_RA_DAV_PROPS_NOT_FOUND, NULL, _("The MERGE response did not include " "a new revision")); } merge_ctx->commit_info->repos_root = apr_pstrdup(result_pool, session->repos_root_str); return SVN_NO_ERROR; }
svn_error_t * svn_ra_serf__get_locks(svn_ra_session_t *ra_session, apr_hash_t **locks, const char *path, svn_depth_t depth, apr_pool_t *pool) { lock_context_t *lock_ctx; svn_ra_serf__session_t *session = ra_session->priv; svn_ra_serf__handler_t *handler; svn_ra_serf__xml_context_t *xmlctx; const char *req_url, *rel_path; svn_error_t *err; req_url = svn_path_url_add_component2(session->session_url.path, path, pool); SVN_ERR(svn_ra_serf__get_relative_path(&rel_path, req_url, session, pool)); lock_ctx = apr_pcalloc(pool, sizeof(*lock_ctx)); lock_ctx->pool = pool; lock_ctx->path = apr_pstrcat(pool, "/", rel_path, SVN_VA_NULL); lock_ctx->requested_depth = depth; lock_ctx->hash = apr_hash_make(pool); xmlctx = svn_ra_serf__xml_context_create(getlocks_ttable, NULL, getlocks_closed, NULL, lock_ctx, pool); handler = svn_ra_serf__create_expat_handler(session, xmlctx, NULL, pool); handler->method = "REPORT"; handler->path = req_url; handler->body_type = "text/xml"; handler->body_delegate = create_getlocks_body; handler->body_delegate_baton = lock_ctx; err = svn_ra_serf__context_run_one(handler, pool); if (err) { if (svn_error_find_cause(err, SVN_ERR_UNSUPPORTED_FEATURE)) { /* The server told us that it doesn't support this report type. We return the documented error for svn_ra_get_locks(), but with the original error report */ return svn_error_create(SVN_ERR_RA_NOT_IMPLEMENTED, err, NULL); } else if (err->apr_err == SVN_ERR_FS_NOT_FOUND) { /* File doesn't exist in HEAD: Not an error */ svn_error_clear(err); } else return svn_error_trace(err); } /* We get a 404 when a path doesn't exist in HEAD, but it might have existed earlier (E.g. 'svn ls http://s/svn/trunk/file@1' */ if (handler->sline.code != 200 && handler->sline.code != 404) { return svn_error_trace(svn_ra_serf__unexpected_status(handler)); } *locks = lock_ctx->hash; return SVN_NO_ERROR; }