2
2
* version.c: mod_dav_svn versioning provider functions for Subversion
4
4
* ====================================================================
5
* Copyright (c) 2000-2007 CollabNet. All rights reserved.
7
* This software is licensed as described in the file COPYING, which
8
* you should have received as part of this distribution. The terms
9
* are also available at http://subversion.tigris.org/license-1.html.
10
* If newer versions of this license are posted there, you may use a
11
* newer version instead, at your option.
13
* This software consists of voluntary contributions made by many
14
* individuals. For exact contribution history, see the revision
15
* history and logs, available at http://subversion.tigris.org/.
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
16
21
* ====================================================================
80
86
if (! (resource->type == DAV_RESOURCE_TYPE_WORKING
81
87
&& resource->info->auto_checked_out))
82
return dav_new_error(resource->pool, HTTP_INTERNAL_SERVER_ERROR, 0,
83
"Set_auto_revprops called on invalid resource.");
88
return dav_svn__new_error(resource->pool, HTTP_INTERNAL_SERVER_ERROR, 0,
89
"Set_auto_revprops called on invalid resource.");
85
91
if ((serr = dav_svn__attach_auto_revprops(resource->info->root.txn,
86
92
resource->info->repos_path,
138
144
/* Send SVN_RA_CAPABILITY_* capabilities. */
139
145
apr_text_append(p, phdr, SVN_DAV_NS_DAV_SVN_DEPTH);
140
146
apr_text_append(p, phdr, SVN_DAV_NS_DAV_SVN_LOG_REVPROPS);
147
apr_text_append(p, phdr, SVN_DAV_NS_DAV_SVN_ATOMIC_REVPROPS);
141
148
apr_text_append(p, phdr, SVN_DAV_NS_DAV_SVN_PARTIAL_REPLAY);
142
149
/* Mergeinfo is a special case: here we merely say that the server
143
150
* knows how to handle mergeinfo -- whether the repository does too
162
169
const apr_xml_elem *elem,
163
170
apr_text_header *option)
172
request_rec *r = resource->info->r;
173
const char *repos_root_uri =
174
dav_svn__build_uri(resource->info->repos, DAV_SVN__BUILD_URI_PUBLIC,
175
SVN_IGNORED_REVNUM, "", 0, resource->pool);
165
177
/* ### DAV:version-history-collection-set */
167
178
if (elem->ns == APR_XML_NS_DAV_ID)
169
180
if (strcmp(elem->name, "activity-collection-set") == 0)
195
if (resource->info->repos->fs)
198
svn_revnum_t youngest;
201
/* Got youngest revision? */
202
if ((serr = svn_fs_youngest_rev(&youngest, resource->info->repos->fs,
205
return dav_svn__convert_err
206
(serr, HTTP_INTERNAL_SERVER_ERROR,
207
"Error fetching youngest revision from repository",
210
if (SVN_IS_VALID_REVNUM(youngest))
212
apr_table_set(r->headers_out,
213
SVN_DAV_YOUNGEST_REV_HEADER,
214
apr_psprintf(resource->pool, "%ld", youngest));
217
/* Got repository UUID? */
218
if ((serr = svn_fs_get_uuid(resource->info->repos->fs,
219
&uuid, resource->pool)))
221
return dav_svn__convert_err
222
(serr, HTTP_INTERNAL_SERVER_ERROR,
223
"Error fetching repository UUID",
228
apr_table_set(r->headers_out,
229
SVN_DAV_REPOS_UUID_HEADER, uuid);
233
/* Welcome to the 2nd generation of the svn HTTP protocol, now
234
DeltaV-free! If we're configured to advise this support, do so. */
235
if (resource->info->repos->v2_protocol)
237
apr_table_set(r->headers_out, SVN_DAV_ROOT_URI_HEADER, repos_root_uri);
238
apr_table_set(r->headers_out, SVN_DAV_ME_RESOURCE_HEADER,
239
apr_pstrcat(resource->pool, repos_root_uri, "/",
240
dav_svn__get_me_resource_uri(r), (char *)NULL));
241
apr_table_set(r->headers_out, SVN_DAV_REV_ROOT_STUB_HEADER,
242
apr_pstrcat(resource->pool, repos_root_uri, "/",
243
dav_svn__get_rev_root_stub(r), (char *)NULL));
244
apr_table_set(r->headers_out, SVN_DAV_REV_STUB_HEADER,
245
apr_pstrcat(resource->pool, repos_root_uri, "/",
246
dav_svn__get_rev_stub(r), (char *)NULL));
247
apr_table_set(r->headers_out, SVN_DAV_TXN_ROOT_STUB_HEADER,
248
apr_pstrcat(resource->pool, repos_root_uri, "/",
249
dav_svn__get_txn_root_stub(r), (char *)NULL));
250
apr_table_set(r->headers_out, SVN_DAV_TXN_STUB_HEADER,
251
apr_pstrcat(resource->pool, repos_root_uri, "/",
252
dav_svn__get_txn_stub(r), (char *)NULL));
253
apr_table_set(r->headers_out, SVN_DAV_VTXN_ROOT_STUB_HEADER,
254
apr_pstrcat(resource->pool, repos_root_uri, "/",
255
dav_svn__get_vtxn_root_stub(r), (char *)NULL));
256
apr_table_set(r->headers_out, SVN_DAV_VTXN_STUB_HEADER,
257
apr_pstrcat(resource->pool, repos_root_uri, "/",
258
dav_svn__get_vtxn_stub(r), (char *)NULL));
232
309
/* All mod_dav_svn resources are versioned objects; so it doesn't
233
310
make sense to call vsn_control on a resource that exists . */
234
311
if (resource->exists)
235
return dav_new_error(resource->pool, HTTP_BAD_REQUEST, 0,
236
"vsn_control called on already-versioned resource.");
312
return dav_svn__new_error(resource->pool, HTTP_BAD_REQUEST, 0,
313
"vsn_control called on already-versioned "
238
316
/* Only allow a NULL target, which means an create an 'empty' VCR. */
239
317
if (target != NULL)
345
421
shared_txn_name = dav_svn__get_txn(resource->info->repos,
346
422
shared_activity);
347
423
if (! shared_txn_name)
348
return dav_new_error(resource->pool, HTTP_INTERNAL_SERVER_ERROR, 0,
349
"Cannot look up a txn_name by activity");
424
return dav_svn__new_error(resource->pool,
425
HTTP_INTERNAL_SERVER_ERROR, 0,
426
"Cannot look up a txn_name by activity");
352
429
/* Tweak the VCR in-place, making it into a WR. (Ignore the
353
430
NULL return value.) */
354
res = dav_svn__create_working_resource(resource,
355
shared_activity, shared_txn_name,
356
TRUE /* tweak in place */);
431
dav_svn__create_working_resource(resource,
432
shared_activity, shared_txn_name,
433
TRUE /* tweak in place */);
358
435
/* Remember that this resource was auto-checked-out, so that
359
436
auto_versionable allows us to do an auto-checkin and
821
898
shared_txn_name = dav_svn__get_txn(resource->info->repos,
822
899
shared_activity);
823
900
if (! shared_txn_name)
824
return dav_new_error(resource->pool, HTTP_INTERNAL_SERVER_ERROR, 0,
825
"Cannot look up a txn_name by activity");
901
return dav_svn__new_error(resource->pool, HTTP_INTERNAL_SERVER_ERROR, 0,
902
"Cannot look up a txn_name by activity");
827
904
/* Sanity checks */
828
905
if (resource->info->root.txn_name
829
906
&& (strcmp(shared_txn_name, resource->info->root.txn_name) != 0))
830
return dav_new_error(resource->pool, HTTP_INTERNAL_SERVER_ERROR, 0,
831
"Internal txn_name doesn't match"
832
" autoversioning transaction.");
907
return dav_svn__new_error(resource->pool, HTTP_INTERNAL_SERVER_ERROR, 0,
908
"Internal txn_name doesn't match "
909
"autoversioning transaction.");
834
911
if (! resource->info->root.txn)
835
912
/* should already be open by checkout */
836
return dav_new_error(resource->pool, HTTP_INTERNAL_SERVER_ERROR, 0,
837
"Autoversioning txn isn't open "
838
"when it should be.");
913
return dav_svn__new_error(resource->pool, HTTP_INTERNAL_SERVER_ERROR, 0,
914
"Autoversioning txn isn't open "
915
"when it should be.");
840
917
err = set_auto_revprops(resource);
1294
1370
/* ### what to verify on the target? */
1296
1372
/* ### anything else for the source? */
1297
if (source->type != DAV_RESOURCE_TYPE_ACTIVITY)
1373
if (! (source->type == DAV_RESOURCE_TYPE_ACTIVITY
1374
|| (source->type == DAV_RESOURCE_TYPE_PRIVATE
1375
&& source->info->restype == DAV_SVN_RESTYPE_TXN_COLLECTION)))
1299
1377
return dav_svn__new_error_tag(pool, HTTP_METHOD_NOT_ALLOWED,
1300
1378
SVN_ERR_INCORRECT_PARAMS,
1301
1379
"MERGE can only be performed using an "
1302
"activity as the source [at this time].",
1380
"activity or transaction resource as the "
1382
SVN_DAV_ERROR_NAMESPACE,
1385
if (! source->exists)
1387
return dav_svn__new_error_tag(pool, HTTP_METHOD_NOT_ALLOWED,
1388
SVN_ERR_INCORRECT_PARAMS,
1389
"MERGE activity or transaction resource "
1303
1391
SVN_DAV_ERROR_NAMESPACE,
1304
1392
SVN_DAV_ERROR_TAG);
1394
1488
svn_log__commit(new_rev, target->info->r->pool));
1396
1490
/* Since the commit was successful, the txn ID is no longer valid.
1397
Store an empty txn ID in the activity database so that when the
1398
client deletes the activity, we don't try to open and abort the
1400
err = dav_svn__store_activity(source->info->repos,
1401
source->info->root.activity_id, "");
1491
If we're using activities, store an empty txn ID in the activity
1492
database so that when the client deletes the activity, we don't
1493
try to open and abort the transaction. */
1494
if (source->type == DAV_RESOURCE_TYPE_ACTIVITY)
1496
err = dav_svn__store_activity(source->info->repos,
1497
source->info->root.activity_id, "");
1405
1502
/* Check the dav_resource->info area for information about the
1406
1503
special X-SVN-Options: header that may have come in the http