Notes on the 'greg hudson' directory versioning problem. * Problem This is a side effect of allowing users to have 'mixed revision' trees; it happens in SVN (and not CVS) because directories are now versioned as well as files. If I commit a deletion, it's not enough to simply remove the entry from the parents' entries file. Why? Because the next time the parent dir is updated, the state-reporter will say "I have revision N of this directory." The truth is, you *don't* have revision N of the directory; you have revision N *minus* an entry. If the missing entry isn't reported to the server during an update, then the server assumes you have all of revision N. This leads to inaccurate updates being sent by the server. (For example, if the update is backdating, the server won't know to re-send the missing file; if updating to HEAD, the server might try to re-delete the missing file.) The solution is to have the entries file continue tracking committed items as 'deleted'. See description below. * History - originally solved by CVS commit on 2001-07-18 15:30. - solution removed in r642. - solution reinstated (into a cleaner libsvn_wc design) in r1970. * When does an entry get the 'deleted' flag attached? When we commit a deletion. In other words, in the post-commit processing phase, we notice if the committed item was deleted in the commit. If the item has a different 'new' revnum than parent's revnum, mark entry 'deleted'. * Who uses the 'deleted' flag? The state-reporter. When it crawls the working copy, it will report a deleted entry as 'missing' to the reporter vtable. * When does the 'deleted' entry go away? 1. In the post-update processor. If the deleted entry hasn't been completely overwritten during the update by a new item of the same name, then the server obviously intended the item to stay deleted. So the entire entry is removed. 2. In the post-commit processor. If the deleted entry has the -same- revnum as its parent, then the parent must have been committed as well, and thus it's safe to remove the child entry completely. OR If item was 'added' during the commit, it's safe to remove the 'deleted' flag here as well. * How to implement this cleanly? Add a flag to svn_wc_entries_read and svn_wc_entry, indicating whether a deleted entries should be returned. Generally, anyone who gets a single entry or a list of entries will NOT want deleted entries returned. Only the routines listed above will want to see them: - post-commit processor - post-update processor - state-reporter - svn_wc_add (see below) * the 'deleted' and 'schedule add' scenario svn rm foo.c svn ci <== now we have a deleted entry. touch foo.c svn add foo.c <== svn_wc_add should just append schedule=add. Now we have an entry that is *simultaneously* schedule=add and deleted! if next command is 'svn revert foo.c', svn_wc_revert should remove schedule=add, and make it just 'deleted' again, rather than just blowing away the entry. if next command is 'svn up', state-reporter should still report original entry as missing, i.e. not ignore the entry just because it's also added. commit, status, propset, etc... each only needs to pay attention to the schedule=add. * Hand tests: 1. delete a file, commit. verify that 'svn up' makes deleted entry vanish. 2. do the same for a dir. 3. delete a file, commit. re-add file, commit. verify that entry is totally normal afterwards. (this is commit_test #11, actually) 4. do the same for a dir. 5. delete a file, commit. re-add file. revert the add. verify that entry is still in 'deleted' state. 6. do the same for a dir.