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

Re: nested copies broken on trunk

From: Philip Martin <philip.martin_at_wandisco.com>
Date: Thu, 28 Jan 2010 23:44:01 +0000

Greg Stein <gstein_at_gmail.com> writes:

> the node functions are considered transient. It would be best to implement
> something more direct against wc_db

I'm not sure it's the right solution -- it might just be working round
a bug.

The problem only occurs when the deleted file is a direct child of a
copied directory, if it's in a subdirectory then there is no problem.
The difference is this bit of code near the start of
entries.c:write_entry:

  switch (entry->schedule)
    {
      [...]
      case svn_wc_schedule_delete:
        working_node = MAYBE_ALLOC(working_node, scratch_pool);
        /* If the entry is part of a REPLACED (not COPIED) subtree,
           then it needs a BASE node. */
       if (! (entry->copied
               || (this_dir->copied
                   && this_dir->schedule == svn_wc_schedule_add)))
          base_node = MAYBE_ALLOC(base_node, scratch_pool);
        break;

When the deleted file is a direct child of the copied directory then
this_dir->schedule is svn_wc_schedule_add, but when it's in a subdir
it's svn_wc_schedule_normal. (That's the usual directory is copied
but subdirs are normal thing.) So when I do:

   svn cp wc/A wc/A2
   svn rm wc/A2/f wc/A2/B/f

the code above allocates a base_node for A2/B/f but not for A2/f.
Later on in the function:

      if (entry->schedule == svn_wc_schedule_delete)
        {
          if (entry->incomplete)
            {
               [...]
            }
          else
            {
              /* If the entry is part of a COPIED (not REPLACED) subtree,
                 then the deletion is referring to the WORKING node, not
                 the BASE node. */
              if (entry->copied
                  || (this_dir->copied
                      && this_dir->schedule == svn_wc_schedule_add))
                working_node->presence = svn_wc__db_status_not_present;
              else
                working_node->presence = svn_wc__db_status_base_deleted;
            }

does the same sort of thing and results in two different
working_node->presence values.

The overall result is that

   svn cp wc/A wc/A2
   svn rm wc/A2/B/f

gets a working node with presence base-deleted and a base node, while

   svn cp wc/A wc/A2
   svn rm wc/A2/f

gets a working node with presence not-present and no base node.

I don't really understand why these cases should be different, and the
comment about "REPLACED (not COPIED)" doesn't seem to apply because
neither item is replaced.

If I use the debugger to tweak this_dir->schedule to
svn_wc_schedule_normal during "svn rm wc/A2/f" then the subsequent
commit works.

-- 
Philip
Received on 2010-01-29 00:44:40 CET

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