2 * revisions.c: discovering revisions
4 * ====================================================================
5 * Licensed to the Apache Software Foundation (ASF) under one
6 * or more contributor license agreements. See the NOTICE file
7 * distributed with this work for additional information
8 * regarding copyright ownership. The ASF licenses this file
9 * to you under the Apache License, Version 2.0 (the
10 * "License"); you may not use this file except in compliance
11 * with the License. You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing,
16 * software distributed under the License is distributed on an
17 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18 * KIND, either express or implied. See the License for the
19 * specific language governing permissions and limitations
21 * ====================================================================
26 #include <apr_pools.h>
28 #include "svn_error.h"
30 #include "svn_dirent_uri.h"
34 #include "svn_private_config.h"
35 #include "private/svn_wc_private.h"
41 svn_client__get_revision_number(svn_revnum_t *revnum,
42 svn_revnum_t *youngest_rev,
43 svn_wc_context_t *wc_ctx,
44 const char *local_abspath,
45 svn_ra_session_t *ra_session,
46 const svn_opt_revision_t *revision,
47 apr_pool_t *scratch_pool)
49 switch (revision->kind)
51 case svn_opt_revision_unspecified:
52 *revnum = SVN_INVALID_REVNUM;
55 case svn_opt_revision_number:
56 *revnum = revision->value.number;
59 case svn_opt_revision_head:
60 /* If our caller provided a value for HEAD that he wants us to
61 use, we'll use it. Otherwise, we have to query the
62 repository (and possible return our fetched value in
63 *YOUNGEST_REV, too). */
64 if (youngest_rev && SVN_IS_VALID_REVNUM(*youngest_rev))
66 *revnum = *youngest_rev;
71 return svn_error_create(SVN_ERR_CLIENT_RA_ACCESS_REQUIRED,
73 SVN_ERR(svn_ra_get_latest_revnum(ra_session, revnum, scratch_pool));
75 *youngest_rev = *revnum;
79 case svn_opt_revision_working:
80 case svn_opt_revision_base:
85 if (local_abspath == NULL)
86 return svn_error_create(SVN_ERR_CLIENT_VERSIONED_PATH_REQUIRED,
89 /* The BASE, COMMITTED, and PREV revision keywords do not
91 if (svn_path_is_url(local_abspath))
94 err = svn_wc__node_get_origin(NULL, revnum, NULL, NULL, NULL, NULL,
96 wc_ctx, local_abspath, TRUE,
97 scratch_pool, scratch_pool);
99 /* Return the same error as older code did (before and at r935091).
100 At least svn_client_proplist4 promises SVN_ERR_ENTRY_NOT_FOUND. */
101 if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
103 svn_error_clear(err);
104 return svn_error_createf(SVN_ERR_ENTRY_NOT_FOUND, NULL,
105 _("'%s' is not under version control"),
106 svn_dirent_local_style(local_abspath,
112 if (! SVN_IS_VALID_REVNUM(*revnum))
113 return svn_error_createf(SVN_ERR_CLIENT_BAD_REVISION, NULL,
114 _("Path '%s' has no committed "
116 svn_dirent_local_style(local_abspath,
121 case svn_opt_revision_committed:
122 case svn_opt_revision_previous:
125 if (local_abspath == NULL)
126 return svn_error_create(SVN_ERR_CLIENT_VERSIONED_PATH_REQUIRED,
129 /* The BASE, COMMITTED, and PREV revision keywords do not
131 if (svn_path_is_url(local_abspath))
132 goto invalid_rev_arg;
134 SVN_ERR(svn_wc__node_get_changed_info(revnum, NULL, NULL,
135 wc_ctx, local_abspath,
136 scratch_pool, scratch_pool));
137 if (! SVN_IS_VALID_REVNUM(*revnum))
138 return svn_error_createf(SVN_ERR_CLIENT_BAD_REVISION, NULL,
139 _("Path '%s' has no committed "
141 svn_dirent_local_style(local_abspath,
144 if (revision->kind == svn_opt_revision_previous)
149 case svn_opt_revision_date:
150 /* ### When revision->kind == svn_opt_revision_date, is there an
151 ### optimization such that we can compare
152 ### revision->value->date with the committed-date in the
153 ### entries file (or rather, with some range of which
154 ### committed-date is one endpoint), and sometimes avoid a
155 ### trip over the RA layer? The only optimizations I can
156 ### think of involve examining other entries to build a
157 ### timespan across which committed-revision is known to be
158 ### the head, but it doesn't seem worth it. -kff */
160 return svn_error_create(SVN_ERR_CLIENT_RA_ACCESS_REQUIRED, NULL, NULL);
161 SVN_ERR(svn_ra_get_dated_revision(ra_session, revnum,
162 revision->value.date, scratch_pool));
166 return svn_error_createf(SVN_ERR_CLIENT_BAD_REVISION, NULL,
167 _("Unrecognized revision type requested for "
169 svn_dirent_local_style(local_abspath,
173 /* Final check -- if our caller provided a youngest revision, and
174 the number we wound up with (after talking to the server) is younger
175 than that revision, we need to stick to our caller's idea of "youngest".
178 && (revision->kind == svn_opt_revision_head
179 || revision->kind == svn_opt_revision_date)
180 && SVN_IS_VALID_REVNUM(*youngest_rev)
181 && SVN_IS_VALID_REVNUM(*revnum)
182 && (*revnum > *youngest_rev))
183 *revnum = *youngest_rev;
188 return svn_error_create(
189 SVN_ERR_CLIENT_BAD_REVISION, NULL,
190 _("PREV, BASE, or COMMITTED revision keywords are invalid for URL"));