📄 ra.c
字号:
pegrev_is_youngest = TRUE;
}
else if (end_revnum > peg_revnum)
{
if (end_revnum >= start_revnum)
{
youngest = end_revnum;
*end_path = lrb.last_path;
}
else
{
youngest = start_revnum;
*start_path = lrb.last_path;
}
}
else /* start_revnum > peg_revnum */
{
if (start_revnum >= end_revnum)
{
youngest = start_revnum;
*start_path = lrb.last_path;
}
else
{
youngest = end_revnum;
*end_path = lrb.last_path;
}
}
/* 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 (ra_lib->get_log (ra_session, targets, youngest, 1,
TRUE, FALSE, log_receiver, &lrb, pool));
/* 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,
const char *path,
const svn_opt_revision_t *revision,
const svn_opt_revision_t *start,
const svn_opt_revision_t *end,
svn_ra_plugin_t *ra_lib,
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;
void *ra_session;
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_open2 (&adm_access, NULL, path,
FALSE, 0, 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;
}
else if (entry->url)
{
url = entry->url;
}
else
{
return svn_error_createf (SVN_ERR_ENTRY_MISSING_URL, NULL,
_("'%s' has no URL"), path);
}
}
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. */
SVN_ERR (svn_client__open_ra_session (&ra_session, ra_lib, 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_lib,
ra_session, revision, path,
pool));
SVN_ERR (svn_client__get_revision_number (&start_revnum, ra_lib,
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_lib,
ra_session, end, path, pool));
SVN_ERR (ra_lib->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 = ra_lib->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_lib, 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
(APR_EGENERAL, NULL,
_("Unable to find repository location for '%s' in revision %ld"),
path, start_revnum);
if (! end_path)
return svn_error_createf
(APR_EGENERAL, 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);
*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_url = svn_path_join (repos_url, svn_path_uri_encode (end_path,
pool), pool);
*end_revision = apr_pcalloc (pool, sizeof (**end_revision));
(*end_revision)->kind = svn_opt_revision_number;
(*end_revision)->value.number = end_revnum;
}
svn_pool_destroy (subpool);
return SVN_NO_ERROR;
}
svn_error_t *
svn_client__ra_lib_from_path (svn_ra_plugin_t **ra_lib_p,
void **session_p,
svn_revnum_t *rev_p,
const char **url_p,
const char *path_or_url,
const svn_opt_revision_t *revision,
svn_client_ctx_t *ctx,
apr_pool_t *pool)
{
const char *initial_url, *url;
void *ra_baton, *session;
svn_ra_plugin_t *ra_lib;
const svn_opt_revision_t *good_rev;
svn_revnum_t rev;
/* Get an RA library for the incoming path. */
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);
SVN_ERR (svn_ra_init_ra_libs (&ra_baton, pool));
SVN_ERR (svn_ra_get_ra_library (&ra_lib, ra_baton, initial_url, pool));
if (svn_path_is_url (path_or_url))
{
/* If an explicit URL was passed in, just use it. */
good_rev = revision;
url = initial_url;
}
else
{
/* For a working copy path, don't blindly use its initial_url
from the entries file. Run the history function to get the
object's (possibly different) url in REVISION. */
svn_opt_revision_t base_rev, dead_end_rev, start_rev;
svn_opt_revision_t *ignored_rev, *new_rev;
const char *ignored_url;
dead_end_rev.kind = svn_opt_revision_unspecified;
base_rev.kind = svn_opt_revision_working;
if (revision->kind == svn_opt_revision_unspecified)
start_rev.kind = svn_opt_revision_base;
else
start_rev = *revision;
SVN_ERR (svn_client__repos_locations (&url, &new_rev,
&ignored_url, &ignored_rev,
/* peg coords are path@BASE: */
path_or_url, &base_rev,
/* search range: */
&start_rev, &dead_end_rev,
ra_lib, ctx, pool));
good_rev = new_rev;
}
SVN_ERR (svn_client__open_ra_session (&session, ra_lib, url,
NULL, NULL, NULL, FALSE, FALSE,
ctx, pool));
/* Resolve good_rev into a real revnum. */
SVN_ERR (svn_client__get_revision_number (&rev, ra_lib, session,
good_rev, url, pool));
if (! SVN_IS_VALID_REVNUM (rev))
SVN_ERR (ra_lib->get_latest_revnum (session, &rev, pool));
*ra_lib_p = ra_lib;
*session_p = session;
*rev_p = rev;
*url_p = url;
return SVN_NO_ERROR;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -