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

[PATCH]notes/commit-from-multiple-working-copies

From: HuiHuang <yellow.flying_at_yahoo.com.cn>
Date: Mon, 29 Jun 2009 15:51:18 +0800

Hey Stefan,

According to the new plan I make a patch for
notes/commit-from-multiple-working-copies.txt.

log message:
     
    [[[
      
       * notes/commit-from-multiple-working-copies.txt
          Tweak the plan as do one single commit for each working copy.
    ]]]

Index: notes/commit-from-multiple-working-copies.txt
===================================================================
--- notes/commit-from-multiple-working-copies.txt (revision 38220)
+++ notes/commit-from-multiple-working-copies.txt (working copy)
@@ -3,157 +3,90 @@
 1) Expected behavior
 
 When committing files, listing their paths, no matter whether they belong to
-the same work copy or not, if they all live in the same repository, they should
-be committed in one transaction successfully.
+the same work copy or not, if they all live in the same repository, they
+should be committed successfully.
  
 2) Actual behavior
 
+Currently, the code "condenses" all target paths, which means it
+tries to find a common root for them, and then it tries to lock that
+common root. If the common root is not a working copy, locking the
+common root fails and the commit is simply aborted ("svn: <common root>
+is not a working copy").
+
 2a) If the committing files belong to the same working copy, they will be
-committed in one transaction successfully.
+committed successfully.
 
-2b) Otherwise, if they belong to more than one working copy, svn will output an
-error which indicates that their common ancestor is not a work copy and commit
-action fails.
+2b) Otherwise, if they belong to more than one working copy, svn will output
+an error which indicates that their common ancestor is not a work copy and
+commit action fails.
  
 3) Suggested change
-
-This section has two parts. The first part introduces how this issue is solved
-in SVNKit, and then I will give my suggestions on how we should solve this
-issue in the second part.
  
-3a) SVNKit's solution
-
-1. SVNKit receives list of paths to commit.
-
-2. All paths are grouped by wc root path, so we get a map of wc_root:paths
-pairs - one for each working copy.
-
-3. For each pair in Map we create SVNWCAccess object - wc_access - which is
-actually a collection of directories being opened for commit (same as
-svn_wc_adm_access_t set in native SVN).
-
-4. For each wc_access we collect items to commit, same way as for "normal"
-commit. Each item refers to its wc_access. Then we group all items by its
-repos_url and repos_uuid (fetching it from repos if not available).
-
-5. So we have commit items grouped by repository root URL, each item may refer
-to its own wc_access (working copy). We call such a group a "commit packet".
+1. We receives list of targets to commit.
 
-7. Now we have a list of commit packets-one for each repository. Then we will
-commit each commit packet as a transaction.
-
-8. During commit and in post commit code we use that wc_access references that
-is stored in each commit item to update corresponding working copy, write and
-execute log files and then finally to close all open directories.
-
-3b) Suggested change for Subversion
-
-I think that "One Commit, One Transaction" is the best (and this is also
-compatible with original system). So commit files from different repositories
-at a time and break them into several transactions may be not a good idea. And
-I suggest that we should constrain committing files in the same repository.
-
-1. We receives list of paths to commit.
+ In subversion\svn\commit-cmd.c: function
+ svn_error_t *
+ svn_cl__commit(apr_getopt_t *os,
+ void *baton,
+ apr_pool_t *pool)
+ receives the targest list first.
 
-In subversion\svn\commit-cmd.c: function
-svn_error_t *
-svn_cl__commit(apr_getopt_t *os,
- void *baton,
- apr_pool_t *pool)
-receives the file list first.
-
-Then in E:\subversion\subversion\libsvn_client\commit.c: function
-svn_error_t *
-svn_client_commit4(svn_commit_info_t **commit_info_p,
- const apr_array_header_t *targets,
- svn_depth_t depth,
- svn_boolean_t keep_locks,
- svn_boolean_t keep_changelists,
- const apr_array_header_t *changelists,
- const apr_hash_t *revprop_table,
- svn_client_ctx_t *ctx,
- apr_pool_t *pool)
-uses the file list do commit.
+ Then in E:\subversion\subversion\libsvn_client\commit.c: function
+ svn_error_t *
+ svn_client_commit4(svn_commit_info_t **commit_info_p,
+ const apr_array_header_t *targets,
+ svn_depth_t depth,
+ svn_boolean_t keep_locks,
+ svn_boolean_t keep_changelists,
+ const apr_array_header_t *changelists,
+ const apr_hash_t *revprop_table,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *pool)
+ uses the targest list do commit. We may add a new function named
+ svn_client_commit5 to do this work.
  
-2. All paths are grouped by wc root path, so we get a map of wc_root:paths
-pairs - one for each working copy.
-
-Here use an apr_hash_t * hash of const char * paths, keyed on working copy
-path directory names to store the wc_root:paths map. It would be a local
-variable of the function svn_client_commit4, because it is used several times
-in the function. And it is allocated from pool by using apr_hash_make(pool).
+2. If targets are not from the same working copy, we did the following
+instead of aborting the commit:
 
-It will be created after the paths are checked for non-url form.
+ If locking the common root failed:
 
-3. For each pair in Map we create svn_wc_adm_access_t- wc_access.
+ For each target path we got:
 
-Here we use function
-svn_error_t *
-svn_wc_adm_open3(svn_wc_adm_access_t **adm_access,
- svn_wc_adm_access_t *associated,
- const char *path,
- svn_boolean_t write_lock,
- int levels_to_lock,
- svn_cancel_func_t cancel_func,
- void *cancel_baton,
- apr_pool_t *pool)
-to create svn_wc_adm_access_t.
+ For each working copy root we already know (initially we don't
+ know any working copy roots):
+ Check if the current target path is below the working copy root.
+ If it is, put it into this root's group ("commit packet")
+ and continue with the next target path.
 
-4. For each wc_access we collect items to commit. Each item refers to its
-wc_access.
+ If we end up here, no suitable working copy root was found
+ for the current target path.
+ Walk the current target path downwards, starting from the common
+ root (the root which we could not lock, currently is base_dir).
+ Try to lock the current directory at each step.
+ If locking succeeds, we have found a new WC root!
+ Store its access baton in the set of known working copy roots.
+ Put the current target path into the group of the root we just found.
+
+ Here we use an struct to store "commit packet":
+ typedef struct commit_packet_t
+ {
+ /* Working copy root of a wc */
+ const char *base_dir;
 
-Here we use function
-svn_error_t *
-svn_client__harvest_committables(apr_hash_t **committables,
- apr_hash_t **lock_tokens,
- svn_wc_adm_access_t *parent_adm,
- apr_array_header_t *targets,
- svn_depth_t depth,
- svn_boolean_t just_locked,
- const apr_array_header_t *changelists,
- svn_client_ctx_t *ctx,
- apr_pool_t *pool)
-to collect commit items for each svn_wc_adm_access_t. here use an apr_hash_t *
-hash of apr_array_header_t *arrays (of svn_client_commit_item_t * structures),
-keyed
-on wc_access to store the map.
+ /* Targets under base_dir */
+ apr_array_header_t *targets;
 
-5. If there are more than one working copies, then we check all items by its
-repos_url and repos_uuid (fetching it from repos if not available). If they are
-not from the same repository, return with error, otherwise, combine them into
-one group.
+ svn_wc_adm_access_t *base_dir_access;
 
-For each working copy we get its repos_url and repos_uuid and group the commit
-items by repos_url and repos_uuid. If there is more than one group, return
-error which indicate that the committing files are not from the same
-repository.
+ } commit_packet_t;
+ It would be a local variable of the function svn_client_commit5,
+ because it is used only in the function. And it is allocated from pool.
 
-6. Commit these items as a transaction.
+ Now run a commit for each working copy root we found.
+ This is done just like before when the code only knew about
+ a single root, but it's done for each root in turn.
 
-Here we can use function
-svn_error_t *
-svn_client__do_commit(const char *base_url,
- apr_array_header_t *commit_items,
- svn_wc_adm_access_t *adm_access,
- const svn_delta_editor_t *editor,
- void *edit_baton,
- const char *notify_path_prefix,
- apr_hash_t **tempfiles,
- apr_hash_t **checksums,
- svn_client_ctx_t *ctx,
- apr_pool_t *pool)
-to commit commit_items.
-
-7. During commit and in post commit code we use that wc_access references that
-is stored in each commit item to update corresponding working copy, write and
-execute log files and then finally to close all open directories.
-
-Here we can use function
-svn_error_t *
-svn_wc_process_committed_queue(svn_wc_committed_queue_t *queue,
- svn_wc_adm_access_t *adm_access,
- svn_revnum_t new_revnum,
- const char *rev_date,
- const char *rev_author,
- apr_pool_t *pool);
-to update working copyes.
+ Also, make svn_client_commit() return an array of svn_commit_info_t
+ objects, one for each commit made, instead of just a single
+ svn_commit_info_t object.

                                 
--------------
yellow.flying
2009-06-29

__________________________________________________
赶快注册雅虎超大容量免费邮箱?
http://cn.mail.yahoo.com

------------------------------------------------------
http://subversion.tigris.org/ds/viewMessage.do?dsForumId=462&dsMessageId=2366257
Received on 2009-06-29 09:52:11 CEST

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

This site is subject to the Apache Privacy Policy and the Apache Public Forum Archive Policy.