A couple of recent issues have revealed that we don't handle incomplete working nodes properly:
http://subversion.tigris.org/issues/show_bug.cgi?id=4025 http://subversion.tigris.org/issues/show_bug.cgi?id=4026 These nodes happen when a wc-to-wc copy is interrupted, and possibly when an incomplete base node is copied. Since this is not something that happens very often I suspect that the code is poorly tested. A patch to fix 4025 is: Index: subversion/libsvn_wc/info.c =================================================================== --- subversion/libsvn_wc/info.c (revision 1177632) +++ subversion/libsvn_wc/info.c (working copy) @@ -94,7 +94,7 @@ svn_wc__db_lock_t *lock; svn_boolean_t conflicted; svn_boolean_t op_root; - svn_boolean_t have_base; + svn_boolean_t have_base, have_work; svn_wc_info_t *wc_info; tmpinfo = apr_pcalloc(result_pool, sizeof(*tmpinfo)); @@ -119,7 +119,7 @@ &wc_info->recorded_time, &wc_info->changelist, &conflicted, &op_root, NULL, NULL, - &have_base, NULL, NULL, + &have_base, NULL, &have_work, db, local_abspath, result_pool, scratch_pool)); @@ -129,7 +129,8 @@ tmpinfo->repos_UUID = original_uuid; } - if (status == svn_wc__db_status_added) + if (status == svn_wc__db_status_added + || (status == svn_wc__db_status_incomplete && have_work)) { /* ### We should also just be fetching the true BASE revision ### here, which means copied items would also not have a Index: subversion/libsvn_wc/wc_db.c =================================================================== --- subversion/libsvn_wc/wc_db.c (revision 1177632) +++ subversion/libsvn_wc/wc_db.c (working copy) @@ -7583,17 +7583,18 @@ const char *repos_relpath; const char *repos_root_url; apr_int64_t repos_id; - svn_boolean_t have_base; + svn_boolean_t have_base, have_work; SVN_ERR(read_info(&status, NULL, NULL, &repos_relpath, &repos_id, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - &have_base, NULL, NULL, + &have_base, NULL, &have_work, wcroot, local_relpath, scratch_pool, scratch_pool)); if (repos_relpath == NULL) { - if (status == svn_wc__db_status_added) + if (status == svn_wc__db_status_added + || (status == svn_wc__db_status_incomplete && have_work)) { SVN_ERR(scan_addition(NULL, NULL, &repos_relpath, &repos_id, NULL, NULL, NULL, NULL, NULL, wcroot, local_relpath, @@ -9463,7 +9464,8 @@ presence = svn_sqlite__column_token(stmt, 1, presence_map); /* The starting node should exist normally. */ - if (presence != svn_wc__db_status_normal) + if (presence != svn_wc__db_status_normal + && presence != svn_wc__db_status_incomplete) /* reset the statement as part of the error generation process */ return svn_error_createf(SVN_ERR_WC_PATH_UNEXPECTED_STATUS, svn_sqlite__reset(stmt), @@ -9477,7 +9479,12 @@ /* Provide the default status; we'll override as appropriate. */ if (sab->status) - *sab->status = svn_wc__db_status_added; + { + if (presence == svn_wc__db_status_incomplete) + *sab->status = svn_wc__db_status_incomplete; + else + *sab->status = svn_wc__db_status_added; + } /* Calculate the op root local path components */ Index: subversion/libsvn_wc/node.c =================================================================== --- subversion/libsvn_wc/node.c (revision 1177632) +++ subversion/libsvn_wc/node.c (working copy) @@ -1403,7 +1403,8 @@ { svn_boolean_t scan_working = FALSE; - if (status == svn_wc__db_status_added) + if (status == svn_wc__db_status_added + || status == svn_wc__db_status_incomplete) scan_working = TRUE; else if (status == svn_wc__db_status_deleted) { @@ -1425,7 +1426,8 @@ db, local_abspath, result_pool, scratch_pool)); - if (status == svn_wc__db_status_added) + if (status == svn_wc__db_status_added + || status == svn_wc__db_status_incomplete) return SVN_NO_ERROR; /* Local addition */ *repos_relpath = svn_relpath_join( 'svn info' still produces an error message but no longer SEGVs: $ svn info wc/X/B Path: wc/X/B Name: B Working Copy Root Path: /home/pm/sw/subversion/obj/wc URL: svn://localhost/repo/X/B Repository Root: svn://localhost/repo Repository UUID: 59189962-c505-4495-a37c-a860a513b12b Revision: 5 Node Kind: unknown Schedule: normal ../src/subversion/svn/info-cmd.c:669: (apr_err=145000) ../src/subversion/libsvn_wc/info.c:499: (apr_err=145000) ../src/subversion/libsvn_wc/info.c:499: (apr_err=145000) ../src/subversion/libsvn_wc/node.c:723: (apr_err=145000) svn: E145000: '/home/pm/sw/subversion/obj/wc/X/B' has an unrecognized node kind Another solution would be to have svn_wc__db_read_info return status=added for incomplete working nodes so they would be treated as added automatically. We would need to have svn_wc__db_scan_addition return status=incomplete so that the incomplete status is still available. That means that we lose the incomplete information when calling read_info, perhaps forcing scan_addition to be used in more places. The patch below also fixes the 'svn info' SEGV. Anyone got any opinions about which approach we should take? Index: subversion/libsvn_wc/wc_db.c =================================================================== --- subversion/libsvn_wc/wc_db.c (revision 1177632) +++ subversion/libsvn_wc/wc_db.c (working copy) @@ -6108,12 +6108,8 @@ || work_status == svn_wc__db_status_incomplete || work_status == svn_wc__db_status_excluded); - if (work_status == svn_wc__db_status_incomplete) + if (work_status == svn_wc__db_status_excluded) { - *working_status = svn_wc__db_status_incomplete; - } - else if (work_status == svn_wc__db_status_excluded) - { *working_status = svn_wc__db_status_excluded; } else if (work_status == svn_wc__db_status_not_present @@ -6127,7 +6123,7 @@ *working_status = svn_wc__db_status_deleted; } - else /* normal */ + else /* normal or incomplete */ { /* The caller should scan upwards to detect whether this addition has occurred because of a simple addition, @@ -9463,7 +9459,9 @@ presence = svn_sqlite__column_token(stmt, 1, presence_map); /* The starting node should exist normally. */ - if (presence != svn_wc__db_status_normal) + op_depth = svn_sqlite__column_int64(stmt, 0); + if (op_depth == 0 || (presence != svn_wc__db_status_normal + && presence != svn_wc__db_status_incomplete)) /* reset the statement as part of the error generation process */ return svn_error_createf(SVN_ERR_WC_PATH_UNEXPECTED_STATUS, svn_sqlite__reset(stmt), @@ -9477,11 +9475,15 @@ /* Provide the default status; we'll override as appropriate. */ if (sab->status) - *sab->status = svn_wc__db_status_added; + { + if (presence == svn_wc__db_status_normal) + *sab->status = svn_wc__db_status_added; + else + *sab->status = svn_wc__db_status_incomplete; + } /* Calculate the op root local path components */ - op_depth = svn_sqlite__column_int64(stmt, 0); op_root_relpath = local_relpath; for (i = (int)relpath_depth(local_relpath); i > op_depth; --i) Index: subversion/libsvn_wc/wc_db.h =================================================================== --- subversion/libsvn_wc/wc_db.h (revision 1177632) +++ subversion/libsvn_wc/wc_db.h (working copy) @@ -1710,8 +1710,8 @@ node's revision. svn_wc__db_status_incomplete - The BASE or WORKING node is incomplete due to an interrupted - operation. + The BASE is incomplete due to an interrupted operation. An + incomplete WORKING node will be svn_wc__db_status_added. If REVISION is requested, it will be set to the revision of the unmodified (BASE) node, or to SVN_INVALID_REVNUM if any structural @@ -2441,6 +2441,8 @@ ancestor unshadowed BASE node. ORIGINAL_* will indicate the source of the copy. + svn_wc__db_status_incomplete -- this NODE is copied but incomplete. + svn_wc__db_status_moved_here -- this NODE arrived as a result of a move. The root of the moved nodes will be stored in OP_ROOT_ABSPATH. Similar to the copied state, its parent may be a WORKING node or a -- uberSVN: Apache Subversion Made Easy http://www.uberSVN.com