[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

Re: [PATCH] Fix issue #3686 - executable bit not set during merge

From: Daniel Shahaf <d.s_at_daniel.shahaf.name>
Date: Fri, 11 Feb 2011 15:26:23 +0200

[ disclaimer: I'm not familiar with wc internals yet; sorry; hope I'll
learn something while reviewing this ]

Daniel Becroft wrote on Thu, Feb 10, 2011 at 07:21:30 +1000:
> >
> Hey Stefan,
>
> It was only partially bypassing the work queue. The items to update the
> executable bit (and read/write bits) is always done at the end of the
> svn_wc_merge4() function, so that's why the test started passing. However,
> you are correct - I should have been using the svn_wc__wq_build_file_install
> workqueue task to copy the file across (this is what happens when a conflict
> is resolved with "theirs-full").
>
> An updated patch is attached.
>
> [[[
> Fix issue #3686 - executable bit not set during merge.
>
> The cause was the special case in libsvn_client, which bypassed the
> use of the workqueue. This logic has now been moved into libsvn_wc.
>
> Additionally, this change allows the status of binary files (during
> a dry-run merge) to be reported correctly (previously, all binary
> files were reported as conflicted).
>

Well written.

> * subversion/libsvn_client/merge.c
> (merge_file_changed): Removed binary-merge special case (now in libsvn_wc).
> Removed merge_required variable (resulting in indentation changes).
>

Two spaces before (. [I guess it was right when you sent it, since your
mail mis-wrapped the above paragraphs as well]

> * subversion/libsvn_wc/merge.c
> (merge_binary_file): Added dry_run parameter. Add the special case merging
> of binary files.
> (svn_wc__internal_merge): Removed dry_run check for binary files, and
> pass to merge_binary_file instead.
>

Use present tense please.

> * subversion/tests/cmdline/merge_tests.py
> (merge_change_to_file_with_executable): Remove @XFail decorator.
> ]]]
>
> Cheers,
> Daniel B
> (who is not a C programmer by trade ...)

> Index: subversion/libsvn_wc/merge.c
> ===================================================================
> --- subversion/libsvn_wc/merge.c (revision 1068136)
> +++ subversion/libsvn_wc/merge.c (working copy)
> @@ -1094,6 +1094,7 @@
> const char *left_label,
> const char *right_label,
> const char *target_label,
> + svn_boolean_t dry_run,

It would have been easier to review the patch if you'd attached
a version generated with 'svn diff -x-pw'.

> Index: subversion/libsvn_wc/merge.c
> ===================================================================
> --- subversion/libsvn_wc/merge.c (revision 1069789)
> +++ subversion/libsvn_wc/merge.c (working copy)
> @@ -1094,6 +1094,7 @@ merge_binary_file(svn_skel_t **work_items,
> const char *left_label,
> const char *right_label,
> const char *target_label,
> + svn_boolean_t dry_run,
> const svn_wc_conflict_version_t *left_version,
> const svn_wc_conflict_version_t *right_version,
> const char *detranslated_target_abspath,
> @@ -1118,6 +1120,33 @@ merge_binary_file(svn_skel_t **work_items,
>
> svn_dirent_split(&merge_dirpath, &merge_filename, target_abspath, pool);
>
> + /* Attempt to merge the binary file. At the moment, we can only
> + handle the special case: if the LEFT side of the merge is equal
> + to WORKING, then we can copy RIGHT directly. */

The comment in libsvn_client mentioned two special case, what happened
to the other one? Does the existing wc code already handle it? (I'd be
surprised)

  - Alternately, if the 'left' side of the merge doesn't exist in
  - the repository, and the 'right' side of the merge is
  - identical to the WC, pretend we did the merge (a no-op).

> + SVN_ERR(svn_io_files_contents_same_p(&same_contents,
> + left_abspath,
> + target_abspath,
> + scratch_pool));
> +
> + if (same_contents)
> + {
> + if (!dry_run)
> + {
> + svn_skel_t *work_item;
> +

subversion/libsvn_wc/merge.c: In function ‘merge_binary_file’:
subversion/libsvn_wc/merge.c:1135: warning: declaration of ‘work_item’ shadows a previous local
subversion/libsvn_wc/merge.c:1114: warning: shadowed declaration is here

> + SVN_ERR(svn_wc__wq_build_file_install(&work_item,
> + db, target_abspath,
> + right_abspath,
> + FALSE /* use_commit_times */,
> + FALSE /* record_fileinfo */,

About RECORD_FILEINFO:

* Why are you passing FALSE? (I see that other calls do this too, so
  this is for my education mainly)) A quick scan makes me expect that
  parameter to control the mtime/size caches for modification detection.

* In update_editor.c there are two places that pass NULL (not FALSE) for
  that, and have above them comment that says that "If %s, we want to
  pass FALSE". What is going on there?
  (this is to the list, not specifically at Daniel)

> + result_pool, scratch_pool));
> + *work_items = svn_wc__wq_merge(*work_items, work_item, result_pool);

Don't you need to convert the next svn_wc__wq_build_file_install() to
use this 'build-then-merge' approach too? Otherwise, won't it overwrite
your WORK_ITEMS?

> + }
> +
> + *merge_outcome = svn_wc_merge_merged;
> + return SVN_NO_ERROR;
> + }
> +
> /* Give the conflict resolution callback a chance to clean
> up the conflict before we mark the file 'conflicted' */
> if (conflict_func)
> @@ -1357,10 +1386,6 @@ svn_wc__internal_merge(svn_skel_t **work_items,
>
> if (is_binary)
> {
> - if (dry_run)
> - /* in dry-run mode, binary files always conflict */
> - *merge_outcome = svn_wc_merge_conflict;
> - else
> SVN_ERR(merge_binary_file(work_items,
> merge_outcome,
> db,
> @@ -1370,6 +1395,7 @@ svn_wc__internal_merge(svn_skel_t **work_items,
> left_label,
> right_label,
> target_label,
> + dry_run,
> left_version,
> right_version,
> detranslated_target_abspath,
> Index: subversion/libsvn_client/merge.c
> ===================================================================
> --- subversion/libsvn_client/merge.c (revision 1069789)
> +++ subversion/libsvn_client/merge.c (working copy)
> @@ -1300,7 +1300,6 @@ merge_file_changed(const char *local_dir_abspath,
> {
> merge_cmd_baton_t *merge_b = baton;
> apr_pool_t *subpool = svn_pool_create(merge_b->pool);
> - svn_boolean_t merge_required = TRUE;
> enum svn_wc_merge_outcome_t merge_outcome;
>
> SVN_ERR_ASSERT(mine_abspath && svn_dirent_is_absolute(mine_abspath));
> @@ -1449,45 +1448,7 @@ merge_file_changed(const char *local_dir_abspath,
> if (older_abspath)
> {
> svn_boolean_t has_local_mods;
> - SVN_ERR(svn_wc_text_modified_p2(&has_local_mods, merge_b->ctx->wc_ctx,
> - mine_abspath, FALSE, subpool));
>
> - /* Special case: if a binary file's working file is
> - exactly identical to the 'left' side of the merge, then don't
> - allow svn_wc_merge to produce a conflict. Instead, just
> - overwrite the working file with the 'right' side of the
> - merge. Why'd we check for local mods above? Because we want
> - to do a different notification depending on whether or not
> - the file was locally modified.
> -
> - Alternately, if the 'left' side of the merge doesn't exist in
> - the repository, and the 'right' side of the merge is
> - identical to the WC, pretend we did the merge (a no-op). */
> - if ((mimetype1 && svn_mime_type_is_binary(mimetype1))
> - || (mimetype2 && svn_mime_type_is_binary(mimetype2)))
> - {
> - /* For adds, the 'left' side of the merge doesn't exist. */
> - svn_boolean_t older_revision_exists =
> - !merge_b->add_necessitated_merge;
> - svn_boolean_t same_contents;
> - SVN_ERR(svn_io_files_contents_same_p(&same_contents,
> - (older_revision_exists ?
> - older_abspath : yours_abspath),
> - mine_abspath, subpool));
> - if (same_contents)
> - {
> - if (older_revision_exists && !merge_b->dry_run)
> - {
> - SVN_ERR(svn_io_file_move(yours_abspath, mine_abspath,
> - subpool));
> - }
> - merge_outcome = svn_wc_merge_merged;
> - merge_required = FALSE;
> - }
> - }
> -
> - if (merge_required)
> - {
> /* xgettext: the '.working', '.merge-left.r%ld' and
> '.merge-right.r%ld' strings are used to tag onto a file
> name in case of a merge conflict */
> @@ -1502,6 +1463,9 @@ merge_file_changed(const char *local_dir_abspath,
> const svn_wc_conflict_version_t *left;
> const svn_wc_conflict_version_t *right;
>
> + SVN_ERR(svn_wc_text_modified_p2(&has_local_mods, merge_b->ctx->wc_ctx,
> + mine_abspath, FALSE, subpool));
> +

You only need HAS_LOCAL_MODS now when CONTENT_STATE is set. Shouldn't
you skip this call when CONTENT_STATE is NULL then? (It may perform
stat() or read().)

> conflict_baton.wrapped_func = merge_b->ctx->conflict_func;
> conflict_baton.wrapped_baton = merge_b->ctx->conflict_baton;
> conflict_baton.conflicted_paths = &merge_b->conflicted_paths;
> @@ -1519,7 +1483,6 @@ merge_file_changed(const char *local_dir_abspath,
> merge_b->ctx->cancel_func,
> merge_b->ctx->cancel_baton,
> subpool));
> - }
>
> if (content_state)
> {
Received on 2011-02-11 14:31:34 CET

This is an archived mail posted to the Subversion Dev mailing list.

This site is subject to the Apache Privacy Policy and the Apache Public Forum Archive Policy.