** Proposed new commit system ** Purpose: 1. [speed] Detect conflicts early: without ever seeing a bit of svndiff data 2. [speed] Less merging: always merging against head. 3. [speed] Zero undeltification: detect conflicts without having to undeltify directories. 4. [theory] Unified commit-system across RA implementations; guarantees that "Hudson" scenarios will consistently work. Status Quo: The first two advantages listed above are already being achieved by ra_dav in its own way, so for a long time the 3rd point was our motivating force. However, because undeltification isn't so horrible anymore, we've prioritized this task as Beta. But now point #4 has come into play; as long as we put off this task, ra_dav will have two theoretical deficiencies: * to replace a file, the user must {delete, add, commit}. If the user attempts to {delete, commit, add, commit}, the second commit will fail. * unable to prevent users from committing propchanges on out-of-date dirs. Thus users could end up with working copies containing dirs whose revision numbers are incorrect. Another TODO: We would like to get rid of the ghudson-scenario 'deleted' existence flag in the working copy. It makes the commit-crawler insanely complex. Here's how: - 'deleted' flag is only needed in the commit case, because the crawler is assuming that it's building a perfect mirror of the working copy on the server (which is true with ra_local). After our commit process is always merging against HEAD on-the-fly, we no longer need to send extra delete commands. - 'deleted' flag is used during updates, where we really *are* always building a perfect mirror of the working copy on the server. But we don't *have* to build a perfect mirror; if we left out the extra deletes, then dir_deltas will send us back an extra delete. This isn't a problem if we make the update editor treat an 'extra' delete as a no-op! ----------------------------------------------------------------------- Key: HEAD := the latest revision number in the repository NRID := Node-Rev-ID of some object in HEAD revision CR := Created Revision; the revision in which NRID was created -- Editor: RA->get_commit_editor() ra_local: Fetches editor from libsvn_repos, composes with tracking editor. ra_dav: Has own editor, composes with tracking editor. Creates a transaction (MKACTIVITY) based on HEAD. (### too early!) Sets the log message on the transaction: (CHECKOUT baseline; PROPPATCH baseline) new system: ? -- Editor: set_target_revision (rev) comment: [Not used by the commit driver. This is for updates.] --- Editor: replace_root (rev) ra_local: Creates a transaction based on REV. ra_dav: Ignores REV; gets versioned-resource-url from working copy. new system: Creates a transaction based on HEAD. -- Editor: add_directory/file (name, copyfrom_path, copyfrom_rev) ra_local: Normally calls fs_make_dir() or fs_make_file(). If copyfrom args, then fs_copy() instead. ra_dav: CHECKOUT parent into activity. if dir, MKCOL. (could return out-of-date error?). if file, do nothing. (--> currently ignores copyfrom) (### bad) new system: look up path in transaction (HEAD) if path exists already, return out-of-date error. else: do what ra_local does. -- Editor: replace_file/dir (name, rev) ra_local: If REV != parent's rev, fs_link() the different file into the transaction. ra_dav: Ignores REV. If dir, just telescope the baton's path. If file, CHECKOUT the file/dir into the activity. (could return out-of-date error?) new system: look up the path in the transaction (HEAD). if path non-existent, return out-of-date error. else: (### ?file only?) get CR of path, by examining path's NRID. if (REV < CR), return out-of-date error. if (CR <= REV <= HEAD), do nothing, all is good. -- Editor: delete_entry (name) ra_local: Calls fs_delete_tree(). ra_dav: CHECKOUT parent into activity. DELETE object. (### this should not return an out-of-date error) new system: look up the path in the transaction (HEAD). if path non-existent, go home. (merge allows this) else: get CR of path, by examining path's NRID. if (REV < CR), return out-of-date error. if (CR <= REV <= HEAD), remove the object from the transaction. -- Editor: apply_textdelta () ra_local: returns window handler from fs_apply_textdelta(). ra_dav: returns window handler that writes to tmp file. when stream is closed, do a PUT of the file (could return out-of-date error?) new system: ? -- Editor: change_file/dir_prop (name, val) ra_local: Calls fs_change_node_prop() ra_dav: CHECKOUT the object. Cache the propchange. new system: ? -- Editor: close_file/dir () ra_local: frees batons. ra_dav: Send cached propchanges via PROPPATCH. new system: ? -- Editor: abort_edit () ra_local: Calls fs_abort_txn() ra_dav: Non-existent!!! (### bad) new system: ? -- Editor: close_edit () ra_local: Calls fs_commit_txn(). All conflicts are found at this time. If merge works, then (selectively) bumps revisions. ra_dav: Sends MERGE request: "please merge this activity" mod_dav_svn calls fs_commit_txn(). mod_dav_svn runs dir_delta() on new revision to generate response. ra_dav parses response and (selectively) bumps revisions/wcprops. new system: ?