| |
| ** 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: ? |
| |
| |