On Wed, Feb 9, 2011 at 7:46 AM, Stefan Sperling <s...@elego.de> wrote:

> On Wed, Feb 09, 2011 at 07:34:53AM +1000, Daniel Becroft wrote:
> > Hi,
> >
> > Attached is a completed patch to resolve issue 3686[1], where the
> executable
> > bit is not maintained during the merge of a binary file.
> >
> > I thought about making this change more generic, and applying it to text
> > files as well (there was discussion with performance of simple-case
> merging
> > a month ago on users@), but thought I'd leave that for later. I didn't
> want
> > to worry about (potential) line-endings, keywords, etc. problems.
>
> Some comments inline.
>
> >
> > [[[
> > 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).
> >
> > * 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).
> >
> > * subversion/libsvn_wc/merge.c
> >  (merge_binary_file): Added dry_run parameter. Add the special case
> merging
> >   of binary files.
>
> The log messages doesn't mention the caller of merge_binary_file()
> which was also changed.>
>

Oops, will fix.

 > * subversion/tests/cmdline/merge_tests.py
> >  (merge_change_to_file_with_executable): Remove @XFail decorator.
> > ]]]
> >
> > [1]
> >
> http://subversion.tigris.org/ds/viewMessage.do?dsForumId=463&dsMessageId=2635024
> >
> > Cheers,
> > Daniel B.
> >
> > ---
> > Daniel Becroft
>
> > Index: subversion/tests/cmdline/merge_tests.py
> > ===================================================================
> > --- subversion/tests/cmdline/merge_tests.py   (revision 1068136)
> > +++ subversion/tests/cmdline/merge_tests.py   (working copy)
> > @@ -16469,7 +16469,6 @@
> >  #----------------------------------------------------------------------
> >  # Test for issue #3686 'executable flag not correctly set on merge'
> >  # See http://subversion.tigris.org/issues/show_bug.cgi?id=3686
> > -@XFail()
> >  @Issue(3686)
> >  @SkipUnless(svntest.main.is_posix_os)
> >  def merge_change_to_file_with_executable(sbox):
> > 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,
> >                    const svn_wc_conflict_version_t *left_version,
> >                    const svn_wc_conflict_version_t *right_version,
> >                    const char *detranslated_target_abspath,
> > @@ -1111,13 +1112,31 @@
> >    const char *merge_dirpath, *merge_filename;
> >    const char *conflict_wrk;
> >    svn_skel_t *work_item;
> > +  svn_boolean_t same_contents = FALSE;
> >
> >    SVN_ERR_ASSERT(svn_dirent_is_absolute(target_abspath));
> >
> >    *work_items = NULL;
> >
> >    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. */
> > +  SVN_ERR(svn_io_files_contents_same_p(&same_contents,
> > +                                      left_abspath,
> > +                                      target_abspath,
> > +                                      scratch_pool));
> >
> > +  if (same_contents)
> > +    {
> > +      if (!dry_run)
> > +        SVN_ERR(svn_io_file_move(right_abspath, target_abspath,
> > +                                         scratch_pool));
>
> Isn't calling svn_io_file_move() directly still bypassing the work queue?
> Shouldn't this code queue a task instead?
>

Hmm ... I'll look into that. The test went from XFAIL to XPASS, and I was
working off the "minimum required to get test to pass" mantra.

> +      *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,26 +1376,23 @@
> >
> >    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,
> > -                                  left_abspath,
> > -                                  right_abspath,
> > -                                  target_abspath,
> > -                                  left_label,
> > -                                  right_label,
> > -                                  target_label,
> > -                                  left_version,
> > -                                  right_version,
> > -                                  detranslated_target_abspath,
> > -                                  mimeprop,
> > -                                  conflict_func,
> > -                                  conflict_baton,
> > -                                  result_pool, scratch_pool));
> > +      SVN_ERR(merge_binary_file(work_items,
> > +                                merge_outcome,
> > +                                db,
> > +                                left_abspath,
> > +                                right_abspath,
> > +                                target_abspath,
> > +                                left_label,
> > +                                right_label,
> > +                                target_label,
> > +                                dry_run,
> > +                                left_version,
> > +                                right_version,
> > +                                detranslated_target_abspath,
> > +                                mimeprop,
> > +                                conflict_func,
> > +                                conflict_baton,
> > +                                result_pool, scratch_pool));
> >      }
> >    else
> >      {
> > Index: subversion/libsvn_client/merge.c
> > ===================================================================
> > --- subversion/libsvn_client/merge.c  (revision 1068136)
> > +++ subversion/libsvn_client/merge.c  (working copy)
> > @@ -1300,7 +1300,6 @@
> >  {
> >    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));
> > @@ -1452,75 +1451,38 @@
> >        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.
> > +      /* 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 */
> > +      const char *target_label = _(".working");
> > +      const char *left_label = apr_psprintf(subpool,
> > +                                            _(".merge-left.r%ld"),
> > +                                            older_rev);
> > +      const char *right_label = apr_psprintf(subpool,
> > +                                             _(".merge-right.r%ld"),
> > +                                             yours_rev);
> > +      conflict_resolver_baton_t conflict_baton = { 0 };
> > +      const svn_wc_conflict_version_t *left;
> > +      const svn_wc_conflict_version_t *right;
>
> The above will fail to compile with C89 compilers.
> Variables must be declared at the beginning of a scope.
>

Thanks. These variables were all wrapped in the if (merge_required) block,
and I simply removed that and adjusted indentation.


> >
> > -         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;
> > -            }
> > -        }
> > +      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;
> > +      conflict_baton.pool = merge_b->pool;
> >
> > -      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 */
> > -          const char *target_label = _(".working");
> > -          const char *left_label = apr_psprintf(subpool,
> > -                                                _(".merge-left.r%ld"),
> > -                                                older_rev);
> > -          const char *right_label = apr_psprintf(subpool,
> > -                                                 _(".merge-right.r%ld"),
> > -                                                 yours_rev);
> > -          conflict_resolver_baton_t conflict_baton = { 0 };
> > -          const svn_wc_conflict_version_t *left;
> > -          const svn_wc_conflict_version_t *right;
> > +      SVN_ERR(make_conflict_versions(&left, &right, mine_abspath,
> > +                                     svn_node_file, merge_b));
> > +      SVN_ERR(svn_wc_merge4(&merge_outcome, merge_b->ctx->wc_ctx,
> > +                            older_abspath, yours_abspath, mine_abspath,
> > +                            left_label, right_label, target_label,
> > +                            left, right,
> > +                            merge_b->dry_run, merge_b->diff3_cmd,
> > +                            merge_b->merge_options, prop_changes,
> > +                            conflict_resolver, &conflict_baton,
> > +                            merge_b->ctx->cancel_func,
> > +                            merge_b->ctx->cancel_baton,
> > +                            subpool));
> >
> > -          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;
> > -          conflict_baton.pool = merge_b->pool;
> > -
> > -          SVN_ERR(make_conflict_versions(&left, &right, mine_abspath,
> > -                                         svn_node_file, merge_b));
> > -          SVN_ERR(svn_wc_merge4(&merge_outcome, merge_b->ctx->wc_ctx,
> > -                                older_abspath, yours_abspath,
> mine_abspath,
> > -                                left_label, right_label, target_label,
> > -                                left, right,
> > -                                merge_b->dry_run, merge_b->diff3_cmd,
> > -                                merge_b->merge_options, prop_changes,
> > -                                conflict_resolver, &conflict_baton,
> > -                                merge_b->ctx->cancel_func,
> > -                                merge_b->ctx->cancel_baton,
> > -                                subpool));
> > -        }
> > -
> >        if (content_state)
> >          {
> >            if (merge_outcome == svn_wc_merge_conflict)
>
>

Reply via email to