486
490
return APR_SUCCESS;
493
/* Calculate the new repos_relpath for a directory or file */
495
calculate_repos_relpath(const char **new_repos_relpath,
496
const char *local_abspath,
497
const char *old_repos_relpath,
498
struct edit_baton *eb,
499
struct dir_baton *pb,
500
apr_pool_t *result_pool,
501
apr_pool_t *scratch_pool)
503
const char *name = svn_dirent_basename(local_abspath, NULL);
505
/* Figure out the new_repos_relpath for this directory. */
506
if (eb->switch_repos_relpath)
508
/* Handle switches... */
512
if (*eb->target_basename == '\0')
514
/* No parent baton and target_basename=="" means that we are
515
the target of the switch. Thus, our new_repos_relpath will be
516
the switch_repos_relpath. */
517
*new_repos_relpath = eb->switch_repos_relpath;
521
/* This node is NOT the target of the switch (one of our
522
children is the target); therefore, it must already exist.
523
Get its old REPOS_RELPATH, as it won't be changing. */
524
*new_repos_relpath = apr_pstrdup(result_pool, old_repos_relpath);
529
/* This directory is *not* the root (has a parent). If there is
530
no grandparent, then we may have anchored at the parent,
531
and self is the target. If we match the target, then set
532
new_repos_relpath to the switch_repos_relpath.
534
Otherwise, we simply extend new_repos_relpath from the parent. */
536
if (pb->parent_baton == NULL
537
&& strcmp(eb->target_basename, name) == 0)
538
*new_repos_relpath = eb->switch_repos_relpath;
540
*new_repos_relpath = svn_relpath_join(pb->new_repos_relpath, name,
544
else /* must be an update */
546
/* If we are adding the node, then simply extend the parent's
547
relpath for our own. */
548
if (old_repos_relpath == NULL)
550
SVN_ERR_ASSERT(pb != NULL);
551
*new_repos_relpath = svn_relpath_join(pb->new_repos_relpath, name,
556
*new_repos_relpath = apr_pstrdup(result_pool, old_repos_relpath);
489
563
/* Make a new dir baton in a subpool of PB->pool. PB is the parent baton.
490
564
If PATH and PB are NULL, this is the root directory of the edit; in this
491
565
case, make the new dir baton in a subpool of EB->pool.
525
599
d->local_abspath = eb->anchor_abspath;
528
/* Figure out the new_relpath for this directory. */
529
if (eb->switch_relpath)
531
/* Handle switches... */
535
if (*eb->target_basename == '\0')
537
/* No parent baton and target_basename=="" means that we are
538
the target of the switch. Thus, our NEW_RELPATH will be
539
the SWITCH_RELPATH. */
540
d->new_relpath = eb->switch_relpath;
544
/* This node is NOT the target of the switch (one of our
545
children is the target); therefore, it must already exist.
546
Get its old REPOS_RELPATH, as it won't be changing. */
547
SVN_ERR(svn_wc__db_scan_base_repos(&d->new_relpath, NULL, NULL,
548
eb->db, d->local_abspath,
549
dir_pool, scratch_pool));
554
/* This directory is *not* the root (has a parent). If there is
555
no grandparent, then we may have anchored at the parent,
556
and self is the target. If we match the target, then set
557
NEW_RELPATH to the SWITCH_RELPATH.
559
Otherwise, we simply extend NEW_RELPATH from the parent. */
560
if (pb->parent_baton == NULL
561
&& strcmp(eb->target_basename, d->name) == 0)
562
d->new_relpath = eb->switch_relpath;
564
d->new_relpath = svn_relpath_join(pb->new_relpath, d->name,
568
else /* must be an update */
570
/* If we are adding the node, then simply extend the parent's
571
relpath for our own. */
574
SVN_ERR_ASSERT(pb != NULL);
575
d->new_relpath = svn_relpath_join(pb->new_relpath, d->name,
580
SVN_ERR(svn_wc__db_scan_base_repos(&d->new_relpath, NULL, NULL,
581
eb->db, d->local_abspath,
582
dir_pool, scratch_pool));
583
SVN_ERR_ASSERT(d->new_relpath);
587
602
d->edit_baton = eb;
588
603
d->parent_baton = pb;
589
604
d->pool = dir_pool;
776
789
SVN_ERR(path_join_under_root(&f->local_abspath,
777
790
pb->local_abspath, f->name, file_pool));
779
/* Figure out the new URL for this file. */
780
if (eb->switch_relpath)
782
/* Handle switches... */
784
/* This file has a parent directory. If there is
785
no grandparent, then we may have anchored at the parent,
786
and self is the target. If we match the target, then set
787
NEW_RELPATH to the SWITCH_RELPATH.
789
Otherwise, we simply extend NEW_RELPATH from the parent. */
790
if (pb->parent_baton == NULL
791
&& strcmp(eb->target_basename, f->name) == 0)
792
f->new_relpath = eb->switch_relpath;
794
f->new_relpath = svn_relpath_join(pb->new_relpath, f->name,
797
else /* must be an update */
800
f->new_relpath = svn_relpath_join(pb->new_relpath, f->name, file_pool);
803
SVN_ERR(svn_wc__db_scan_base_repos(&f->new_relpath, NULL, NULL,
804
eb->db, f->local_abspath,
805
file_pool, scratch_pool));
806
SVN_ERR_ASSERT(f->new_relpath);
810
792
f->pool = file_pool;
811
793
f->edit_baton = pb->edit_baton;
812
794
f->propchanges = apr_array_make(file_pool, 1, sizeof(svn_prop_t));
843
825
const char *new_repos_relpath,
844
826
svn_node_kind_t local_kind,
845
827
svn_node_kind_t target_kind,
828
const svn_skel_t *delete_conflict,
846
829
apr_pool_t *result_pool,
847
830
apr_pool_t *scratch_pool)
849
svn_wc_conflict_version_t *original_version;
832
const svn_wc_conflict_version_t *original_version = NULL;
850
833
svn_wc_conflict_version_t *target_version;
851
834
svn_boolean_t is_complete;
836
SVN_ERR_ASSERT(new_repos_relpath);
854
839
return SVN_NO_ERROR; /* Not conflicted */
869
original_version = NULL;
871
if (new_repos_relpath)
872
target_version = svn_wc_conflict_version_create2(eb->repos_root,
875
*eb->target_revision,
879
target_version = NULL;
881
if (eb->switch_relpath)
853
else if (delete_conflict)
855
const apr_array_header_t *locations;
857
SVN_ERR(svn_wc__conflict_read_info(NULL, &locations, NULL, NULL, NULL,
858
eb->db, local_abspath,
860
scratch_pool, scratch_pool));
864
original_version = APR_ARRAY_IDX(locations, 0,
865
const svn_wc_conflict_version_t *);
869
target_version = svn_wc_conflict_version_create2(eb->repos_root,
872
*eb->target_revision,
876
if (eb->switch_repos_relpath)
882
877
SVN_ERR(svn_wc__conflict_skel_set_op_switch(conflict,
883
878
original_version,
949
944
SVN_ERR(complete_conflict(fb->edit_conflict, fb->edit_baton,
950
945
fb->local_abspath, fb->old_repos_relpath,
951
fb->old_revision, fb->new_relpath,
946
fb->old_revision, fb->new_repos_relpath,
952
947
svn_node_file, svn_node_file,
953
949
fb->pool, scratch_pool));
955
951
SVN_ERR(svn_wc__db_op_mark_conflict(fb->edit_baton->db,
1228
1212
eb->db, db->local_abspath,
1229
1213
db->pool, pool));
1217
SVN_ERR(svn_wc__db_base_get_info(&base_status, NULL,
1219
&db->old_repos_relpath, NULL, NULL,
1220
&db->changed_rev, &db->changed_date,
1221
&db->changed_author,
1223
NULL, NULL, NULL, NULL, NULL, NULL,
1224
eb->db, db->local_abspath,
1228
base_status = status;
1230
SVN_ERR(calculate_repos_relpath(&db->new_repos_relpath, db->local_abspath,
1231
db->old_repos_relpath, eb, NULL,
1231
1234
if (conflict_ignored)
1233
db->shadowed = TRUE;
1235
db->shadowed = TRUE;
1235
1236
else if (have_work)
1237
1238
const char *move_src_root_abspath;
1239
1240
SVN_ERR(svn_wc__db_base_moved_to(NULL, NULL, &move_src_root_abspath,
1240
1241
NULL, eb->db, db->local_abspath,
1242
if (move_src_root_abspath || *eb->target_basename == '\0')
1243
SVN_ERR(svn_wc__db_base_get_info(&base_status, NULL,
1245
&db->old_repos_relpath, NULL, NULL,
1246
&db->changed_rev, &db->changed_date,
1247
&db->changed_author,
1249
NULL, NULL, NULL, NULL, NULL, NULL,
1250
eb->db, db->local_abspath,
1253
1244
if (move_src_root_abspath)
1320
1310
/* ===================================================================== */
1321
1311
/* Checking for local modifications. */
1323
/* A baton for use with modcheck_found_entry(). */
1324
typedef struct modcheck_baton_t {
1325
svn_wc__db_t *db; /* wc_db to access nodes */
1326
svn_boolean_t found_mod; /* whether a modification has been found */
1327
svn_boolean_t found_not_delete; /* Found a not-delete modification */
1330
/* An implementation of svn_wc_status_func4_t. */
1331
static svn_error_t *
1332
modcheck_callback(void *baton,
1333
const char *local_abspath,
1334
const svn_wc_status3_t *status,
1335
apr_pool_t *scratch_pool)
1337
modcheck_baton_t *mb = baton;
1339
switch (status->node_status)
1341
case svn_wc_status_normal:
1342
case svn_wc_status_incomplete:
1343
case svn_wc_status_ignored:
1344
case svn_wc_status_none:
1345
case svn_wc_status_unversioned:
1346
case svn_wc_status_external:
1349
case svn_wc_status_deleted:
1350
mb->found_mod = TRUE;
1353
case svn_wc_status_missing:
1354
case svn_wc_status_obstructed:
1355
mb->found_mod = TRUE;
1356
mb->found_not_delete = TRUE;
1357
/* Exit from the status walker: We know what we want to know */
1358
return svn_error_create(SVN_ERR_CEASE_INVOCATION, NULL, NULL);
1361
case svn_wc_status_added:
1362
case svn_wc_status_replaced:
1363
case svn_wc_status_modified:
1364
mb->found_mod = TRUE;
1365
mb->found_not_delete = TRUE;
1366
/* Exit from the status walker: We know what we want to know */
1367
return svn_error_create(SVN_ERR_CEASE_INVOCATION, NULL, NULL);
1370
return SVN_NO_ERROR;
1374
/* Set *MODIFIED to true iff there are any local modifications within the
1375
* tree rooted at LOCAL_ABSPATH, using DB. If *MODIFIED
1376
* is set to true and all the local modifications were deletes then set
1377
* *ALL_EDITS_ARE_DELETES to true, set it to false otherwise. LOCAL_ABSPATH
1378
* may be a file or a directory. */
1380
svn_wc__node_has_local_mods(svn_boolean_t *modified,
1381
svn_boolean_t *all_edits_are_deletes,
1383
const char *local_abspath,
1384
svn_cancel_func_t cancel_func,
1386
apr_pool_t *scratch_pool)
1388
modcheck_baton_t modcheck_baton = { NULL, FALSE, FALSE };
1391
modcheck_baton.db = db;
1393
/* Walk the WC tree for status with depth infinity, looking for any local
1394
* modifications. If it's a "sparse" directory, that's OK: there can be
1395
* no local mods in the pieces that aren't present in the WC. */
1397
err = svn_wc__internal_walk_status(db, local_abspath,
1399
FALSE, FALSE, FALSE, NULL,
1400
modcheck_callback, &modcheck_baton,
1401
cancel_func, cancel_baton,
1404
if (err && err->apr_err == SVN_ERR_CEASE_INVOCATION)
1405
svn_error_clear(err);
1409
*modified = modcheck_baton.found_mod;
1410
*all_edits_are_deletes = (modcheck_baton.found_mod
1411
&& !modcheck_baton.found_not_delete);
1413
return SVN_NO_ERROR;
1416
1313
/* Indicates an unset svn_wc_conflict_reason_t. */
1417
1314
#define SVN_WC_CONFLICT_REASON_NONE (svn_wc_conflict_reason_t)(-1)
1489
/* The node is locally replaced but could also be moved-away. */
1490
SVN_ERR(svn_wc__db_base_moved_to(NULL, NULL, NULL,
1491
&move_src_op_root_abspath,
1492
eb->db, local_abspath,
1493
scratch_pool, scratch_pool));
1494
if (move_src_op_root_abspath)
1495
reason = svn_wc_conflict_reason_moved_away;
1497
reason = svn_wc_conflict_reason_replaced;
1385
/* The node is locally replaced but could also be moved-away,
1386
but we can't report that it is moved away and replaced.
1388
And we wouldn't be able to store that each of a dozen
1389
descendants was moved to other locations...
1391
Replaced is what actually happened... */
1393
reason = svn_wc_conflict_reason_replaced;
1557
1453
* not visit the subdirectories of a directory that it wants to delete.
1558
1454
* Therefore, we need to start a separate crawl here. */
1560
SVN_ERR(svn_wc__node_has_local_mods(&modified, &all_mods_are_deletes,
1561
eb->db, local_abspath,
1456
SVN_ERR(svn_wc__node_has_local_mods(&modified, NULL,
1457
eb->db, local_abspath, FALSE,
1562
1458
eb->cancel_func, eb->cancel_baton,
1563
1459
scratch_pool));
1567
if (all_mods_are_deletes)
1463
if (working_status == svn_wc__db_status_deleted)
1568
1464
reason = svn_wc_conflict_reason_deleted;
1570
1466
reason = svn_wc_conflict_reason_edited;
1843
1736
SVN_ERR(check_tree_conflict(&tree_conflict, eb, local_abspath,
1845
(kind == svn_node_dir)
1848
1739
svn_wc_conflict_action_delete,
1849
1740
pb->pool, scratch_pool));
1852
queue_deletes = FALSE; /* There is no in-wc representation */
1854
1743
if (tree_conflict != NULL)
1856
svn_wc_conflict_reason_t reason;
1857
1745
/* When we raise a tree conflict on a node, we don't want to mark the
1858
1746
* node as skipped, to allow a replacement to continue doing at least
1859
1747
* a bit of its work (possibly adding a not present node, for the
1864
1752
svn_hash_sets(pb->deletion_conflicts, apr_pstrdup(pb->pool, base),
1865
1753
tree_conflict);
1867
SVN_ERR(svn_wc__conflict_read_tree_conflict(&reason, NULL, NULL,
1868
eb->db, local_abspath,
1870
scratch_pool, scratch_pool));
1872
if (reason == svn_wc_conflict_reason_edited
1873
|| reason == svn_wc_conflict_reason_obstructed)
1875
/* The item exists locally and has some sort of local mod.
1876
* It no longer exists in the repository at its target URL@REV.
1878
* To prepare the "accept mine" resolution for the tree conflict,
1879
* we must schedule the existing content for re-addition as a copy
1880
* of what it was, but with its local modifications preserved. */
1881
keep_as_working = TRUE;
1883
/* Fall through to remove the BASE_NODEs properly, with potentially
1884
keeping a not-present marker */
1886
else if (reason == svn_wc_conflict_reason_deleted
1887
|| reason == svn_wc_conflict_reason_moved_away
1888
|| reason == svn_wc_conflict_reason_replaced)
1890
/* The item does not exist locally because it was already shadowed.
1891
* We must complete the deletion, leaving the tree conflict info
1892
* as the only difference from a normal deletion. */
1894
/* Fall through to the normal "delete" code path. */
1897
SVN_ERR_MALFUNCTION(); /* other reasons are not expected here */
1755
/* Whatever the kind of conflict, we can just clear BASE
1756
by turning whatever is there into a copy */
1759
/* Calculate the repository-relative path of the entry which was
1760
* deleted. For updates it's the same as REPOS_RELPATH but for
1761
* switches it is within the switch target. */
1762
SVN_ERR(calculate_repos_relpath(&deleted_repos_relpath, local_abspath,
1763
repos_relpath, eb, pb, scratch_pool,
1900
1765
SVN_ERR(complete_conflict(tree_conflict, eb, local_abspath, repos_relpath,
1902
(kind == svn_node_dir)
1766
old_revision, deleted_repos_relpath,
1767
kind, svn_node_none, NULL,
1906
1768
pb->pool, scratch_pool));
1908
1770
/* Issue a wq operation to delete the BASE_NODE data and to delete actual
1955
1820
eb->cancel_func,
1956
1821
eb->cancel_baton,
1957
1822
scratch_pool));
1958
do_notification(eb, local_abspath, svn_node_unknown,
1823
do_notification(eb, local_abspath, kind,
1959
1824
svn_wc_notify_tree_conflict, scratch_pool);
1963
1828
svn_wc_notify_action_t action = svn_wc_notify_update_delete;
1964
svn_node_kind_t node_kind;
1966
1830
if (pb->shadowed || pb->edit_obstructed)
1967
1831
action = svn_wc_notify_update_shadowed_delete;
1969
if (kind == svn_node_dir)
1970
node_kind = svn_node_dir;
1972
node_kind = svn_node_file;
1974
do_notification(eb, local_abspath, node_kind, action, scratch_pool);
1833
do_notification(eb, local_abspath, kind, action, scratch_pool);
1977
1836
svn_pool_destroy(scratch_pool);
2037
1899
"administrative directory"),
2038
1900
svn_dirent_local_style(db->local_abspath, pool));
2040
SVN_ERR(svn_io_check_path(db->local_abspath, &kind, db->pool));
2042
err = svn_wc__db_read_info(&status, &wc_kind, NULL, NULL, NULL, NULL, NULL,
2043
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
2044
NULL, NULL, NULL, NULL, NULL,
2045
&conflicted, NULL, NULL, NULL, NULL, NULL, NULL,
2046
eb->db, db->local_abspath, db->pool, db->pool);
1902
if (!eb->clean_checkout)
1904
SVN_ERR(svn_io_check_path(db->local_abspath, &kind, db->pool));
1906
err = svn_wc__db_read_info(&status, &wc_kind, NULL, NULL, NULL, NULL, NULL,
1907
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1908
NULL, NULL, NULL, NULL, NULL,
1909
&conflicted, NULL, NULL, NULL, NULL, NULL, NULL,
1910
eb->db, db->local_abspath,
1911
scratch_pool, scratch_pool);
1915
kind = svn_node_none;
1916
status = svn_wc__db_status_not_present;
1917
wc_kind = svn_node_unknown;
2049
1924
if (err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND)
2057
1932
versioned_locally_and_present = FALSE;
2059
else if (wc_kind == svn_node_dir
2060
&& status == svn_wc__db_status_normal)
1934
else if (status == svn_wc__db_status_normal && wc_kind == svn_node_unknown)
2062
/* !! We found the root of a separate working copy obstructing the wc !!
2064
If the directory would be part of our own working copy then
2065
we wouldn't have been called as an add_directory().
2067
The only thing we can do is add a not-present node, to allow
2068
a future update to bring in the new files when the problem is
2069
resolved. Note that svn_wc__db_base_add_not_present_node()
2070
explicitly adds the node into the parent's node database. */
2072
SVN_ERR(svn_wc__db_base_add_not_present_node(eb->db, db->local_abspath,
2076
*eb->target_revision,
2081
SVN_ERR(remember_skipped_tree(eb, db->local_abspath, pool));
2082
db->skip_this = TRUE;
2083
db->already_notified = TRUE;
2085
do_notification(eb, db->local_abspath, svn_node_dir,
2086
svn_wc_notify_update_skip_obstruction, pool);
2088
return SVN_NO_ERROR;
1936
SVN_ERR_ASSERT(conflicted);
1937
versioned_locally_and_present = FALSE; /* Tree conflict ACTUAL-only node */
2090
1939
else if (status == svn_wc__db_status_normal
2091
&& (wc_kind == svn_node_file
2092
|| wc_kind == svn_node_symlink))
1940
|| status == svn_wc__db_status_incomplete)
2094
/* We found a file external occupating the place we need in BASE.
2096
We can't add a not-present node in this case as that would overwrite
2097
the file external. Luckily the file external itself stops us from
2098
forgetting a child of this parent directory like an obstructing
2101
The reason we get here is that the adm crawler doesn't report
2105
SVN_ERR(remember_skipped_tree(eb, db->local_abspath, pool));
1944
SVN_ERR(svn_wc__db_is_wcroot(&root, eb->db, db->local_abspath,
1949
/* !! We found the root of a working copy obstructing the wc !!
1951
If the directory would be part of our own working copy then
1952
we wouldn't have been called as an add_directory().
1954
The only thing we can do is add a not-present node, to allow
1955
a future update to bring in the new files when the problem is
1956
resolved. Note that svn_wc__db_base_add_not_present_node()
1957
explicitly adds the node into the parent's node database. */
1959
svn_hash_sets(pb->not_present_nodes,
1960
apr_pstrdup(pb->pool, db->name),
1961
svn_node_kind_to_word(svn_node_dir));
1963
else if (wc_kind == svn_node_dir)
1965
/* We have an editor violation. Github sometimes does this
1966
in its subversion compatibility code, when changing the
1967
depth of a working copy, or on updates from incomplete */
1971
/* We found a file external occupating the place we need in BASE.
1973
We can't add a not-present node in this case as that would overwrite
1974
the file external. Luckily the file external itself stops us from
1975
forgetting a child of this parent directory like an obstructing
1978
The reason we get here is that the adm crawler doesn't report
1981
SVN_ERR_ASSERT(wc_kind == svn_node_file
1982
|| wc_kind == svn_node_symlink);
1985
SVN_ERR(remember_skipped_tree(eb, db->local_abspath, scratch_pool));
2106
1986
db->skip_this = TRUE;
2107
1987
db->already_notified = TRUE;
2109
do_notification(eb, db->local_abspath, svn_node_file,
2110
svn_wc_notify_update_skip_obstruction, pool);
1989
do_notification(eb, db->local_abspath, wc_kind,
1990
svn_wc_notify_update_skip_obstruction, scratch_pool);
1992
svn_pool_destroy(scratch_pool);
2112
1994
return SVN_NO_ERROR;
2114
else if (wc_kind == svn_node_unknown)
2115
versioned_locally_and_present = FALSE; /* Tree conflict ACTUAL-only node */
2117
1997
versioned_locally_and_present = IS_NODE_PRESENT(status);
2177
2058
Note that we can safely assume that no present base node exists,
2178
2059
because then we would not have received an add_directory.
2180
SVN_ERR(svn_wc__db_base_add_not_present_node(eb->db, db->local_abspath,
2184
*eb->target_revision,
2061
svn_hash_sets(pb->not_present_nodes, apr_pstrdup(pb->pool, db->name),
2062
svn_node_kind_to_word(svn_node_dir));
2189
/* ### TODO: Also print victim_path in the skip msg. */
2190
2064
do_notification(eb, db->local_abspath, svn_node_dir,
2191
svn_wc_notify_skip_conflicted, pool);
2065
svn_wc_notify_skip_conflicted, scratch_pool);
2067
svn_pool_destroy(scratch_pool);
2192
2068
return SVN_NO_ERROR;
2194
2070
else if (conflict_ignored)
2296
2175
(! db->shadowed
2297
2176
&& status == svn_wc__db_status_added),
2298
2177
tree_conflict, NULL,
2301
2180
/* Make sure there is a real directory at LOCAL_ABSPATH, unless we are just
2302
2181
updating the DB */
2303
2182
if (!db->shadowed)
2304
SVN_ERR(svn_wc__ensure_directory(db->local_abspath, pool));
2183
SVN_ERR(svn_wc__ensure_directory(db->local_abspath, scratch_pool));
2306
2185
if (tree_conflict != NULL)
2308
if (eb->conflict_func)
2309
SVN_ERR(svn_wc__conflict_invoke_resolver(eb->db, db->local_abspath,
2311
NULL /* merge_options */,
2187
db->edit_conflict = tree_conflict;
2318
2189
db->already_notified = TRUE;
2319
2190
do_notification(eb, db->local_abspath, svn_node_dir,
2320
svn_wc_notify_tree_conflict, pool);
2191
svn_wc_notify_tree_conflict, scratch_pool);
2786
2665
transaction, but I can't even trigger it. I've tried
2787
2666
ra_local, ra_svn, ra_neon, ra_serf and they all call
2788
2667
close_file before close_dir. */
2789
for (hi = apr_hash_first(scratch_pool, db->not_present_files);
2668
for (hi = apr_hash_first(scratch_pool, db->not_present_nodes);
2791
2670
hi = apr_hash_next(hi))
2793
const char *child = svn__apr_hash_index_key(hi);
2672
const char *child = apr_hash_this_key(hi);
2794
2673
const char *child_abspath, *child_relpath;
2674
svn_node_kind_t kind = svn_node_kind_from_word(apr_hash_this_val(hi));
2796
2676
svn_pool_clear(iterpool);
2798
2678
child_abspath = svn_dirent_join(db->local_abspath, child, iterpool);
2799
child_relpath = svn_dirent_join(db->new_relpath, child, iterpool);
2679
child_relpath = svn_dirent_join(db->new_repos_relpath, child, iterpool);
2801
2681
SVN_ERR(svn_wc__db_base_add_not_present_node(eb->db,
3074
2967
/* We have a local addition. If this would be a BASE node it would have
3075
2968
been deleted before we get here. (Which might have turned it into
3078
### This should be recorded as a tree conflict and the update
3079
### can just continue, as we can just record the absent status
3082
2970
SVN_ERR_ASSERT(status != svn_wc__db_status_normal);
3084
return svn_error_createf(
3085
SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL,
3086
_("Failed to mark '%s' absent: item of the same name is already "
3087
"scheduled for addition"),
3088
svn_dirent_local_style(local_abspath, pool));
2972
if (!pb->shadowed && !pb->edit_obstructed)
2973
SVN_ERR(check_tree_conflict(&tree_conflict, eb, local_abspath,
2974
status, FALSE, svn_node_unknown,
2975
svn_wc_conflict_action_add,
2976
scratch_pool, scratch_pool));
3092
2981
const char *repos_relpath;
3093
repos_relpath = svn_relpath_join(pb->new_relpath, name, scratch_pool);
2982
repos_relpath = svn_relpath_join(pb->new_repos_relpath, name, scratch_pool);
2985
SVN_ERR(complete_conflict(tree_conflict, eb, local_abspath,
2986
NULL, SVN_INVALID_REVNUM, repos_relpath,
2987
kind, svn_node_unknown, NULL,
2988
scratch_pool, scratch_pool));
3095
2990
/* Insert an excluded node below the parent node to note that this child
3096
2991
is absent. (This puts it in the parent db if the child is obstructed) */
3142
3053
struct dir_baton *pb = parent_baton;
3143
3054
struct edit_baton *eb = pb->edit_baton;
3144
3055
struct file_baton *fb;
3145
svn_node_kind_t kind = svn_node_none;
3146
svn_node_kind_t wc_kind = svn_node_unknown;
3147
svn_wc__db_status_t status = svn_wc__db_status_normal;
3056
svn_node_kind_t kind;
3057
svn_node_kind_t wc_kind;
3058
svn_wc__db_status_t status;
3148
3059
apr_pool_t *scratch_pool;
3149
svn_boolean_t conflicted = FALSE;
3060
svn_boolean_t conflicted;
3150
3061
svn_boolean_t conflict_ignored = FALSE;
3151
svn_boolean_t versioned_locally_and_present = FALSE;
3062
svn_boolean_t versioned_locally_and_present;
3152
3063
svn_skel_t *tree_conflict = NULL;
3153
3064
svn_error_t *err = SVN_NO_ERROR;
3155
3066
SVN_ERR_ASSERT(! (copyfrom_path || SVN_IS_VALID_REVNUM(copyfrom_rev)));
3157
3068
SVN_ERR(make_file_baton(&fb, pb, path, TRUE, pool));
3069
SVN_ERR(calculate_repos_relpath(&fb->new_repos_relpath, fb->local_abspath,
3070
NULL, eb, pb, fb->pool, pool));
3158
3071
*file_baton = fb;
3160
3073
if (fb->skip_this)
3199
3119
versioned_locally_and_present = FALSE;
3201
else if (wc_kind == svn_node_dir
3202
&& status == svn_wc__db_status_normal)
3121
else if (status == svn_wc__db_status_normal && wc_kind == svn_node_unknown)
3204
/* !! We found the root of a separate working copy obstructing the wc !!
3206
If the directory would be part of our own working copy then
3207
we wouldn't have been called as an add_file().
3209
The only thing we can do is add a not-present node, to allow
3210
a future update to bring in the new files when the problem is
3212
svn_hash_sets(pb->not_present_files, apr_pstrdup(pb->pool, fb->name),
3215
SVN_ERR(remember_skipped_tree(eb, fb->local_abspath, pool));
3216
fb->skip_this = TRUE;
3217
fb->already_notified = TRUE;
3219
do_notification(eb, fb->local_abspath, svn_node_file,
3220
svn_wc_notify_update_skip_obstruction, scratch_pool);
3222
svn_pool_destroy(scratch_pool);
3224
return SVN_NO_ERROR;
3123
SVN_ERR_ASSERT(conflicted);
3124
versioned_locally_and_present = FALSE; /* Tree conflict ACTUAL-only node */
3226
3126
else if (status == svn_wc__db_status_normal
3227
&& (wc_kind == svn_node_file
3228
|| wc_kind == svn_node_symlink))
3127
|| status == svn_wc__db_status_incomplete)
3230
/* We found a file external occupating the place we need in BASE.
3232
We can't add a not-present node in this case as that would overwrite
3233
the file external. Luckily the file external itself stops us from
3234
forgetting a child of this parent directory like an obstructing
3237
The reason we get here is that the adm crawler doesn't report
3131
SVN_ERR(svn_wc__db_is_wcroot(&root, eb->db, fb->local_abspath,
3136
/* !! We found the root of a working copy obstructing the wc !!
3138
If the directory would be part of our own working copy then
3139
we wouldn't have been called as an add_directory().
3141
The only thing we can do is add a not-present node, to allow
3142
a future update to bring in the new files when the problem is
3143
resolved. Note that svn_wc__db_base_add_not_present_node()
3144
explicitly adds the node into the parent's node database. */
3146
svn_hash_sets(pb->not_present_nodes,
3147
apr_pstrdup(pb->pool, fb->name),
3148
svn_node_kind_to_word(svn_node_dir));
3150
else if (wc_kind == svn_node_dir)
3152
/* We have an editor violation. Github sometimes does this
3153
in its subversion compatibility code, when changing the
3154
depth of a working copy, or on updates from incomplete */
3158
/* We found a file external occupating the place we need in BASE.
3160
We can't add a not-present node in this case as that would overwrite
3161
the file external. Luckily the file external itself stops us from
3162
forgetting a child of this parent directory like an obstructing
3165
The reason we get here is that the adm crawler doesn't report
3168
SVN_ERR_ASSERT(wc_kind == svn_node_file
3169
|| wc_kind == svn_node_symlink);
3240
3172
SVN_ERR(remember_skipped_tree(eb, fb->local_abspath, pool));
3241
3173
fb->skip_this = TRUE;
3242
3174
fb->already_notified = TRUE;
3244
do_notification(eb, fb->local_abspath, svn_node_file,
3176
do_notification(eb, fb->local_abspath, wc_kind,
3245
3177
svn_wc_notify_update_skip_obstruction, scratch_pool);
3247
3179
svn_pool_destroy(scratch_pool);
3249
3181
return SVN_NO_ERROR;
3251
else if (wc_kind == svn_node_unknown)
3252
versioned_locally_and_present = FALSE; /* Tree conflict ACTUAL-only node */
3254
3184
versioned_locally_and_present = IS_NODE_PRESENT(status);
3316
3246
Note that we can safely assume that no present base node exists,
3317
3247
because then we would not have received an add_file.
3319
svn_hash_sets(pb->not_present_files, apr_pstrdup(pb->pool, fb->name),
3249
svn_hash_sets(pb->not_present_nodes, apr_pstrdup(pb->pool, fb->name),
3250
svn_node_kind_to_word(svn_node_file));
3322
do_notification(eb, fb->local_abspath, svn_node_unknown,
3252
do_notification(eb, fb->local_abspath, svn_node_file,
3323
3253
svn_wc_notify_skip_conflicted, scratch_pool);
3325
3255
svn_pool_destroy(scratch_pool);
3628
3550
apr_pool_t *result_pool,
3629
3551
apr_pool_t *scratch_pool)
3631
struct lazy_target_baton *tb = baton;
3553
struct handler_baton *hb = baton;
3633
SVN_ERR(svn_wc__open_writable_base(stream, &tb->hb->new_text_base_tmp_abspath,
3634
NULL, &tb->hb->new_text_base_sha1_checksum,
3635
tb->fb->edit_baton->db,
3636
tb->eb->wcroot_abspath,
3637
result_pool, scratch_pool));
3555
SVN_ERR(svn_wc__db_pristine_prepare_install(stream,
3557
&hb->new_text_base_sha1_checksum,
3559
hb->fb->edit_baton->db,
3560
hb->fb->dir_baton->local_abspath,
3561
result_pool, scratch_pool));
3639
3563
return SVN_NO_ERROR;
3748
3671
hb->source_checksum_stream = source;
3751
tb = apr_palloc(handler_pool, sizeof(struct lazy_target_baton));
3755
target = svn_stream_lazyopen_create(lazy_open_target, tb, TRUE, handler_pool);
3674
target = svn_stream_lazyopen_create(lazy_open_target, hb, TRUE, handler_pool);
3757
3676
/* Prepare to apply the delta. */
3758
3677
svn_txdelta_apply(source, target,
3759
3678
hb->new_text_base_md5_digest,
3760
hb->new_text_base_tmp_abspath /* error_info */,
3679
fb->local_abspath /* error_info */,
3762
3681
&hb->apply_handler, &hb->apply_baton);
3852
3771
SVN_ERR(complete_conflict(fb->edit_conflict, fb->edit_baton,
3853
3772
fb->local_abspath, fb->old_repos_relpath,
3854
fb->old_revision, fb->new_relpath,
3773
fb->old_revision, fb->new_repos_relpath,
3855
3774
svn_node_file, svn_node_file,
3856
fb->pool, scratch_pool));
3775
NULL, fb->pool, scratch_pool));
3858
3777
/* Create a copy of the existing (pre update) BASE node in WORKING,
3859
3778
mark a tree conflict and handle the rest of the update as
4322
4241
/* If we lose the lock, but not because we are switching to
4323
4242
another url, remove the state lock from the wc */
4324
if (! eb->switch_relpath
4325
|| strcmp(fb->new_relpath, fb->old_repos_relpath) == 0)
4243
if (! eb->switch_repos_relpath
4244
|| strcmp(fb->new_repos_relpath, fb->old_repos_relpath) == 0)
4327
4246
SVN_ERR_ASSERT(prop->value == NULL);
4328
SVN_ERR(svn_wc__db_lock_remove(eb->db, fb->local_abspath,
4247
SVN_ERR(svn_wc__db_lock_remove(eb->db, fb->local_abspath, NULL,
4329
4248
scratch_pool));
4331
4250
lock_state = svn_wc_notify_lock_state_unlocked;
4615
/* Implements svn_wc__proplist_receiver_t.
4616
* Check for the presence of an svn:keywords property and queues an install_file
4617
* work queue item if present. Thus, when the work queue is run to complete the
4618
* switch operation, all files with keywords will go through the translation
4619
* process so URLs etc are updated. */
4620
static svn_error_t *
4621
update_keywords_after_switch_cb(void *baton,
4622
const char *local_abspath,
4624
apr_pool_t *scratch_pool)
4626
struct edit_baton *eb = baton;
4627
svn_string_t *propval;
4628
svn_boolean_t modified;
4629
svn_boolean_t record_fileinfo;
4630
svn_skel_t *work_items;
4631
const char *install_from;
4633
propval = svn_hash_gets(props, SVN_PROP_KEYWORDS);
4635
return SVN_NO_ERROR;
4637
SVN_ERR(svn_wc__internal_file_modified_p(&modified, eb->db,
4638
local_abspath, FALSE,
4642
const char *temp_dir_abspath;
4643
svn_stream_t *working_stream;
4644
svn_stream_t *install_from_stream;
4646
SVN_ERR(svn_wc__db_temp_wcroot_tempdir(&temp_dir_abspath, eb->db,
4647
local_abspath, scratch_pool,
4649
SVN_ERR(svn_stream_open_readonly(&working_stream, local_abspath,
4650
scratch_pool, scratch_pool));
4651
SVN_ERR(svn_stream_open_unique(&install_from_stream, &install_from,
4652
temp_dir_abspath, svn_io_file_del_none,
4653
scratch_pool, scratch_pool));
4654
SVN_ERR(svn_stream_copy3(working_stream, install_from_stream,
4655
eb->cancel_func, eb->cancel_baton,
4657
record_fileinfo = FALSE;
4661
install_from = NULL;
4662
record_fileinfo = TRUE;
4665
SVN_ERR(svn_wc__wq_build_file_install(&work_items, eb->db, local_abspath,
4667
eb->use_commit_times,
4669
scratch_pool, scratch_pool));
4672
svn_skel_t *work_item;
4674
SVN_ERR(svn_wc__wq_build_file_remove(&work_item, eb->db,
4675
local_abspath, install_from,
4676
scratch_pool, scratch_pool));
4677
work_items = svn_wc__wq_merge(work_items, work_item, scratch_pool);
4680
SVN_ERR(svn_wc__db_wq_add(eb->db, local_abspath, work_items,
4683
return SVN_NO_ERROR;
4690
4687
/* An svn_delta_editor_t function. */
4691
4688
static svn_error_t *
4692
4689
close_edit(void *edit_baton,
4773
4771
If so, we should get rid of this excluded node now. */
4775
4773
SVN_ERR(svn_wc__db_base_remove(eb->db, eb->target_abspath,
4776
FALSE /* keep_as_working */,
4777
FALSE /* queue_deletes */,
4778
FALSE /* remove_locks */,
4779
4775
SVN_INVALID_REVNUM,
4780
4776
NULL, NULL, scratch_pool));
4781
/* Update keywords in switched files.
4782
GOTO #1975 (the year of the Altair 8800). */
4783
if (eb->switch_repos_relpath)
4787
if (eb->requested_depth > svn_depth_empty)
4788
depth = eb->requested_depth;
4790
depth = svn_depth_infinity;
4792
SVN_ERR(svn_wc__db_read_props_streamily(eb->db,
4795
FALSE, /* pristine */
4796
NULL, /* changelists */
4797
update_keywords_after_switch_cb,
4785
4804
/* The edit is over: run the wq with proper cancel support,
4786
4805
but first kill the handler that would run it on the pool
4787
4806
cleanup at the end of this function. */
4855
4874
/* Get the anchor's repository root and uuid. The anchor must already exist
4857
SVN_ERR(svn_wc__db_scan_base_repos(NULL, &repos_root, &repos_uuid,
4859
result_pool, scratch_pool));
4876
SVN_ERR(svn_wc__db_base_get_info(NULL, NULL, NULL, NULL, &repos_root,
4877
&repos_uuid, NULL, NULL, NULL, NULL,
4878
NULL, NULL, NULL, NULL, NULL, NULL,
4880
result_pool, scratch_pool));
4861
4882
/* With WC-NG we need a valid repository root */
4862
4883
SVN_ERR_ASSERT(repos_root != NULL && repos_uuid != NULL);
5344
5367
/* Copy NEW_BASE_CONTENTS into a temporary file so our log can refer to
5345
5368
it, and set TMP_TEXT_BASE_ABSPATH to its path. Compute its
5346
5369
NEW_TEXT_BASE_MD5_CHECKSUM and NEW_TEXT_BASE_SHA1_CHECKSUM as we copy. */
5348
svn_stream_t *tmp_base_contents;
5350
SVN_ERR(svn_wc__open_writable_base(&tmp_base_contents,
5351
&tmp_text_base_abspath,
5352
&new_text_base_md5_checksum,
5353
&new_text_base_sha1_checksum,
5354
wc_ctx->db, local_abspath,
5356
SVN_ERR(svn_stream_copy3(new_base_contents, tmp_base_contents,
5357
cancel_func, cancel_baton, pool));
5372
SVN_ERR(svn_wc__db_pristine_prepare_install(&tmp_base_contents,
5374
&new_text_base_sha1_checksum,
5375
&new_text_base_md5_checksum,
5376
wc_ctx->db, local_abspath,
5377
scratch_pool, scratch_pool));
5381
const char *tmp_dir_abspath;
5383
/* We are not installing a PRISTINE file, but we use the same code to
5384
create whatever we want to install */
5386
SVN_ERR(svn_wc__db_temp_wcroot_tempdir(&tmp_dir_abspath,
5388
scratch_pool, scratch_pool));
5390
SVN_ERR(svn_stream_open_unique(&tmp_base_contents, &tmp_text_base_abspath,
5391
tmp_dir_abspath, svn_io_file_del_none,
5392
scratch_pool, scratch_pool));
5394
new_text_base_sha1_checksum = NULL;
5395
new_text_base_md5_checksum = NULL;
5397
SVN_ERR(svn_stream_copy3(new_base_contents, tmp_base_contents,
5398
cancel_func, cancel_baton, pool));
5360
5400
/* If the caller gave us a new working file, copy it to a safe (temporary)
5361
5401
location and set SOURCE_ABSPATH to that path. We'll then translate/copy