Hi!

Is 'svn switch does not update keywords' a problem that needs solving?

Is the performance of this solution acceptable (traverse the entire wc
one more time after the editor drive)?

Alternatives? 
* Custom db-query that only returns the paths with matching property set
  on them. Could be used by 'svn pg -R' later on.
* Do the recording during the crawling of the wc. Saves us the extra
  traversal.

And why is it not working? :)

I'm translating the file in the WC back into Normal Form and then I
install it through the workqueue mecanism. It does get translated but
not to the current URL but to the previous.

[[[
Fix issue #1975 - 'svn switch does not update keywords'.

Only files affected by the switch gets keyword translation, possibly
making some $URL$ keywords incorrect. We do a complete traversal of
the WC to check for the files that have svn:keywords pristine props 
set and retranslate those files. */

* subversion/libsvn_wc/update_editor.c
  (reinstall_target_baton): New
  (reinstall_target_with_keywords): New.
  (close_edit): walk all children and call 
    reinstall_target_with_keywords().
]]]

Daniel
Index: subversion/libsvn_wc/update_editor.c
===================================================================
--- subversion/libsvn_wc/update_editor.c        (revision 957424)
+++ subversion/libsvn_wc/update_editor.c        (arbetskopia)
@@ -5080,13 +5080,83 @@ close_file(void *file_baton,
   return SVN_NO_ERROR;
 }
 
+struct reinstall_target_baton
+{
+  svn_wc__db_t *db;
+  svn_cancel_func_t cancel_func;
+  void *cancel_baton;
 
+  /* ### Do we need a result_pool here? How is the apr pool cleanup handler
+   * configured? We need a pool with the handler activated in case we get
+   * cancelled. ### */
+};
+
+/* Reinstall target to assure svn:keywords expand correctly. */
+static svn_error_t *
+reinstall_target_with_keywords(const char *local_abspath, 
+                               void *walk_baton,
+                               apr_pool_t *scratch_pool)
+{
+  struct reinstall_target_baton *rtb = walk_baton;
+  apr_hash_t *props;
+  const char *tmptext;
+
+  SVN_DBG(("reinstall_target() %s\n", local_abspath));
+
+  SVN_ERR(svn_wc__get_pristine_props(&props, rtb->db, local_abspath,
+                                     scratch_pool, scratch_pool));
+
+  /* ### There must be a constant for svn:keywords somewhere, but where? */
+  if (props && apr_hash_get(props, "svn:keywords", APR_HASH_KEY_STRING))
+    {
+      svn_skel_t *all_work_items;
+      svn_skel_t *work_item;
+
+      SVN_DBG(("svn:keywords found\n"));
+      SVN_ERR(svn_wc__internal_translated_file(&tmptext, local_abspath,
+                                               rtb->db, local_abspath,
+                                               SVN_WC_TRANSLATE_TO_NF
+                                               | 
SVN_WC_TRANSLATE_NO_OUTPUT_CLEANUP,
+                                               rtb->cancel_func,
+                                               rtb->cancel_baton,
+                                               scratch_pool, scratch_pool));
+
+      SVN_ERR(svn_wc__wq_build_file_install(&all_work_items, rtb->db,
+                                            local_abspath,
+                                            tmptext, /* install_from */
+                                            TRUE, /* use_commit_times */
+                                            TRUE, /* record_fileinfo */
+                                            scratch_pool, scratch_pool));
+      SVN_ERR(svn_wc__wq_build_file_remove(&work_item, rtb->db, tmptext,
+                                           scratch_pool, scratch_pool));
+      all_work_items = svn_wc__wq_merge(all_work_items, work_item,
+                                        scratch_pool);
+
+      /* ### Should we really run the wq here? close_file() and
+       * close_directory() runs wq's so I assume that we want them performed
+       * on each item. I had this notion about wq's as something containing
+       * all items in a WC, e.g. we check what needs to be done and then do
+       * it all in one batch. What happens if we have three files done but
+       * three more should have been installed when we get an interrupt? 
+       * Does the editor have some way of marking what has been done and
+       * what has not? E.g. if we run svn_wc_cleanup() on a WC, we're
+       * supposed to finish the remaining work items but the update_editor
+       * may not have recorded all work items, right? Do we check that
+       * revisions match or what? ### */
+      SVN_ERR(svn_wc__wq_run(rtb->db, local_abspath, rtb->cancel_func,
+                             rtb->cancel_baton, scratch_pool));
+    }
+
+  return SVN_NO_ERROR;
+}
+
 /* An svn_delta_editor_t function. */
 static svn_error_t *
 close_edit(void *edit_baton,
            apr_pool_t *pool)
 {
   struct edit_baton *eb = edit_baton;
+  struct reinstall_target_baton rtb;
 
   /* If there is a target and that target is missing, then it
      apparently wasn't re-added by the update process, so we'll
@@ -5151,6 +5221,27 @@ close_edit(void *edit_baton,
   eb->close_edit_complete = TRUE;
   svn_pool_destroy(eb->pool);
 
+  rtb.db = eb->db;
+  rtb.cancel_func = eb->cancel_func;
+  rtb.cancel_baton = eb->cancel_baton;
+
+  /* #1975 - svn switch does not update keywords, exposes the need to update
+   * each and every file with svn:keywords set to have the correct $URL$
+   * set. 
+   *
+   * ### An extra walk of the entire wc? Seriously? Shouldn't switch be
+   * ### blazingly fast? 
+   *
+   * ### This */
+  if (eb->switch_relpath)
+    SVN_ERR(svn_wc__internal_walk_children(eb->db, eb->target_abspath, 
+                                           FALSE /* show_hidden */,
+                                           reinstall_target_with_keywords,
+                                           &rtb, 
+                                           svn_depth_infinity, /* ### Fix */
+                                           eb->cancel_func,
+                                           eb->cancel_baton, pool));
+
   return SVN_NO_ERROR;
 }
 

Reply via email to