]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/subversion/subversion/libsvn_client/revisions.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / subversion / subversion / libsvn_client / revisions.c
1 /*
2  * revisions.c:  discovering revisions
3  *
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
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
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
20  *    under the License.
21  * ====================================================================
22  */
23
24
25 \f
26 #include <apr_pools.h>
27
28 #include "svn_error.h"
29 #include "svn_ra.h"
30 #include "svn_dirent_uri.h"
31 #include "svn_path.h"
32 #include "client.h"
33
34 #include "svn_private_config.h"
35 #include "private/svn_wc_private.h"
36
37 \f
38
39
40 svn_error_t *
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)
48 {
49   switch (revision->kind)
50     {
51     case svn_opt_revision_unspecified:
52       *revnum = SVN_INVALID_REVNUM;
53       break;
54
55     case svn_opt_revision_number:
56       *revnum = revision->value.number;
57       break;
58
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))
65         {
66           *revnum = *youngest_rev;
67         }
68       else
69         {
70           if (! ra_session)
71             return svn_error_create(SVN_ERR_CLIENT_RA_ACCESS_REQUIRED,
72                                     NULL, NULL);
73           SVN_ERR(svn_ra_get_latest_revnum(ra_session, revnum, scratch_pool));
74           if (youngest_rev)
75             *youngest_rev = *revnum;
76         }
77       break;
78
79     case svn_opt_revision_working:
80     case svn_opt_revision_base:
81       {
82         svn_error_t *err;
83
84         /* Sanity check. */
85         if (local_abspath == NULL)
86           return svn_error_create(SVN_ERR_CLIENT_VERSIONED_PATH_REQUIRED,
87                                   NULL, NULL);
88
89         /* The BASE, COMMITTED, and PREV revision keywords do not
90            apply to URLs. */
91         if (svn_path_is_url(local_abspath))
92           goto invalid_rev_arg;
93
94         err = svn_wc__node_get_origin(NULL, revnum, NULL, NULL, NULL, NULL,
95                                       wc_ctx, local_abspath, TRUE,
96                                       scratch_pool, scratch_pool);
97
98         /* Return the same error as older code did (before and at r935091).
99            At least svn_client_proplist4 promises SVN_ERR_ENTRY_NOT_FOUND. */
100         if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
101           {
102             svn_error_clear(err);
103             return svn_error_createf(SVN_ERR_ENTRY_NOT_FOUND, NULL,
104                                      _("'%s' is not under version control"),
105                                      svn_dirent_local_style(local_abspath,
106                                                             scratch_pool));
107           }
108         else
109           SVN_ERR(err);
110
111         if (! SVN_IS_VALID_REVNUM(*revnum))
112           return svn_error_createf(SVN_ERR_CLIENT_BAD_REVISION, NULL,
113                                    _("Path '%s' has no committed "
114                                      "revision"),
115                                    svn_dirent_local_style(local_abspath,
116                                                           scratch_pool));
117       }
118       break;
119
120     case svn_opt_revision_committed:
121     case svn_opt_revision_previous:
122       {
123         /* Sanity check. */
124         if (local_abspath == NULL)
125           return svn_error_create(SVN_ERR_CLIENT_VERSIONED_PATH_REQUIRED,
126                                   NULL, NULL);
127
128         /* The BASE, COMMITTED, and PREV revision keywords do not
129            apply to URLs. */
130         if (svn_path_is_url(local_abspath))
131           goto invalid_rev_arg;
132
133         SVN_ERR(svn_wc__node_get_changed_info(revnum, NULL, NULL,
134                                               wc_ctx, local_abspath,
135                                               scratch_pool, scratch_pool));
136         if (! SVN_IS_VALID_REVNUM(*revnum))
137           return svn_error_createf(SVN_ERR_CLIENT_BAD_REVISION, NULL,
138                                    _("Path '%s' has no committed "
139                                      "revision"),
140                                    svn_dirent_local_style(local_abspath,
141                                                           scratch_pool));
142
143         if (revision->kind == svn_opt_revision_previous)
144           (*revnum)--;
145       }
146       break;
147
148     case svn_opt_revision_date:
149       /* ### When revision->kind == svn_opt_revision_date, is there an
150          ### optimization such that we can compare
151          ### revision->value->date with the committed-date in the
152          ### entries file (or rather, with some range of which
153          ### committed-date is one endpoint), and sometimes avoid a
154          ### trip over the RA layer?  The only optimizations I can
155          ### think of involve examining other entries to build a
156          ### timespan across which committed-revision is known to be
157          ### the head, but it doesn't seem worth it.  -kff */
158       if (! ra_session)
159         return svn_error_create(SVN_ERR_CLIENT_RA_ACCESS_REQUIRED, NULL, NULL);
160       SVN_ERR(svn_ra_get_dated_revision(ra_session, revnum,
161                                         revision->value.date, scratch_pool));
162       break;
163
164     default:
165       return svn_error_createf(SVN_ERR_CLIENT_BAD_REVISION, NULL,
166                                _("Unrecognized revision type requested for "
167                                  "'%s'"),
168                                svn_dirent_local_style(local_abspath,
169                                                       scratch_pool));
170     }
171
172   /* Final check -- if our caller provided a youngest revision, and
173      the number we wound up with (after talking to the server) is younger
174      than that revision, we need to stick to our caller's idea of "youngest".
175    */
176   if (youngest_rev
177       && (revision->kind == svn_opt_revision_head
178           || revision->kind == svn_opt_revision_date)
179       && SVN_IS_VALID_REVNUM(*youngest_rev)
180       && SVN_IS_VALID_REVNUM(*revnum)
181       && (*revnum > *youngest_rev))
182     *revnum = *youngest_rev;
183
184   return SVN_NO_ERROR;
185
186   invalid_rev_arg:
187     return svn_error_create(
188       SVN_ERR_CLIENT_BAD_REVISION, NULL,
189       _("PREV, BASE, or COMMITTED revision keywords are invalid for URL"));
190
191 }