Modified: subversion/branches/fsx-1.10/subversion/libsvn_subr/version.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_subr/version.c?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_subr/version.c (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_subr/version.c Sun Jun 14 20:58:10 2015 @@ -40,11 +40,13 @@ svn_subr_version(void) svn_boolean_t svn_ver_compatible(const svn_version_t *my_version, const svn_version_t *lib_version) { - /* With normal development builds the matching rules are strict, to - avoid inadvertantly using the wrong libraries. For backward - compatibility testing use --disable-full-version-match to - configure 1.7 and then the libraries that get built can be used - to replace those in 1.6 or earlier builds. */ + /* With normal development builds the matching rules are stricter + that for release builds, to avoid inadvertantly using the wrong + libraries. For backward compatibility testing of development + builds one can use --disable-full-version-match to cause a + development build to use the release build rules. This allows + the libraries from the newer development build to be used by an + older development build. */ #ifndef SVN_DISABLE_FULL_VERSION_MATCH if (lib_version->tag[0] != '\0') @@ -83,6 +85,11 @@ svn_ver_check_list2(const svn_version_t svn_error_t *err = SVN_NO_ERROR; int i; +#ifdef SVN_DISABLE_FULL_VERSION_MATCH + /* Force more relaxed check for --disable-full-version-match. */ + comparator = svn_ver_compatible; +#endif + for (i = 0; checklist[i].label != NULL; ++i) { const svn_version_t *lib_version = checklist[i].version_query(); @@ -136,7 +143,7 @@ svn_version_extended(svn_boolean_t verbo info->build_time = __TIME__; info->build_host = SVN_BUILD_HOST; info->copyright = apr_pstrdup - (pool, _("Copyright (C) 2014 The Apache Software Foundation.\n" + (pool, _("Copyright (C) 2015 The Apache Software Foundation.\n" "This software consists of contributions made by many people;\n" "see the NOTICE file for more information.\n" "Subversion is open source software, see "
Modified: subversion/branches/fsx-1.10/subversion/libsvn_subr/win32_crashrpt.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_subr/win32_crashrpt.c?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_subr/win32_crashrpt.c (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_subr/win32_crashrpt.c Sun Jun 14 20:58:10 2015 @@ -422,7 +422,7 @@ write_var_values(PSYMBOL_INFO sym_info, if (log_params && sym_info->Flags & SYMFLAG_PARAMETER) { if (last_nr_of_frame == nr_of_frame) - fprintf(log_file, ", ", 2); + fprintf(log_file, ", "); else last_nr_of_frame = nr_of_frame; Modified: subversion/branches/fsx-1.10/subversion/libsvn_subr/x509info.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_subr/x509info.c?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_subr/x509info.c (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_subr/x509info.c Sun Jun 14 20:58:10 2015 @@ -41,8 +41,7 @@ svn_x509_name_attr_dup(const svn_x509_na { svn_x509_name_attr_t *result = apr_palloc(result_pool, sizeof(*result)); result->oid_len = attr->oid_len; - result->oid = apr_palloc(result_pool, result->oid_len); - memcpy(result->oid, attr->oid, result->oid_len); + result->oid = apr_pmemdup(result_pool, attr->oid, attr->oid_len); result->utf8_value = apr_pstrdup(result_pool, attr->utf8_value); return result; @@ -124,7 +123,7 @@ svn_x509_certinfo_dup(const svn_x509_cer typedef struct asn1_oid { const unsigned char *oid; - const ptrdiff_t oid_len; + const apr_size_t oid_len; const char *short_label; const char *long_label; } asn1_oid; @@ -168,7 +167,7 @@ svn_x509_oid_to_string(const unsigned ch } else if (*p < 128) { - /* The remaining values if they're less than 128 are just + /* The remaining values if they're less than 128 are just * the number one to one encoded */ temp = apr_psprintf(scratch_pool, ".%d", *p); p++; Modified: subversion/branches/fsx-1.10/subversion/libsvn_subr/x509parse.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_subr/x509parse.c?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_subr/x509parse.c (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_subr/x509parse.c Sun Jun 14 20:58:10 2015 @@ -685,6 +685,8 @@ x509_get_ext(apr_array_header_t *dnsname *p += len; continue; } + + return svn_error_trace(err); } else { @@ -917,8 +919,7 @@ x509_name_to_certinfo(apr_array_header_t svn_x509_name_attr_t *attr = apr_palloc(result_pool, sizeof(svn_x509_name_attr_t)); attr->oid_len = name->oid.len; - attr->oid = apr_palloc(result_pool, attr->oid_len); - memcpy(attr->oid, name->oid.p, attr->oid_len); + attr->oid = apr_pmemdup(result_pool, name->oid.p, attr->oid_len); attr->utf8_value = x509name_to_utf8_string(name, result_pool); if (!attr->utf8_value) /* this should never happen */ @@ -1052,7 +1053,7 @@ svn_x509_parse_cert(svn_x509_certinfo_t */ err = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE); if (err) - return svn_error_create(SVN_ERR_X509_CERT_INVALID_FORMAT, NULL, NULL); + return svn_error_create(SVN_ERR_X509_CERT_INVALID_FORMAT, err, NULL); if (len != (end - p)) { Modified: subversion/branches/fsx-1.10/subversion/libsvn_wc/adm_ops.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_wc/adm_ops.c?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_wc/adm_ops.c (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_wc/adm_ops.c Sun Jun 14 20:58:10 2015 @@ -680,7 +680,8 @@ svn_wc_add4(svn_wc_context_t *wc_ctx, repos_relpath, repos_root_url, repos_uuid, copyfrom_rev, - NULL /* children */, FALSE, depth, + NULL /* children */, depth, + FALSE /* is_move */, NULL /* conflicts */, NULL /* work items */, scratch_pool)); Modified: subversion/branches/fsx-1.10/subversion/libsvn_wc/conflicts.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_wc/conflicts.c?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_wc/conflicts.c (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_wc/conflicts.c Sun Jun 14 20:58:10 2015 @@ -1142,6 +1142,7 @@ static svn_error_t * generate_propconflict(svn_boolean_t *conflict_remains, svn_wc__db_t *db, const char *local_abspath, + svn_node_kind_t kind, svn_wc_operation_t operation, const svn_wc_conflict_version_t *left_version, const svn_wc_conflict_version_t *right_version, @@ -1159,24 +1160,11 @@ generate_propconflict(svn_boolean_t *con svn_wc_conflict_result_t *result = NULL; svn_wc_conflict_description2_t *cdesc; const char *dirpath = svn_dirent_dirname(local_abspath, scratch_pool); - svn_node_kind_t kind; const svn_string_t *new_value = NULL; - SVN_ERR(svn_wc__db_read_kind(&kind, db, local_abspath, - FALSE /* allow_missing */, - FALSE /* show_deleted */, - FALSE /* show_hidden */, - scratch_pool)); - - if (kind == svn_node_none) - return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND, NULL, - _("The node '%s' was not found."), - svn_dirent_local_style(local_abspath, - scratch_pool)); - cdesc = svn_wc_conflict_description_create_prop2( local_abspath, - (kind == svn_node_dir) ? svn_node_dir : svn_node_file, + kind, propname, scratch_pool); cdesc->operation = operation; @@ -1365,18 +1353,24 @@ generate_propconflict(svn_boolean_t *con { svn_stringbuf_t *merged_stringbuf; - if (!cdesc->merged_file && !result->merged_file) + if (!cdesc->merged_file + && (!result->merged_file && !result->merged_value)) return svn_error_create (SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, _("Conflict callback violated API:" " returned no merged file")); - SVN_ERR(svn_stringbuf_from_file2(&merged_stringbuf, - result->merged_file ? - result->merged_file : - cdesc->merged_file, - scratch_pool)); - new_value = svn_stringbuf__morph_into_string(merged_stringbuf); + if (result->merged_value) + new_value = result->merged_value; + else + { + SVN_ERR(svn_stringbuf_from_file2(&merged_stringbuf, + result->merged_file ? + result->merged_file : + cdesc->merged_file, + scratch_pool)); + new_value = svn_stringbuf__morph_into_string(merged_stringbuf); + } *conflict_remains = FALSE; break; } @@ -1675,7 +1669,13 @@ build_text_conflict_resolve_items(svn_sk SVN_ERR_ASSERT(choice == svn_wc_conflict_choose_postpone); } - SVN_ERR_ASSERT(install_from_abspath != NULL); + if (install_from_abspath == NULL) + return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, + _("Conflict on '%s' could not be resolved " + "because the chosen version of the file " + "is not available."), + svn_dirent_local_style(local_abspath, + scratch_pool)); /* ### It would be nice if we could somehow pass RECORD_FILEINFO as true in some easy cases. */ @@ -1733,7 +1733,6 @@ read_text_conflict_desc(svn_wc_conflict_ svn_wc__db_t *db, const char *local_abspath, const svn_skel_t *conflict_skel, - svn_boolean_t is_binary, const char *mime_type, svn_wc_operation_t operation, const svn_wc_conflict_version_t *left_version, @@ -1742,8 +1741,8 @@ read_text_conflict_desc(svn_wc_conflict_ apr_pool_t *scratch_pool) { *desc = svn_wc_conflict_description_create_text2(local_abspath, result_pool); - (*desc)->is_binary = is_binary; (*desc)->mime_type = mime_type; + (*desc)->is_binary = mime_type ? svn_mime_type_is_binary(mime_type) : FALSE; (*desc)->operation = operation; (*desc)->src_left_version = left_version; (*desc)->src_right_version = right_version; @@ -1772,6 +1771,7 @@ static svn_error_t * read_tree_conflict_desc(svn_wc_conflict_description2_t **desc, svn_wc__db_t *db, const char *local_abspath, + svn_node_kind_t node_kind, const svn_skel_t *conflict_skel, svn_wc_operation_t operation, const svn_wc_conflict_version_t *left_version, @@ -1792,49 +1792,18 @@ read_tree_conflict_desc(svn_wc_conflict_ else if (reason == svn_wc_conflict_reason_unversioned || reason == svn_wc_conflict_reason_obstructed) SVN_ERR(svn_io_check_path(local_abspath, &local_kind, scratch_pool)); - else if (operation == svn_wc_operation_merge) + else if (action == svn_wc_conflict_action_delete + && left_version + && (operation == svn_wc_operation_update + ||operation == svn_wc_operation_switch) + && (reason == svn_wc_conflict_reason_deleted + || reason == svn_wc_conflict_reason_moved_away)) { - /* ### If the merge replaced the node, this will read the kind of - * ### the merge-right node, which is not necessarily the node - * ### kind of the tree conflict victim. - * ### This needs the BASE node kind if the node was not replaced - * ### at the time the merge was run. But if the node was already - * ### replaced before the merge, it needs the kind of the replacing - * ### node. Ideally, we'd store the victim node kind in conflict - * ### storage instead of guessing it here... - */ - /* Read the tree conflict victim's node kind from the working copy, - or if it doesn't exist directly from disk. */ - SVN_ERR(svn_wc__db_read_kind(&local_kind, db, local_abspath, - TRUE /* allow missing */, - FALSE /* show deleted */, - FALSE /* show hidden */, scratch_pool)); - - if (local_kind == svn_node_unknown || local_kind == svn_node_none) - SVN_ERR(svn_io_check_path(local_abspath, &local_kind, scratch_pool)); - } - else if (operation == svn_wc_operation_update || - operation == svn_wc_operation_switch) - { - /* For updates, the left version corresponds to the pre-update state. */ - if (left_version) - local_kind = left_version->node_kind; - else - { - /* No left version is available, so the conflict was flagged - * because of a locally added node which was not part of the - * BASE tree before the update. */ - SVN_ERR(svn_wc__db_read_kind(&local_kind, db, local_abspath, - TRUE /* allow missing */, - TRUE /* show deleted */, - FALSE /* show hidden */, scratch_pool)); - if (local_kind == svn_node_unknown || local_kind == svn_node_none) - SVN_ERR(svn_io_check_path(local_abspath, &local_kind, - scratch_pool)); - } + /* We have nothing locally to take the kind from */ + local_kind = left_version->node_kind; } else - SVN_ERR_MALFUNCTION(); + local_kind = node_kind; *desc = svn_wc_conflict_description_create_tree2(local_abspath, local_kind, operation, @@ -1863,6 +1832,7 @@ resolve_tree_conflict_on_node(svn_boolea svn_error_t * svn_wc__conflict_invoke_resolver(svn_wc__db_t *db, const char *local_abspath, + svn_node_kind_t kind, const svn_skel_t *conflict_skel, const apr_array_header_t *merge_options, svn_wc_conflict_resolver_func2_t resolver_func, @@ -1939,7 +1909,7 @@ svn_wc__conflict_invoke_resolver(svn_wc_ SVN_ERR(cancel_func(cancel_baton)); SVN_ERR(generate_propconflict(&conflict_remains, - db, local_abspath, + db, local_abspath, kind, operation, left_version, right_version, @@ -1984,7 +1954,7 @@ svn_wc__conflict_invoke_resolver(svn_wc_ scratch_pool, scratch_pool)); SVN_ERR(read_text_conflict_desc(&desc, - db, local_abspath, conflict_skel, FALSE, + db, local_abspath, conflict_skel, svn_prop_get_value(props, SVN_PROP_MIME_TYPE), operation, left_version, right_version, @@ -2029,9 +1999,14 @@ svn_wc__conflict_invoke_resolver(svn_wc_ svn_wc_conflict_result_t *result; svn_wc_conflict_description2_t *desc; svn_boolean_t resolved; + svn_node_kind_t node_kind; + + SVN_ERR(svn_wc__db_read_kind(&node_kind, db, local_abspath, TRUE, + TRUE, FALSE, scratch_pool)); SVN_ERR(read_tree_conflict_desc(&desc, - db, local_abspath, conflict_skel, + db, local_abspath, node_kind, + conflict_skel, operation, left_version, right_version, scratch_pool, scratch_pool)); @@ -2085,7 +2060,7 @@ read_prop_conflict_descs(apr_array_heade apr_pool_t *result_pool, apr_pool_t *scratch_pool) { - const char *prop_reject_file; + const char *prop_reject_abspath; apr_hash_t *base_props; apr_hash_t *my_props; apr_hash_t *their_old_props; @@ -2093,8 +2068,16 @@ read_prop_conflict_descs(apr_array_heade apr_hash_t *conflicted_props; apr_hash_index_t *hi; apr_pool_t *iterpool; + svn_boolean_t prop_conflicted; - SVN_ERR(svn_wc__conflict_read_prop_conflict(&prop_reject_file, + SVN_ERR(svn_wc__conflict_read_info(&operation, NULL, NULL, &prop_conflicted, + NULL, db, local_abspath, conflict_skel, + scratch_pool, scratch_pool)); + + if (!prop_conflicted) + return SVN_NO_ERROR; + + SVN_ERR(svn_wc__conflict_read_prop_conflict(&prop_reject_abspath, &my_props, &their_old_props, &their_props, @@ -2103,7 +2086,9 @@ read_prop_conflict_descs(apr_array_heade conflict_skel, scratch_pool, scratch_pool)); - if ((! create_tempfiles) || apr_hash_count(conflicted_props) == 0) + prop_reject_abspath = apr_pstrdup(result_pool, prop_reject_abspath); + + if (apr_hash_count(conflicted_props) == 0) { /* Legacy prop conflict with only a .reject file. */ svn_wc_conflict_description2_t *desc; @@ -2114,7 +2099,7 @@ read_prop_conflict_descs(apr_array_heade /* ### For property conflicts, cd2 stores prop_reject_abspath in * ### their_abspath, and stores theirs_abspath in merged_file. */ - desc->prop_reject_abspath = apr_pstrdup(result_pool, prop_reject_file); + desc->prop_reject_abspath = prop_reject_abspath; /* in result_pool */ desc->their_abspath = desc->prop_reject_abspath; desc->operation = operation; @@ -2126,8 +2111,11 @@ read_prop_conflict_descs(apr_array_heade return SVN_NO_ERROR; } - SVN_ERR(svn_wc__db_read_pristine_props(&base_props, db, local_abspath, - result_pool, scratch_pool)); + if (operation == svn_wc_operation_merge) + SVN_ERR(svn_wc__db_read_pristine_props(&base_props, db, local_abspath, + result_pool, scratch_pool)); + else + base_props = NULL; iterpool = svn_pool_create(scratch_pool); for (hi = apr_hash_first(scratch_pool, conflicted_props); hi; @@ -2174,22 +2162,26 @@ read_prop_conflict_descs(apr_array_heade /* ### For property conflicts, cd2 stores prop_reject_abspath in * ### their_abspath, and stores theirs_abspath in merged_file. */ - desc->prop_reject_abspath = apr_pstrdup(result_pool, prop_reject_file); + desc->prop_reject_abspath = prop_reject_abspath; /* in result_pool */ desc->their_abspath = desc->prop_reject_abspath; - desc->prop_value_base = svn_hash_gets(base_props, propname); + desc->prop_value_base = base_props ? svn_hash_gets(base_props, propname) + : desc->prop_value_incoming_old; if (my_value) { svn_stream_t *s; apr_size_t len; - SVN_ERR(svn_stream_open_unique(&s, &desc->my_abspath, NULL, - svn_io_file_del_on_pool_cleanup, - result_pool, iterpool)); - len = my_value->len; - SVN_ERR(svn_stream_write(s, my_value->data, &len)); - SVN_ERR(svn_stream_close(s)); + if (create_tempfiles) + { + SVN_ERR(svn_stream_open_unique(&s, &desc->my_abspath, NULL, + svn_io_file_del_on_pool_cleanup, + result_pool, iterpool)); + len = my_value->len; + SVN_ERR(svn_stream_write(s, my_value->data, &len)); + SVN_ERR(svn_stream_close(s)); + } desc->prop_value_working = svn_string_dup(my_value, result_pool); } @@ -2201,12 +2193,15 @@ read_prop_conflict_descs(apr_array_heade /* ### For property conflicts, cd2 stores prop_reject_abspath in * ### their_abspath, and stores theirs_abspath in merged_file. */ - SVN_ERR(svn_stream_open_unique(&s, &desc->merged_file, NULL, - svn_io_file_del_on_pool_cleanup, - result_pool, iterpool)); - len = their_value->len; - SVN_ERR(svn_stream_write(s, their_value->data, &len)); - SVN_ERR(svn_stream_close(s)); + if (create_tempfiles) + { + SVN_ERR(svn_stream_open_unique(&s, &desc->merged_file, NULL, + svn_io_file_del_on_pool_cleanup, + result_pool, iterpool)); + len = their_value->len; + SVN_ERR(svn_stream_write(s, their_value->data, &len)); + SVN_ERR(svn_stream_close(s)); + } desc->prop_value_incoming_new = svn_string_dup(their_value, result_pool); } @@ -2216,12 +2211,15 @@ read_prop_conflict_descs(apr_array_heade svn_stream_t *s; apr_size_t len; - SVN_ERR(svn_stream_open_unique(&s, &desc->base_abspath, NULL, - svn_io_file_del_on_pool_cleanup, - result_pool, iterpool)); - len = old_value->len; - SVN_ERR(svn_stream_write(s, old_value->data, &len)); - SVN_ERR(svn_stream_close(s)); + if (create_tempfiles) + { + SVN_ERR(svn_stream_open_unique(&s, &desc->base_abspath, NULL, + svn_io_file_del_on_pool_cleanup, + result_pool, iterpool)); + len = old_value->len; + SVN_ERR(svn_stream_write(s, old_value->data, &len)); + SVN_ERR(svn_stream_close(s)); + } desc->prop_value_incoming_old = svn_string_dup(old_value, result_pool); } @@ -2235,13 +2233,15 @@ read_prop_conflict_descs(apr_array_heade svn_error_t * svn_wc__read_conflicts(const apr_array_header_t **conflicts, + svn_skel_t **conflict_skel, svn_wc__db_t *db, const char *local_abspath, svn_boolean_t create_tempfiles, + svn_boolean_t only_tree_conflict, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { - svn_skel_t *conflict_skel; + svn_skel_t *the_conflict_skel; apr_array_header_t *cflcts; svn_boolean_t prop_conflicted; svn_boolean_t text_conflicted; @@ -2250,11 +2250,20 @@ svn_wc__read_conflicts(const apr_array_h const apr_array_header_t *locations; const svn_wc_conflict_version_t *left_version = NULL; const svn_wc_conflict_version_t *right_version = NULL; - - SVN_ERR(svn_wc__db_read_conflict(&conflict_skel, db, local_abspath, - scratch_pool, scratch_pool)); + svn_node_kind_t node_kind; + apr_hash_t *props; if (!conflict_skel) + conflict_skel = &the_conflict_skel; + + SVN_ERR(svn_wc__db_read_conflict(conflict_skel, &node_kind, &props, + db, local_abspath, + (conflict_skel == &the_conflict_skel) + ? scratch_pool + : result_pool, + scratch_pool)); + + if (!*conflict_skel) { /* Some callers expect not NULL */ *conflicts = apr_array_make(result_pool, 0, @@ -2264,7 +2273,7 @@ svn_wc__read_conflicts(const apr_array_h SVN_ERR(svn_wc__conflict_read_info(&operation, &locations, &text_conflicted, &prop_conflicted, &tree_conflicted, - db, local_abspath, conflict_skel, + db, local_abspath, *conflict_skel, result_pool, scratch_pool)); cflcts = apr_array_make(result_pool, 4, @@ -2275,25 +2284,23 @@ svn_wc__read_conflicts(const apr_array_h if (locations && locations->nelts > 1) right_version = APR_ARRAY_IDX(locations, 1, const svn_wc_conflict_version_t *); - if (prop_conflicted) + if (prop_conflicted && !only_tree_conflict) { - svn_node_kind_t node_kind - = left_version ? left_version->node_kind : svn_node_unknown; - SVN_ERR(read_prop_conflict_descs(cflcts, - db, local_abspath, conflict_skel, + db, local_abspath, *conflict_skel, create_tempfiles, node_kind, operation, left_version, right_version, result_pool, scratch_pool)); } - if (text_conflicted) + if (text_conflicted && !only_tree_conflict) { svn_wc_conflict_description2_t *desc; SVN_ERR(read_text_conflict_desc(&desc, - db, local_abspath, conflict_skel, - FALSE /*is_binary*/, NULL /*mime_type*/, + db, local_abspath, *conflict_skel, + svn_prop_get_value(props, + SVN_PROP_MIME_TYPE), operation, left_version, right_version, result_pool, scratch_pool)); APR_ARRAY_PUSH(cflcts, svn_wc_conflict_description2_t *) = desc; @@ -2304,7 +2311,8 @@ svn_wc__read_conflicts(const apr_array_h svn_wc_conflict_description2_t *desc; SVN_ERR(read_tree_conflict_desc(&desc, - db, local_abspath, conflict_skel, + db, local_abspath, node_kind, + *conflict_skel, operation, left_version, right_version, result_pool, scratch_pool)); @@ -2357,9 +2365,11 @@ static svn_error_t * resolve_prop_conflict_on_node(svn_boolean_t *did_resolve, svn_wc__db_t *db, const char *local_abspath, + svn_skel_t *conflicts, const char *conflicted_propname, svn_wc_conflict_choice_t conflict_choice, const char *merged_file, + const svn_string_t *merged_value, svn_cancel_func_t cancel_func, void *cancel_baton, apr_pool_t *scratch_pool) @@ -2372,18 +2382,13 @@ resolve_prop_conflict_on_node(svn_boolea apr_hash_t *old_props; apr_hash_t *resolve_from = NULL; svn_skel_t *work_items = NULL; - svn_skel_t *conflicts; svn_wc_operation_t operation; svn_boolean_t prop_conflicted; + apr_hash_t *actual_props; + svn_boolean_t resolved_all, resolved_all_prop; *did_resolve = FALSE; - SVN_ERR(svn_wc__db_read_conflict(&conflicts, db, local_abspath, - scratch_pool, scratch_pool)); - - if (!conflicts) - return SVN_NO_ERROR; - SVN_ERR(svn_wc__conflict_read_info(&operation, NULL, NULL, &prop_conflicted, NULL, db, local_abspath, conflicts, scratch_pool, scratch_pool)); @@ -2396,12 +2401,35 @@ resolve_prop_conflict_on_node(svn_boolea db, local_abspath, conflicts, scratch_pool, scratch_pool)); + if (!conflicted_props) + { + /* We have a pre 1.8 property conflict. Just mark it resolved */ + + SVN_ERR(remove_artifact_file_if_exists(&work_items, did_resolve, + db, local_abspath, prop_reject_file, + scratch_pool, scratch_pool)); + SVN_ERR(svn_wc__db_op_mark_resolved(db, local_abspath, FALSE, TRUE, FALSE, + work_items, scratch_pool)); + SVN_ERR(svn_wc__wq_run(db, local_abspath, cancel_func, cancel_baton, + scratch_pool)); + return SVN_NO_ERROR; + } + + if (conflicted_propname[0] != '\0' + && !svn_hash_gets(conflicted_props, conflicted_propname)) + { + return SVN_NO_ERROR; /* This property is not conflicted! */ + } + if (operation == svn_wc_operation_merge) SVN_ERR(svn_wc__db_read_pristine_props(&old_props, db, local_abspath, scratch_pool, scratch_pool)); else old_props = their_old_props; + SVN_ERR(svn_wc__db_read_props(&actual_props, db, local_abspath, + scratch_pool, scratch_pool)); + /* We currently handle *_conflict as *_full as this argument is currently always applied for all conflicts on a node at the same time. Giving an error would break some tests that assumed that this would just @@ -2427,21 +2455,23 @@ resolve_prop_conflict_on_node(svn_boolea resolve_from = their_props; break; case svn_wc_conflict_choose_merged: - if (merged_file && conflicted_propname[0] != '\0') + if ((merged_file || merged_value) && conflicted_propname[0] != '\0') { - apr_hash_t *actual_props; - svn_stream_t *stream; - svn_string_t *merged_propval; + resolve_from = apr_hash_copy(scratch_pool, actual_props); - SVN_ERR(svn_wc__db_read_props(&actual_props, db, local_abspath, - scratch_pool, scratch_pool)); - resolve_from = actual_props; + if (!merged_value) + { + svn_stream_t *stream; + svn_string_t *merged_propval; - SVN_ERR(svn_stream_open_readonly(&stream, merged_file, - scratch_pool, scratch_pool)); - SVN_ERR(svn_string_from_stream(&merged_propval, stream, - scratch_pool, scratch_pool)); - svn_hash_sets(resolve_from, conflicted_propname, merged_propval); + SVN_ERR(svn_stream_open_readonly(&stream, merged_file, + scratch_pool, scratch_pool)); + SVN_ERR(svn_string_from_stream(&merged_propval, stream, + scratch_pool, scratch_pool)); + + merged_value = merged_propval; + } + svn_hash_sets(resolve_from, conflicted_propname, merged_value); } else resolve_from = NULL; @@ -2451,15 +2481,26 @@ resolve_prop_conflict_on_node(svn_boolea _("Invalid 'conflict_result' argument")); } - if (conflicted_props && apr_hash_count(conflicted_props) && resolve_from) + + if (resolve_from) { apr_hash_index_t *hi; - apr_hash_t *actual_props; + apr_hash_t *apply_on_props; - SVN_ERR(svn_wc__db_read_props(&actual_props, db, local_abspath, - scratch_pool, scratch_pool)); + if (conflicted_propname[0] == '\0') + { + /* Apply to all conflicted properties */ + apply_on_props = conflicted_props; + } + else + { + /* Apply to a single property */ + apply_on_props = apr_hash_make(scratch_pool); + svn_hash_sets(apply_on_props, conflicted_propname, ""); + } - for (hi = apr_hash_first(scratch_pool, conflicted_props); + /* Apply the selected changes */ + for (hi = apr_hash_first(scratch_pool, apply_on_props); hi; hi = apr_hash_next(hi)) { @@ -2470,28 +2511,67 @@ resolve_prop_conflict_on_node(svn_boolea svn_hash_sets(actual_props, propname, new_value); } - SVN_ERR(svn_wc__db_op_set_props(db, local_abspath, actual_props, - FALSE, NULL, NULL, - scratch_pool)); } + /*else the user accepted the properties as-is */ - /* Legacy behavior: Only report property conflicts as resolved when the - property reject file exists + /* This function handles conflicted_propname "" as resolving + all property conflicts... Just what we need here */ + SVN_ERR(svn_wc__conflict_skel_resolve(&resolved_all, conflicts, + db, local_abspath, + FALSE, conflicted_propname, + FALSE, + scratch_pool, scratch_pool)); - If not the UI shows the conflict as already resolved - (and in this case we just remove the in-db conflict) */ + if (!resolved_all) + { + /* Are there still property conflicts left? (or only...) */ + SVN_ERR(svn_wc__conflict_read_info(NULL, NULL, NULL, &prop_conflicted, + NULL, db, local_abspath, conflicts, + scratch_pool, scratch_pool)); - { - svn_skel_t *work_item; + resolved_all_prop = (! prop_conflicted); + } + else + { + resolved_all_prop = TRUE; + conflicts = NULL; + } - SVN_ERR(remove_artifact_file_if_exists(&work_item, did_resolve, - db, local_abspath, prop_reject_file, - scratch_pool, scratch_pool)); - work_items = svn_wc__wq_merge(work_items, work_item, scratch_pool); - } + if (resolved_all_prop) + { + /* Legacy behavior: Only report property conflicts as resolved when the + property reject file exists + + If not the UI shows the conflict as already resolved + (and in this case we just remove the in-db conflict) */ + SVN_ERR(remove_artifact_file_if_exists(&work_items, did_resolve, + db, local_abspath, + prop_reject_file, + scratch_pool, scratch_pool)); + } + else + { + /* Create a new prej file, based on the remaining conflicts */ + SVN_ERR(svn_wc__wq_build_prej_install(&work_items, + db, local_abspath, + scratch_pool, scratch_pool)); + *did_resolve = TRUE; /* We resolved a property conflict */ + } + + /* This installs the updated conflict skel */ + SVN_ERR(svn_wc__db_op_set_props(db, local_abspath, actual_props, + FALSE, conflicts, work_items, + scratch_pool)); + + if (resolved_all) + { + /* Remove the whole conflict. Should probably be integrated + into the op_set_props() call */ + SVN_ERR(svn_wc__db_op_mark_resolved(db, local_abspath, + FALSE, TRUE, FALSE, + NULL, scratch_pool)); + } - SVN_ERR(svn_wc__db_op_mark_resolved(db, local_abspath, FALSE, TRUE, FALSE, - work_items, scratch_pool)); SVN_ERR(svn_wc__wq_run(db, local_abspath, cancel_func, cancel_baton, scratch_pool)); @@ -2555,19 +2635,31 @@ resolve_tree_conflict_on_node(svn_boolea { /* Break moves for any children moved out of this directory, * and leave this directory deleted. */ - SVN_ERR(svn_wc__db_resolve_break_moved_away_children( - db, local_abspath, src_op_root_abspath, - notify_func, notify_baton, - scratch_pool)); + + if (action != svn_wc_conflict_action_delete) + { + SVN_ERR(svn_wc__db_op_break_moved_away( + db, local_abspath, src_op_root_abspath, TRUE, + notify_func, notify_baton, + scratch_pool)); + *did_resolve = TRUE; + return SVN_NO_ERROR; /* Marked resolved by function*/ + } + /* else # The move is/moves are already broken */ + + *did_resolve = TRUE; } else if (conflict_choice == svn_wc_conflict_choose_mine_conflict) { - /* Raised moved-away conflicts on any children moved out of - * this directory, and leave this directory deleted. + svn_skel_t *new_conflicts; + + /* Raise moved-away conflicts on any children moved out of + * this directory, and leave this directory as-is. + * * The newly conflicted moved-away children will be updated * if they are resolved with 'mine_conflict' as well. */ - err = svn_wc__db_resolve_delete_raise_moved_away( + err = svn_wc__db_op_raise_moved_away( db, local_abspath, notify_func, notify_baton, scratch_pool); @@ -2576,7 +2668,8 @@ resolve_tree_conflict_on_node(svn_boolea const char *dup_abspath; if (!resolve_later - || err->apr_err != SVN_ERR_WC_OBSTRUCTED_UPDATE) + || (err->apr_err != SVN_ERR_WC_OBSTRUCTED_UPDATE + && err->apr_err != SVN_ERR_WC_FOUND_CONFLICT)) return svn_error_trace(err); svn_error_clear(err); @@ -2587,8 +2680,44 @@ resolve_tree_conflict_on_node(svn_boolea return SVN_NO_ERROR; /* Retry after other conflicts */ } - else - *did_resolve = TRUE; + + /* We might now have a moved-away on *this* path, let's + try to resolve that directly if that is the case */ + SVN_ERR(svn_wc__db_read_conflict(&new_conflicts, NULL, NULL, + db, local_abspath, + scratch_pool, scratch_pool)); + + if (new_conflicts) + SVN_ERR(svn_wc__conflict_read_info(NULL, NULL, NULL, NULL, + &tree_conflicted, + db, local_abspath, + new_conflicts, + scratch_pool, + scratch_pool)); + + if (!new_conflicts || !tree_conflicted) + { + /* TC is marked resolved by calling + svn_wc__db_resolve_delete_raise_moved_away */ + *did_resolve = TRUE; + return SVN_NO_ERROR; + } + + SVN_ERR(svn_wc__conflict_read_tree_conflict(&reason, &action, + &src_op_root_abspath, + db, local_abspath, + new_conflicts, + scratch_pool, + scratch_pool)); + + if (reason != svn_wc_conflict_reason_moved_away) + { + *did_resolve = TRUE; + return SVN_NO_ERROR; /* We fixed one, but... */ + } + + conflicts = new_conflicts; + /* Fall through in moved_away handling */ } else return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, @@ -2599,8 +2728,9 @@ resolve_tree_conflict_on_node(svn_boolea svn_dirent_local_style(local_abspath, scratch_pool)); } - else if (reason == svn_wc_conflict_reason_moved_away - && action == svn_wc_conflict_action_edit) + + if (reason == svn_wc_conflict_reason_moved_away + && action == svn_wc_conflict_action_edit) { /* After updates, we can resolve local moved-away * vs. any incoming change, either by updating the @@ -2620,7 +2750,8 @@ resolve_tree_conflict_on_node(svn_boolea const char *dup_abspath; if (!resolve_later - || err->apr_err != SVN_ERR_WC_OBSTRUCTED_UPDATE) + || (err->apr_err != SVN_ERR_WC_OBSTRUCTED_UPDATE + && err->apr_err != SVN_ERR_WC_FOUND_CONFLICT)) return svn_error_trace(err); svn_error_clear(err); @@ -2640,15 +2771,12 @@ resolve_tree_conflict_on_node(svn_boolea * working copy state instead of updating the move. * Else the move would be left in an invalid state. */ - /* ### This breaks the move but leaves the conflict - ### involving the move until - ### svn_wc__db_op_mark_resolved. */ - SVN_ERR(svn_wc__db_resolve_break_moved_away(db, local_abspath, - src_op_root_abspath, - notify_func, - notify_baton, - scratch_pool)); + SVN_ERR(svn_wc__db_op_break_moved_away(db, local_abspath, + src_op_root_abspath, TRUE, + notify_func, notify_baton, + scratch_pool)); *did_resolve = TRUE; + return SVN_NO_ERROR; /* Conflict is marked resolved */ } else return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, @@ -2727,7 +2855,8 @@ svn_wc__mark_resolved_text_conflict(svn_ svn_skel_t *work_items; svn_skel_t *conflict; - SVN_ERR(svn_wc__db_read_conflict(&conflict, db, local_abspath, + SVN_ERR(svn_wc__db_read_conflict(&conflict, NULL, NULL, + db, local_abspath, scratch_pool, scratch_pool)); if (!conflict) @@ -2754,11 +2883,20 @@ svn_wc__mark_resolved_prop_conflicts(svn apr_pool_t *scratch_pool) { svn_boolean_t ignored_result; + svn_skel_t *conflicts; + + SVN_ERR(svn_wc__db_read_conflict(&conflicts, NULL, NULL, + db, local_abspath, + scratch_pool, scratch_pool)); + + if (!conflicts) + return SVN_NO_ERROR; return svn_error_trace(resolve_prop_conflict_on_node( &ignored_result, - db, local_abspath, "", - svn_wc_conflict_choose_merged, NULL, + db, local_abspath, conflicts, "", + svn_wc_conflict_choose_merged, + NULL, NULL, NULL, NULL, scratch_pool)); } @@ -2778,6 +2916,7 @@ struct conflict_status_walker_baton void *cancel_baton; svn_wc_notify_func2_t notify_func; void *notify_baton; + svn_boolean_t resolved_one; apr_hash_t *resolve_later; }; @@ -2832,10 +2971,10 @@ conflict_status_walker(void *baton, iterpool = svn_pool_create(scratch_pool); - SVN_ERR(svn_wc__db_read_conflict(&conflict, db, local_abspath, - scratch_pool, scratch_pool)); - - SVN_ERR(svn_wc__read_conflicts(&conflicts, db, local_abspath, TRUE, + SVN_ERR(svn_wc__read_conflicts(&conflicts, &conflict, + db, local_abspath, + (cswb->conflict_func != NULL) /* tmp files */, + FALSE /* only tree conflicts */, scratch_pool, iterpool)); for (i = 0; i < conflicts->nelts; i++) @@ -2848,7 +2987,10 @@ conflict_status_walker(void *baton, cd = APR_ARRAY_IDX(conflicts, i, const svn_wc_conflict_description2_t *); - if ((cd->kind == svn_wc_conflict_kind_property && !cswb->resolve_prop) + if ((cd->kind == svn_wc_conflict_kind_property + && (!cswb->resolve_prop + || (*cswb->resolve_prop != '\0' + && strcmp(cswb->resolve_prop, cd->property_name) != 0))) || (cd->kind == svn_wc_conflict_kind_text && !cswb->resolve_text) || (cd->kind == svn_wc_conflict_kind_tree && !cswb->resolve_tree)) { @@ -2877,8 +3019,6 @@ conflict_status_walker(void *baton, switch (cd->kind) { case svn_wc_conflict_kind_tree: - if (!cswb->resolve_tree) - break; SVN_ERR(resolve_tree_conflict_on_node(&did_resolve, db, local_abspath, conflict, @@ -2895,9 +3035,6 @@ conflict_status_walker(void *baton, break; case svn_wc_conflict_kind_text: - if (!cswb->resolve_text) - break; - SVN_ERR(build_text_conflict_resolve_items( &work_items, &resolved, @@ -2921,23 +3058,18 @@ conflict_status_walker(void *baton, break; case svn_wc_conflict_kind_property: - if (!cswb->resolve_prop) - break; - - if (*cswb->resolve_prop != '\0' && - strcmp(cswb->resolve_prop, cd->property_name) != 0) - { - break; /* This is not the property we want to resolve. */ - } - SVN_ERR(resolve_prop_conflict_on_node(&did_resolve, db, local_abspath, + conflict, cd->property_name, my_choice, result ? result->merged_file : NULL, + result + ? result->merged_value + : NULL, cswb->cancel_func, cswb->cancel_baton, iterpool)); @@ -2960,6 +3092,9 @@ conflict_status_walker(void *baton, iterpool), iterpool); + if (resolved) + cswb->resolved_one = TRUE; + svn_pool_destroy(iterpool); return SVN_NO_ERROR; @@ -2981,33 +3116,11 @@ svn_wc__resolve_conflicts(svn_wc_context void *notify_baton, apr_pool_t *scratch_pool) { - svn_node_kind_t kind; - svn_boolean_t conflicted; struct conflict_status_walker_baton cswb; apr_pool_t *iterpool = NULL; svn_error_t *err; - /* ### the underlying code does NOT support resolving individual - ### properties. bail out if the caller tries it. */ - if (resolve_prop != NULL && *resolve_prop != '\0') - return svn_error_create(SVN_ERR_INCORRECT_PARAMS, NULL, - U_("Resolving a single property is not (yet) " - "supported.")); - - /* ### Just a versioned check? */ - /* Conflicted is set to allow invoking on actual only nodes */ - SVN_ERR(svn_wc__db_read_info(NULL, &kind, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, &conflicted, - NULL, NULL, NULL, NULL, NULL, NULL, - wc_ctx->db, local_abspath, - scratch_pool, scratch_pool)); - - /* When the implementation still used the entry walker, depth - unknown was translated to infinity. */ - if (kind != svn_node_dir) - depth = svn_depth_empty; - else if (depth == svn_depth_unknown) + if (depth == svn_depth_unknown) depth = svn_depth_infinity; cswb.db = wc_ctx->db; @@ -3025,6 +3138,7 @@ svn_wc__resolve_conflicts(svn_wc_context cswb.notify_func = notify_func; cswb.notify_baton = notify_baton; + cswb.resolved_one = FALSE; cswb.resolve_later = (depth != svn_depth_empty) ? apr_hash_make(scratch_pool) : NULL; @@ -3047,10 +3161,12 @@ svn_wc__resolve_conflicts(svn_wc_context cancel_func, cancel_baton, scratch_pool); + /* If we got new tree conflicts (or delayed conflicts) during the initial + walk, we now walk them one by one as closure. */ while (!err && cswb.resolve_later && apr_hash_count(cswb.resolve_later)) { apr_hash_index_t *hi; - svn_boolean_t cleared_one = FALSE; + svn_wc_status3_t *status = NULL; const char *tc_abspath = NULL; if (iterpool) @@ -3060,31 +3176,64 @@ svn_wc__resolve_conflicts(svn_wc_context hi = apr_hash_first(scratch_pool, cswb.resolve_later); cswb.resolve_later = apr_hash_make(scratch_pool); + cswb.resolved_one = FALSE; for (; hi && !err; hi = apr_hash_next(hi)) { - tc_abspath = apr_hash_this_key(hi); + const char *relpath; svn_pool_clear(iterpool); - /* ### TODO: Check if tc_abspath falls within selected depth */ + tc_abspath = apr_hash_this_key(hi); + + if (cancel_func) + SVN_ERR(cancel_func(cancel_baton)); + + relpath = svn_dirent_skip_ancestor(local_abspath, + tc_abspath); + + if (!relpath + || (depth >= svn_depth_empty + && depth < svn_depth_infinity + && strchr(relpath, '/'))) + { + continue; + } + + SVN_ERR(svn_wc_status3(&status, wc_ctx, tc_abspath, + iterpool, iterpool)); - err = svn_wc_walk_status(wc_ctx, tc_abspath, svn_depth_empty, - FALSE, FALSE, TRUE, NULL, - conflict_status_walker, &cswb, - cancel_func, cancel_baton, - iterpool); + if (depth == svn_depth_files + && status->kind == svn_node_dir) + continue; - if (!err && !svn_hash_gets(cswb.resolve_later, tc_abspath)) - cleared_one = TRUE; + err = svn_error_trace(conflict_status_walker(&cswb, tc_abspath, + status, scratch_pool)); } - if (!cleared_one && !err) + /* None of the remaining conflicts got resolved, and non did provide + an error... + + We can fix that if we disable the 'resolve_later' option... + */ + if (!cswb.resolved_one && !err && tc_abspath + && apr_hash_count(cswb.resolve_later)) { - /* Return the error on one of the paths: The last one. */ + /* Run the last resolve operation again. We still have status + and tc_abspath for that one. */ + + cswb.resolve_later = NULL; /* Produce proper error! */ + + /* Recreate the error */ + err = svn_error_trace(conflict_status_walker(&cswb, tc_abspath, + status, scratch_pool)); + + SVN_ERR_ASSERT(err != NULL); + err = svn_error_createf( - SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, + SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, err, _("Unable to resolve pending conflict on '%s'"), svn_dirent_local_style(tc_abspath, scratch_pool)); + break; } } @@ -3141,7 +3290,7 @@ svn_wc_create_conflict_result(svn_wc_con { svn_wc_conflict_result_t *result = apr_pcalloc(pool, sizeof(*result)); result->choice = choice; - result->merged_file = merged_file; + result->merged_file = apr_pstrdup(pool, merged_file); result->save_merged = FALSE; /* If we add more fields to svn_wc_conflict_result_t, add them here. */ Modified: subversion/branches/fsx-1.10/subversion/libsvn_wc/conflicts.h URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_wc/conflicts.h?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_wc/conflicts.h (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_wc/conflicts.h Sun Jun 14 20:58:10 2015 @@ -419,6 +419,7 @@ svn_wc__conflict_create_markers(svn_skel svn_error_t * svn_wc__conflict_invoke_resolver(svn_wc__db_t *db, const char *local_abspath, + svn_node_kind_t kind, const svn_skel_t *conflict_skel, const apr_array_header_t *merge_options, svn_wc_conflict_resolver_func2_t resolver_func, Modified: subversion/branches/fsx-1.10/subversion/libsvn_wc/copy.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_wc/copy.c?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_wc/copy.c (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_wc/copy.c Sun Jun 14 20:58:10 2015 @@ -258,8 +258,9 @@ copy_versioned_file(svn_wc__db_t *db, svn_error_t *err; /* Is there a text conflict at the source path? */ - SVN_ERR(svn_wc__db_read_conflict(&conflict, db, src_abspath, - scratch_pool, scratch_pool)); + SVN_ERR(svn_wc__db_read_conflict(&conflict, NULL, NULL, + db, src_abspath, + scratch_pool, scratch_pool)); err = svn_wc__conflict_read_text_conflict(&conflict_working, NULL, NULL, db, src_abspath, conflict, @@ -945,7 +946,8 @@ remove_node_conflict_markers(svn_wc__db_ { svn_skel_t *conflict; - SVN_ERR(svn_wc__db_read_conflict(&conflict, db, src_abspath, + SVN_ERR(svn_wc__db_read_conflict(&conflict, NULL, NULL, + db, src_abspath, scratch_pool, scratch_pool)); /* Do we have conflict markers that should be removed? */ @@ -965,18 +967,18 @@ remove_node_conflict_markers(svn_wc__db_ { const char *marker_abspath; const char *child_relpath; - const char *child_abpath; + const char *child_abspath; marker_abspath = APR_ARRAY_IDX(markers, i, const char *); - child_relpath = svn_dirent_is_child(src_dir, marker_abspath, NULL); + child_relpath = svn_dirent_skip_ancestor(src_dir, marker_abspath); if (child_relpath) { - child_abpath = svn_dirent_join(dst_dir, child_relpath, - scratch_pool); + child_abspath = svn_dirent_join(dst_dir, child_relpath, + scratch_pool); - SVN_ERR(svn_io_remove_file2(child_abpath, TRUE, scratch_pool)); + SVN_ERR(svn_io_remove_file2(child_abspath, TRUE, scratch_pool)); } } } @@ -996,7 +998,9 @@ remove_node_conflict_markers(svn_wc__db_ static svn_error_t * remove_all_conflict_markers(svn_wc__db_t *db, const char *src_dir_abspath, - const char *wc_dir_abspath, + const char *dst_dir_abspath, + svn_cancel_func_t cancel_func, + void *cancel_baton, apr_pool_t *scratch_pool) { apr_pool_t *iterpool = svn_pool_create(scratch_pool); @@ -1020,13 +1024,16 @@ remove_all_conflict_markers(svn_wc__db_t const char *name = apr_hash_this_key(hi); struct svn_wc__db_info_t *info = apr_hash_this_val(hi); + if (cancel_func) + SVN_ERR(cancel_func(cancel_baton)); + if (info->conflicted) { svn_pool_clear(iterpool); SVN_ERR(remove_node_conflict_markers( db, svn_dirent_join(src_dir_abspath, name, iterpool), - svn_dirent_join(wc_dir_abspath, name, iterpool), + svn_dirent_join(dst_dir_abspath, name, iterpool), iterpool)); } if (info->kind == svn_node_dir) @@ -1035,7 +1042,8 @@ remove_all_conflict_markers(svn_wc__db_t SVN_ERR(remove_all_conflict_markers( db, svn_dirent_join(src_dir_abspath, name, iterpool), - svn_dirent_join(wc_dir_abspath, name, iterpool), + svn_dirent_join(dst_dir_abspath, name, iterpool), + cancel_func, cancel_baton, iterpool)); } } @@ -1093,7 +1101,25 @@ svn_wc__move2(svn_wc_context_t *wc_ctx, is still in a valid state. So be careful when switching this over to the workqueue. */ if (!metadata_only) - SVN_ERR(svn_io_file_rename(src_abspath, dst_abspath, scratch_pool)); + { + svn_error_t *err; + + err = svn_error_trace(svn_io_file_rename(src_abspath, dst_abspath, + scratch_pool)); + + /* Let's try if we can keep wc.db consistent even when the move + fails. Deleting the target is a wc.db only operation, while + going forward (delaying the error) would try to change + conflict markers, which might also fail. */ + if (err) + return svn_error_trace( + svn_error_compose_create( + err, + svn_wc__db_op_delete(wc_ctx->db, dst_abspath, NULL, TRUE, + NULL, NULL, cancel_func, cancel_baton, + NULL, NULL, + scratch_pool))); + } SVN_ERR(svn_wc__db_read_info(NULL, &kind, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -1105,11 +1131,20 @@ svn_wc__move2(svn_wc_context_t *wc_ctx, if (kind == svn_node_dir) SVN_ERR(remove_all_conflict_markers(db, src_abspath, dst_abspath, + cancel_func, cancel_baton, scratch_pool)); if (conflicted) - SVN_ERR(remove_node_conflict_markers(db, src_abspath, dst_abspath, - scratch_pool)); + { + /* When we moved a directory, we moved the conflict markers + with the target... if we moved a file we only moved the + file itself and the markers are still in the old location */ + SVN_ERR(remove_node_conflict_markers(db, src_abspath, + (kind == svn_node_dir) + ? dst_abspath + : src_abspath, + scratch_pool)); + } SVN_ERR(svn_wc__db_op_delete(db, src_abspath, record_on_delete ? dst_abspath : NULL, Modified: subversion/branches/fsx-1.10/subversion/libsvn_wc/crop.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_wc/crop.c?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_wc/crop.c (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_wc/crop.c Sun Jun 14 20:58:10 2015 @@ -53,7 +53,7 @@ crop_children(svn_wc__db_t *db, void *notify_baton, svn_cancel_func_t cancel_func, void *cancel_baton, - apr_pool_t *pool) + apr_pool_t *scratch_pool) { const apr_array_header_t *children; apr_pool_t *iterpool; @@ -65,7 +65,7 @@ crop_children(svn_wc__db_t *db, if (cancel_func) SVN_ERR(cancel_func(cancel_baton)); - iterpool = svn_pool_create(pool); + iterpool = svn_pool_create(scratch_pool); if (dir_depth == svn_depth_unknown) dir_depth = svn_depth_infinity; @@ -76,8 +76,8 @@ crop_children(svn_wc__db_t *db, iterpool)); /* Looping over current directory's SVN entries: */ - SVN_ERR(svn_wc__db_read_children(&children, db, local_abspath, pool, - iterpool)); + SVN_ERR(svn_wc__db_base_get_children(&children, db, local_abspath, + scratch_pool, iterpool)); for (i = 0; i < children->nelts; i++) { @@ -86,6 +86,8 @@ crop_children(svn_wc__db_t *db, svn_wc__db_status_t child_status; svn_node_kind_t kind; svn_depth_t child_depth; + svn_boolean_t have_work; + svn_depth_t remove_below; svn_pool_clear(iterpool); @@ -96,86 +98,80 @@ crop_children(svn_wc__db_t *db, NULL,NULL, NULL, NULL, &child_depth, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, &have_work, db, child_abspath, iterpool, iterpool)); - if (child_status == svn_wc__db_status_server_excluded || - child_status == svn_wc__db_status_excluded || - child_status == svn_wc__db_status_not_present) + if (have_work) + { + svn_boolean_t modified, all_deletes; + + if (child_status != svn_wc__db_status_deleted) + continue; /* Leave local additions alone */ + + SVN_ERR(svn_wc__node_has_local_mods(&modified, &all_deletes, + db, child_abspath, FALSE, + cancel_func, cancel_baton, + iterpool)); + + if (modified && !all_deletes) + continue; /* Something interesting is still there */ + } + + remove_below = (kind == svn_node_dir) + ? svn_depth_immediates + : svn_depth_files; + + if ((child_status == svn_wc__db_status_server_excluded || + child_status == svn_wc__db_status_excluded || + child_status == svn_wc__db_status_not_present)) { - svn_depth_t remove_below = (kind == svn_node_dir) - ? svn_depth_immediates - : svn_depth_files; if (new_depth < remove_below) SVN_ERR(svn_wc__db_base_remove(db, child_abspath, FALSE /* keep_as_working */, - FALSE /* queue_deletes */, - FALSE /* remove_locks */, + FALSE, FALSE, SVN_INVALID_REVNUM, NULL, NULL, iterpool)); - continue; + continue; /* No recurse */ } - else if (kind == svn_node_file) + + if (new_depth < remove_below) { - if (new_depth == svn_depth_empty) - SVN_ERR(svn_wc__db_op_remove_node(NULL, - db, child_abspath, - TRUE /* destroy */, - FALSE /* destroy_changes */, - SVN_INVALID_REVNUM, - svn_wc__db_status_not_present, - svn_node_none, - NULL, NULL, + svn_boolean_t modified, all_deletes; + + SVN_ERR(svn_wc__node_has_local_mods(&modified, &all_deletes, + db, child_abspath, FALSE, cancel_func, cancel_baton, iterpool)); - else - continue; - } - else if (kind == svn_node_dir) - { - if (new_depth < svn_depth_immediates) + if (!modified || all_deletes) { - SVN_ERR(svn_wc__db_op_remove_node(NULL, - db, child_abspath, - TRUE /* destroy */, - FALSE /* destroy_changes */, - SVN_INVALID_REVNUM, - svn_wc__db_status_not_present, - svn_node_none, - NULL, NULL, - cancel_func, cancel_baton, - iterpool)); - } - else - { - SVN_ERR(crop_children(db, - child_abspath, - child_depth, - svn_depth_empty, - notify_func, - notify_baton, - cancel_func, - cancel_baton, - iterpool)); - continue; + SVN_ERR(svn_wc__db_base_remove(db, child_abspath, + FALSE, FALSE, FALSE, + SVN_INVALID_REVNUM, + NULL, NULL, iterpool)); + if (notify_func) + { + svn_wc_notify_t *notify; + notify = svn_wc_create_notify(child_abspath, + svn_wc_notify_delete, + iterpool); + (*notify_func)(notify_baton, notify, iterpool); + } + + continue; /* No recurse */ } - } - else - { - return svn_error_createf - (SVN_ERR_NODE_UNKNOWN_KIND, NULL, _("Unknown node kind for '%s'"), - svn_dirent_local_style(child_abspath, iterpool)); + + /* Fall through: recurse:*/ } - if (notify_func) + if (kind == svn_node_dir) { - svn_wc_notify_t *notify; - notify = svn_wc_create_notify(child_abspath, - svn_wc_notify_delete, - iterpool); - (*notify_func)(notify_baton, notify, iterpool); + SVN_ERR(crop_children(db, child_abspath, + child_depth, svn_depth_empty, + notify_func, notify_baton, + cancel_func, cancel_baton, + iterpool)); } } @@ -197,6 +193,8 @@ svn_wc_exclude(svn_wc_context_t *wc_ctx, svn_wc__db_status_t status; svn_node_kind_t kind; svn_revnum_t revision; + svn_depth_t depth; + svn_boolean_t modified, all_deletes; const char *repos_relpath, *repos_root, *repos_uuid; SVN_ERR(svn_wc__db_is_switched(&is_root, &is_switched, NULL, @@ -221,7 +219,7 @@ svn_wc_exclude(svn_wc_context_t *wc_ctx, SVN_ERR(svn_wc__db_read_info(&status, &kind, &revision, &repos_relpath, &repos_root, &repos_uuid, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + &depth, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, wc_ctx->db, local_abspath, @@ -258,29 +256,41 @@ svn_wc_exclude(svn_wc_context_t *wc_ctx, break; /* Ok to exclude */ } - /* Remove all working copy data below local_abspath */ - SVN_ERR(svn_wc__db_op_remove_node(NULL, - wc_ctx->db, local_abspath, - TRUE /* destroy */, - FALSE /* destroy_changes */, - revision, - svn_wc__db_status_excluded, - kind, - NULL, NULL, - cancel_func, cancel_baton, - scratch_pool)); - - SVN_ERR(svn_wc__wq_run(wc_ctx->db, local_abspath, - cancel_func, cancel_baton, - scratch_pool)); - - if (notify_func) - { - svn_wc_notify_t *notify; - notify = svn_wc_create_notify(local_abspath, - svn_wc_notify_exclude, - scratch_pool); - notify_func(notify_baton, notify, scratch_pool); + SVN_ERR(svn_wc__node_has_local_mods(&modified, &all_deletes, + wc_ctx->db, local_abspath, FALSE, + cancel_func, cancel_baton, + scratch_pool)); + + if (!modified || all_deletes) + { + /* Remove all working copy data below local_abspath */ + SVN_ERR(svn_wc__db_base_remove(wc_ctx->db, local_abspath, + FALSE /* keep_working */, + FALSE, TRUE, + revision, + NULL, NULL, + scratch_pool)); + + SVN_ERR(svn_wc__wq_run(wc_ctx->db, local_abspath, + cancel_func, cancel_baton, + scratch_pool)); + + if (notify_func) + { + svn_wc_notify_t *notify; + notify = svn_wc_create_notify(local_abspath, + svn_wc_notify_exclude, + scratch_pool); + notify_func(notify_baton, notify, scratch_pool); + } + } + else + { + /* Do the next best thing: retry below this path */ + SVN_ERR(crop_children(wc_ctx->db, local_abspath, depth, svn_depth_empty, + notify_func, notify_baton, + cancel_func, cancel_baton, + scratch_pool)); } return SVN_NO_ERROR; Modified: subversion/branches/fsx-1.10/subversion/libsvn_wc/delete.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_wc/delete.c?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_wc/delete.c (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_wc/delete.c Sun Jun 14 20:58:10 2015 @@ -135,7 +135,8 @@ create_delete_wq_items(svn_skel_t **work const apr_array_header_t *markers; int i; - SVN_ERR(svn_wc__db_read_conflict(&conflict, db, local_abspath, + SVN_ERR(svn_wc__db_read_conflict(&conflict, NULL, NULL, + db, local_abspath, scratch_pool, scratch_pool)); SVN_ERR(svn_wc__conflict_read_markers(&markers, db, local_abspath, @@ -431,9 +432,6 @@ svn_wc__internal_remove_from_revision_co db, local_abspath, destroy_wf /* destroy_wc */, destroy_wf /* destroy_changes */, - SVN_INVALID_REVNUM, - svn_wc__db_status_not_present, - svn_node_none, NULL, NULL, cancel_func, cancel_baton, scratch_pool)); Modified: subversion/branches/fsx-1.10/subversion/libsvn_wc/deprecated.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_wc/deprecated.c?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_wc/deprecated.c (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_wc/deprecated.c Sun Jun 14 20:58:10 2015 @@ -948,12 +948,12 @@ svn_wc_delete(const char *path, svn_error_t * svn_wc_add_from_disk2(svn_wc_context_t *wc_ctx, const char *local_abspath, - const apr_hash_t *props, + const apr_hash_t *props, svn_wc_notify_func2_t notify_func, void *notify_baton, apr_pool_t *scratch_pool) { - SVN_ERR(svn_wc_add_from_disk3(wc_ctx, local_abspath, NULL, FALSE, + SVN_ERR(svn_wc_add_from_disk3(wc_ctx, local_abspath, props, FALSE, notify_func, notify_baton, scratch_pool)); return SVN_NO_ERROR; } Modified: subversion/branches/fsx-1.10/subversion/libsvn_wc/diff.h URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_wc/diff.h?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_wc/diff.h (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_wc/diff.h Sun Jun 14 20:58:10 2015 @@ -39,7 +39,7 @@ extern "C" { #endif /* __cplusplus */ /* A function to diff locally added and locally copied files. - + Reports the file LOCAL_ABSPATH as ADDED file with relpath RELPATH to PROCESSOR with as parent baton PROCESSOR_PARENT_BATON. @@ -60,7 +60,7 @@ svn_wc__diff_local_only_file(svn_wc__db_ apr_pool_t *scratch_pool); /* A function to diff locally added and locally copied directories. - + Reports the directory LOCAL_ABSPATH and everything below it (limited by DEPTH) as added with relpath RELPATH to PROCESSOR with as parent baton PROCESSOR_PARENT_BATON. Modified: subversion/branches/fsx-1.10/subversion/libsvn_wc/diff_editor.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_wc/diff_editor.c?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_wc/diff_editor.c (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_wc/diff_editor.c Sun Jun 14 20:58:10 2015 @@ -145,6 +145,9 @@ struct dir_baton_t /* TRUE if the node is to be compared with an unrelated node*/ svn_boolean_t ignoring_ancestry; + /* TRUE if the directory was reported incomplete to the repository */ + svn_boolean_t is_incomplete; + /* Processor state */ void *pdb; svn_boolean_t skip; @@ -1051,8 +1054,12 @@ svn_wc__diff_local_only_dir(svn_wc__db_t copyfrom_src->repos_relpath = original_repos_relpath; } + /* svn_wc__db_status_incomplete should never happen, as the result won't be + stable or guaranteed related to what is in the repository for this + revision, but without this it would be hard to diagnose that status... */ assert(kind == svn_node_dir && (status == svn_wc__db_status_normal + || status == svn_wc__db_status_incomplete || status == svn_wc__db_status_added || (status == svn_wc__db_status_deleted && diff_pristine))); @@ -1167,12 +1174,12 @@ svn_wc__diff_local_only_dir(svn_wc__db_t if (!skip) { apr_hash_t *right_props; - if (diff_pristine) - SVN_ERR(svn_wc__db_read_pristine_props(&right_props, db, local_abspath, - scratch_pool, scratch_pool)); + + if (props_mod && !diff_pristine) + SVN_ERR(svn_wc__db_read_props(&right_props, db, local_abspath, + scratch_pool, scratch_pool)); else - SVN_ERR(svn_wc__get_actual_props(&right_props, db, local_abspath, - scratch_pool, scratch_pool)); + right_props = svn_prop_hash_dup(pristine_props, scratch_pool); SVN_ERR(processor->dir_added(relpath, copyfrom_src, @@ -1216,10 +1223,8 @@ handle_local_only(struct dir_baton_t *pb switch (info->status) { - case svn_wc__db_status_incomplete: - return SVN_NO_ERROR; /* Not local only */ - case svn_wc__db_status_normal: + case svn_wc__db_status_incomplete: if (!repos_delete) return SVN_NO_ERROR; /* Local and remote */ svn_hash_sets(pb->deletes, name, NULL); @@ -1604,25 +1609,47 @@ open_directory(const char *path, db->repos_only = TRUE; if (!db->repos_only) - switch (info->status) - { - case svn_wc__db_status_normal: - break; - case svn_wc__db_status_deleted: - db->repos_only = TRUE; - - if (!info->have_more_work) - svn_hash_sets(pb->compared, - apr_pstrdup(pb->pool, db->name), ""); - break; - case svn_wc__db_status_added: - if (eb->ignore_ancestry) - db->ignoring_ancestry = TRUE; - else + { + switch (info->status) + { + case svn_wc__db_status_normal: + case svn_wc__db_status_incomplete: + db->is_incomplete = (info->status == + svn_wc__db_status_incomplete); + break; + case svn_wc__db_status_deleted: db->repos_only = TRUE; - break; - default: - SVN_ERR_MALFUNCTION(); + + if (!info->have_more_work) + svn_hash_sets(pb->compared, + apr_pstrdup(pb->pool, db->name), ""); + break; + case svn_wc__db_status_added: + if (eb->ignore_ancestry) + db->ignoring_ancestry = TRUE; + else + db->repos_only = TRUE; + break; + default: + SVN_ERR_MALFUNCTION(); + } + + if (info->status == svn_wc__db_status_added + || info->status == svn_wc__db_status_deleted) + { + svn_wc__db_status_t base_status; + + /* Node is shadowed; check BASE */ + SVN_ERR(svn_wc__db_base_get_info(&base_status, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, + eb->db, db->local_abspath, + dir_pool, dir_pool)); + + if (base_status == svn_wc__db_status_incomplete) + db->is_incomplete = TRUE; + } } if (!db->repos_only) @@ -1710,7 +1737,7 @@ close_directory(void *dir_baton, { apr_hash_t *repos_props; - if (db->added) + if (db->added || db->is_incomplete) { repos_props = apr_hash_make(scratch_pool); } @@ -1887,6 +1914,7 @@ open_file(const char *path, switch (info->status) { case svn_wc__db_status_normal: + case svn_wc__db_status_incomplete: break; case svn_wc__db_status_deleted: fb->repos_only = TRUE; @@ -2400,8 +2428,8 @@ wrap_dir_opened(void **new_dir_baton, wc_diff_wrap_baton_t *wb = processor->baton; svn_boolean_t tree_conflicted = FALSE; - assert(left_source || right_source); - assert(!copyfrom_source || !right_source); + assert(left_source || right_source); /* Must exist at one point. */ + assert(!left_source || !copyfrom_source); /* Either existed or added. */ /* Maybe store state and tree_conflicted in baton? */ if (left_source != NULL) Modified: subversion/branches/fsx-1.10/subversion/libsvn_wc/diff_local.c URL: http://svn.apache.org/viewvc/subversion/branches/fsx-1.10/subversion/libsvn_wc/diff_local.c?rev=1685464&r1=1685463&r2=1685464&view=diff ============================================================================== --- subversion/branches/fsx-1.10/subversion/libsvn_wc/diff_local.c (original) +++ subversion/branches/fsx-1.10/subversion/libsvn_wc/diff_local.c Sun Jun 14 20:58:10 2015 @@ -281,7 +281,8 @@ diff_status_callback(void *baton, { local_only = TRUE; /* Only report additions */ } - else if (db_status == svn_wc__db_status_normal) + else if (db_status == svn_wc__db_status_normal + || db_status == svn_wc__db_status_incomplete) { /* Simple diff */ base_kind = db_kind; @@ -297,7 +298,8 @@ diff_status_callback(void *baton, eb->db, local_abspath, scratch_pool, scratch_pool)); - if (base_status != svn_wc__db_status_normal) + if (base_status != svn_wc__db_status_normal + && base_status != svn_wc__db_status_incomplete) return SVN_NO_ERROR; } else @@ -312,7 +314,8 @@ diff_status_callback(void *baton, eb->db, local_abspath, scratch_pool, scratch_pool)); - if (base_status != svn_wc__db_status_normal) + if (base_status != svn_wc__db_status_normal + && base_status != svn_wc__db_status_incomplete) local_only = TRUE; else if (base_kind != db_kind || !eb->ignore_ancestry) {
