📄 ra.c
字号:
oldest = (end_revnum < oldest) ? end_revnum : oldest; /* Build a one-item TARGETS array, as input to ra->get_log() */ targets = apr_array_make(pool, 1, sizeof(const char *)); APR_ARRAY_PUSH(targets, const char *) = ""; /* Let the RA layer drive our log information handler, which will do the work of finding the actual locations for our resource. Notice that we always run on the youngest rev of the 3 inputs. */ SVN_ERR(svn_ra_get_log(ra_session, targets, youngest, oldest, 0, TRUE, FALSE, log_receiver, &lrb, pool)); /* If the received log information did not cover any of the requested revisions, use the last known path. (This normally just means that ABS_PATH was not modified between the requested revision and OLDEST. If the file was created at some point after OLDEST, then lrb.last_path should be NULL.) */ if (! lrb.peg_path) lrb.peg_path = lrb.last_path; if (! *start_path) *start_path = lrb.last_path; if (! *end_path) *end_path = lrb.last_path; /* Check that we got the peg path. */ if (! lrb.peg_path) return svn_error_createf (APR_EGENERAL, NULL, _("Unable to find repository location for '%s' in revision %ld"), orig_path, peg_revnum); /* If our peg revision was smaller than either of our range revisions, we need to make sure that our calculated peg path is the same as what we expected it to be. */ if (! pegrev_is_youngest) { if (strcmp(abs_path, lrb.peg_path) != 0) return svn_error_createf (SVN_ERR_CLIENT_UNRELATED_RESOURCES, NULL, _("'%s' in revision %ld is an unrelated object"), orig_path, youngest); } return SVN_NO_ERROR;} svn_error_t *svn_client__repos_locations(const char **start_url, svn_opt_revision_t **start_revision, const char **end_url, svn_opt_revision_t **end_revision, svn_ra_session_t *ra_session, const char *path, const svn_opt_revision_t *revision, const svn_opt_revision_t *start, const svn_opt_revision_t *end, svn_client_ctx_t *ctx, apr_pool_t *pool){ const char *repos_url; const char *url; const char *start_path = NULL; const char *end_path = NULL; svn_revnum_t peg_revnum = SVN_INVALID_REVNUM; svn_revnum_t start_revnum, end_revnum; apr_array_header_t *revs; apr_hash_t *rev_locs; apr_pool_t *subpool = svn_pool_create(pool); svn_error_t *err; /* Ensure that we are given some real revision data to work with. (It's okay if the END is unspecified -- in that case, we'll just set it to the same thing as START.) */ if (revision->kind == svn_opt_revision_unspecified || start->kind == svn_opt_revision_unspecified) return svn_error_create(SVN_ERR_CLIENT_BAD_REVISION, NULL, NULL); /* Check to see if this is schedule add with history working copy path. If it is, then we need to use the URL and peg revision of the copyfrom information. */ if (! svn_path_is_url(path)) { svn_wc_adm_access_t *adm_access; const svn_wc_entry_t *entry; SVN_ERR(svn_wc_adm_probe_open3(&adm_access, NULL, path, FALSE, 0, ctx->cancel_func, ctx->cancel_baton, pool)); SVN_ERR(svn_wc_entry(&entry, path, adm_access, FALSE, pool)); SVN_ERR(svn_wc_adm_close(adm_access)); if (entry->copyfrom_url && revision->kind == svn_opt_revision_working) { url = entry->copyfrom_url; peg_revnum = entry->copyfrom_rev; if (!entry->url || strcmp(entry->url, entry->copyfrom_url) != 0) { /* We can't use the caller provided RA session in this case */ ra_session = NULL; } } else if (entry->url) { url = entry->url; } else { return svn_error_createf(SVN_ERR_ENTRY_MISSING_URL, NULL, _("'%s' has no URL"), svn_path_local_style(path, pool)); } } else { url = path; } /* ### We should be smarter here. If the callers just asks for BASE and WORKING revisions, we should already have the correct URL:s, so we don't need to do anything more here in that case. */ /* Open a RA session to this URL if we don't have one already. */ if (! ra_session) SVN_ERR(svn_client__open_ra_session_internal(&ra_session, url, NULL, NULL, NULL, FALSE, TRUE, ctx, subpool)); /* Resolve the opt_revision_ts. */ if (peg_revnum == SVN_INVALID_REVNUM) SVN_ERR(svn_client__get_revision_number(&peg_revnum, ra_session, revision, path, pool)); SVN_ERR(svn_client__get_revision_number(&start_revnum, ra_session, start, path, pool)); if (end->kind == svn_opt_revision_unspecified) end_revnum = start_revnum; else SVN_ERR(svn_client__get_revision_number(&end_revnum, ra_session, end, path, pool)); /* Set the output revision variables. */ *start_revision = apr_pcalloc(pool, sizeof(**start_revision)); (*start_revision)->kind = svn_opt_revision_number; (*start_revision)->value.number = start_revnum; if (end->kind != svn_opt_revision_unspecified) { *end_revision = apr_pcalloc(pool, sizeof(**end_revision)); (*end_revision)->kind = svn_opt_revision_number; (*end_revision)->value.number = end_revnum; } if (start_revnum == peg_revnum && end_revnum == peg_revnum) { /* Avoid a network request in the common easy case. */ *start_url = url; if (end->kind != svn_opt_revision_unspecified) *end_url = url; svn_pool_destroy(subpool); return SVN_NO_ERROR; } SVN_ERR(svn_ra_get_repos_root(ra_session, &repos_url, subpool)); revs = apr_array_make(subpool, 2, sizeof(svn_revnum_t)); APR_ARRAY_PUSH(revs, svn_revnum_t) = start_revnum; if (end_revnum != start_revnum) APR_ARRAY_PUSH(revs, svn_revnum_t) = end_revnum; if (! (err = svn_ra_get_locations(ra_session, &rev_locs, "", peg_revnum, revs, subpool))) { start_path = apr_hash_get(rev_locs, &start_revnum, sizeof(svn_revnum_t)); end_path = apr_hash_get(rev_locs, &end_revnum, sizeof(svn_revnum_t)); } else if (err->apr_err == SVN_ERR_RA_NOT_IMPLEMENTED) { svn_error_clear(err); /* Do it the slow way for 1.0.x servers. */ SVN_ERR(slow_locations(&start_path, &end_path, svn_path_uri_decode(url + strlen(repos_url), subpool), peg_revnum, start_revnum, end_revnum, path, ra_session, ctx, subpool)); } else return err; /* We'd better have all the paths we were looking for! */ if (! start_path) return svn_error_createf (SVN_ERR_CLIENT_UNRELATED_RESOURCES, NULL, _("Unable to find repository location for '%s' in revision %ld"), path, start_revnum); if (! end_path) return svn_error_createf (SVN_ERR_CLIENT_UNRELATED_RESOURCES, NULL, _("The location for '%s' for revision %ld does not exist in the " "repository or refers to an unrelated object"), path, end_revnum); /* Repository paths might be absolute, but we want to treat them as relative. ### Aren't they always absolute? */ if (start_path[0] == '/') start_path = start_path + 1; if (end_path[0] == '/') end_path = end_path + 1; /* Set our return variables */ *start_url = svn_path_join(repos_url, svn_path_uri_encode(start_path, pool), pool); if (end->kind != svn_opt_revision_unspecified) *end_url = svn_path_join(repos_url, svn_path_uri_encode(end_path, pool), pool); svn_pool_destroy(subpool); return SVN_NO_ERROR;}svn_error_t *svn_client__ra_session_from_path(svn_ra_session_t **ra_session_p, svn_revnum_t *rev_p, const char **url_p, const char *path_or_url, const svn_opt_revision_t *peg_revision_p, const svn_opt_revision_t *revision, svn_client_ctx_t *ctx, apr_pool_t *pool){ svn_ra_session_t *ra_session; const char *initial_url, *url; const svn_opt_revision_t *good_rev; svn_opt_revision_t peg_revision, start_rev; svn_opt_revision_t dead_end_rev; svn_opt_revision_t *ignored_rev, *new_rev; svn_revnum_t rev; const char *ignored_url; SVN_ERR(svn_client_url_from_path(&initial_url, path_or_url, pool)); if (! initial_url) return svn_error_createf(SVN_ERR_ENTRY_MISSING_URL, NULL, _("'%s' has no URL"), path_or_url); /* If a peg revision was specified, but a desired revision was not, assume it is the same as the peg revision. */ if (revision->kind == svn_opt_revision_unspecified && peg_revision_p->kind != svn_opt_revision_unspecified) revision = peg_revision_p; if (svn_path_is_url(path_or_url)) { /* URLs get a default starting rev of HEAD. */ if (revision->kind == svn_opt_revision_unspecified) start_rev.kind = svn_opt_revision_head; else start_rev = *revision; /* If an explicit URL was passed in, the default peg revision is HEAD. */ if (peg_revision_p->kind == svn_opt_revision_unspecified) peg_revision.kind = svn_opt_revision_head; else peg_revision = *peg_revision_p; } else { /* And a default starting rev of BASE. */ if (revision->kind == svn_opt_revision_unspecified) start_rev.kind = svn_opt_revision_base; else start_rev = *revision; /* WC paths have a default peg revision of WORKING. */ if (peg_revision_p->kind == svn_opt_revision_unspecified) peg_revision.kind = svn_opt_revision_working; else peg_revision = *peg_revision_p; } SVN_ERR(svn_client__open_ra_session_internal(&ra_session, initial_url, NULL, NULL, NULL, FALSE, FALSE, ctx, pool)); dead_end_rev.kind = svn_opt_revision_unspecified; /* Run the history function to get the object's (possibly different) url in REVISION. */ SVN_ERR(svn_client__repos_locations(&url, &new_rev, &ignored_url, &ignored_rev, ra_session, path_or_url, &peg_revision, /* search range: */ &start_rev, &dead_end_rev, ctx, pool)); good_rev = new_rev; /* Make the session point to the real URL. */ SVN_ERR(svn_ra_reparent(ra_session, url, pool)); /* Resolve good_rev into a real revnum. */ SVN_ERR(svn_client__get_revision_number(&rev, ra_session, good_rev, url, pool)); if (! SVN_IS_VALID_REVNUM(rev)) SVN_ERR(svn_ra_get_latest_revnum(ra_session, &rev, pool)); *ra_session_p = ra_session; *rev_p = rev; *url_p = url; return SVN_NO_ERROR;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -