]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/subversion/subversion/libsvn_client/revisions.c
Update Subversion and dependencies to 1.14.0 LTS.
[FreeBSD/FreeBSD.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           return svn_error_create(SVN_ERR_CLIENT_BAD_REVISION, NULL,
93                                   _("PREV, BASE, or COMMITTED revision "
94                                     "keywords are invalid for URL"));
95
96         err = svn_wc__node_get_origin(NULL, revnum, NULL, NULL, NULL, NULL,
97                                       NULL,
98                                       wc_ctx, local_abspath, TRUE,
99                                       scratch_pool, scratch_pool);
100
101         /* Return the same error as older code did (before and at r935091).
102            At least svn_client_proplist4 promises SVN_ERR_ENTRY_NOT_FOUND. */
103         if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
104           {
105             svn_error_clear(err);
106             return svn_error_createf(SVN_ERR_ENTRY_NOT_FOUND, NULL,
107                                      _("'%s' is not under version control"),
108                                      svn_dirent_local_style(local_abspath,
109                                                             scratch_pool));
110           }
111         else
112           SVN_ERR(err);
113
114         if (! SVN_IS_VALID_REVNUM(*revnum))
115           return svn_error_createf(SVN_ERR_CLIENT_BAD_REVISION, NULL,
116                                    _("Path '%s' has no committed "
117                                      "revision"),
118                                    svn_dirent_local_style(local_abspath,
119                                                           scratch_pool));
120       }
121       break;
122
123     case svn_opt_revision_committed:
124     case svn_opt_revision_previous:
125       {
126         /* Sanity check. */
127         if (local_abspath == NULL)
128           return svn_error_create(SVN_ERR_CLIENT_VERSIONED_PATH_REQUIRED,
129                                   NULL, NULL);
130
131         /* The BASE, COMMITTED, and PREV revision keywords do not
132            apply to URLs. */
133         if (svn_path_is_url(local_abspath))
134           return svn_error_create(SVN_ERR_CLIENT_BAD_REVISION, NULL,
135                                   _("PREV, BASE, or COMMITTED revision "
136                                     "keywords are invalid for URL"));
137
138         SVN_ERR(svn_wc__node_get_changed_info(revnum, NULL, NULL,
139                                               wc_ctx, local_abspath,
140                                               scratch_pool, scratch_pool));
141         if (! SVN_IS_VALID_REVNUM(*revnum))
142           return svn_error_createf(SVN_ERR_CLIENT_BAD_REVISION, NULL,
143                                    _("Path '%s' has no committed "
144                                      "revision"),
145                                    svn_dirent_local_style(local_abspath,
146                                                           scratch_pool));
147
148         if (revision->kind == svn_opt_revision_previous)
149           {
150             if (*revnum == 0)
151               return svn_error_createf(
152                   SVN_ERR_CLIENT_BAD_REVISION, NULL,
153                   _("Path '%s' has no previous revision"),
154                   svn_dirent_local_style(local_abspath, scratch_pool));
155             --(*revnum);
156           }
157       }
158       break;
159
160     case svn_opt_revision_date:
161       /* ### When revision->kind == svn_opt_revision_date, is there an
162          ### optimization such that we can compare
163          ### revision->value->date with the committed-date in the
164          ### entries file (or rather, with some range of which
165          ### committed-date is one endpoint), and sometimes avoid a
166          ### trip over the RA layer?  The only optimizations I can
167          ### think of involve examining other entries to build a
168          ### timespan across which committed-revision is known to be
169          ### the head, but it doesn't seem worth it.  -kff */
170       if (! ra_session)
171         return svn_error_create(SVN_ERR_CLIENT_RA_ACCESS_REQUIRED, NULL, NULL);
172       SVN_ERR(svn_ra_get_dated_revision(ra_session, revnum,
173                                         revision->value.date, scratch_pool));
174       break;
175
176     default:
177       return svn_error_createf(SVN_ERR_CLIENT_BAD_REVISION, NULL,
178                                _("Unrecognized revision type requested for "
179                                  "'%s'"),
180                                svn_dirent_local_style(local_abspath,
181                                                       scratch_pool));
182     }
183
184   /* Final check -- if our caller provided a youngest revision, and
185      the number we wound up with (after talking to the server) is younger
186      than that revision, we need to stick to our caller's idea of "youngest".
187    */
188   if (youngest_rev
189       && (revision->kind == svn_opt_revision_head
190           || revision->kind == svn_opt_revision_date)
191       && SVN_IS_VALID_REVNUM(*youngest_rev)
192       && SVN_IS_VALID_REVNUM(*revnum)
193       && (*revnum > *youngest_rev))
194     *revnum = *youngest_rev;
195
196   return SVN_NO_ERROR;
197 }