Author: stsp
Date: Sat Dec 19 14:13:18 2009
New Revision: 892471

URL: http://svn.apache.org/viewvc?rev=892471&view=rev
Log:
Allow keyword expansion to be disabled during 'svn export' using
a new --ignore-keywords option.

In some scenarios expanded keywords create unnecessary noise.
E.g. if files exported from Subversion need to be compared with files
from other sources, such as after a migration from another version
control system to Subversion.
Or, if two Subversion URLs need to be compared reliably using 'svn export'
(currently a 2-URL diff from 'svn diff' doesn't show deleted files properly,
see issue #2333).

* subversion/include/svn_client.h
  (svn_client_export5): Declare, document new ignore_keywords parameter.
  (svn_client_export4): Deprecate.

* subversion/libsvn_client/deprecated.c
  (svn_client_export4): Moved here from ...

* subversion/libsvn_client/export.c
  (svn_client_export4): ... here.
  (copy_one_versioned_file, copy_versioned_files): Add and handle new
   ignore_keywords parameter.
  (edit_baton): Add ignore_keywords field.
  (change_file_prop): Heed new ignore_keywords in edit_baton.
  (svn_client_export5): Add ignore_keywords parameter, pass it on to
   the edit_baton and copy_versioned_files().

* subversion/svn/cl.h
  (svn_cl__opt_state_t): Add ignore_keywords field.

* subversion/svn/export-cmd.c
  (svn_cl__export): Upgrade to svn_client_export5().

* subversion/svn/main.c
  (svn_cl__longopt_t): Add opt_ignore_keywords field.
  (svn_cl__options): Add entry for --ignore-keywords, alias --ik.
  (svn_cl__cmd_table): Add opt_ignore_keywords to the list of options
   supported by 'svn export'.
  (main): Handle new --ignore-keywords option.

* subversion/tests/cmdline/export_tests.py
  (export_ignoring_keyword_translation,
   export_working_copy_ignoring_keyword_translation): New tests.
  (test_list): Add new tests.

Modified:
    subversion/trunk/subversion/include/svn_client.h
    subversion/trunk/subversion/libsvn_client/deprecated.c
    subversion/trunk/subversion/libsvn_client/export.c
    subversion/trunk/subversion/svn/cl.h
    subversion/trunk/subversion/svn/export-cmd.c
    subversion/trunk/subversion/svn/main.c
    subversion/trunk/subversion/tests/cmdline/export_tests.py

Modified: subversion/trunk/subversion/include/svn_client.h
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_client.h?rev=892471&r1=892470&r2=892471&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_client.h (original)
+++ subversion/trunk/subversion/include/svn_client.h Sat Dec 19 14:13:18 2009
@@ -4033,6 +4033,9 @@
  * If @a ignore_externals is set, don't process externals definitions
  * as part of this operation.
  *
+ * If @a ignore_keywords is set, don't expand keywords as part of this
+ * operation.
+ *
  * @a native_eol allows you to override the standard eol marker on the platform
  * you are running on.  Can be either "LF", "CR" or "CRLF" or NULL.  If NULL
  * will use the standard eol marker.  Any other value will cause the
@@ -4047,6 +4050,28 @@
  *
  * All allocations are done in @a pool.
  *
+ * @since New in 1.7.
+ */
+svn_error_t *
+svn_client_export5(svn_revnum_t *result_rev,
+                   const char *from,
+                   const char *to,
+                   const svn_opt_revision_t *peg_revision,
+                   const svn_opt_revision_t *revision,
+                   svn_boolean_t overwrite,
+                   svn_boolean_t ignore_externals,
+                   svn_boolean_t ignore_keywords,
+                   svn_depth_t depth,
+                   const char *native_eol,
+                   svn_client_ctx_t *ctx,
+                   apr_pool_t *pool);
+
+/**
+ * Similar to svn_client_export5(), but with @a ignore_keywords set
+ * to FALSE.
+ *
+ * @deprecated Provided for backward compatibility with the 1.5 API.
+ *
  * @since New in 1.5.
  */
 svn_error_t *

Modified: subversion/trunk/subversion/libsvn_client/deprecated.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/deprecated.c?rev=892471&r1=892470&r2=892471&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/deprecated.c (original)
+++ subversion/trunk/subversion/libsvn_client/deprecated.c Sat Dec 19 14:13:18 
2009
@@ -860,6 +860,24 @@
 
 /*** From export.c ***/
 svn_error_t *
+svn_client_export4(svn_revnum_t *result_rev,
+                   const char *from,
+                   const char *to,
+                   const svn_opt_revision_t *peg_revision,
+                   const svn_opt_revision_t *revision,
+                   svn_boolean_t overwrite,
+                   svn_boolean_t ignore_externals,
+                   svn_depth_t depth,
+                   const char *native_eol,
+                   svn_client_ctx_t *ctx,
+                   apr_pool_t *pool)
+{
+  return svn_client_export5(result_rev, from, to, peg_revision, revision,
+                            overwrite, ignore_externals, FALSE, depth,
+                            native_eol, ctx, pool);
+}
+
+svn_error_t *
 svn_client_export3(svn_revnum_t *result_rev,
                    const char *from,
                    const char *to,

Modified: subversion/trunk/subversion/libsvn_client/export.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/export.c?rev=892471&r1=892470&r2=892471&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/export.c (original)
+++ subversion/trunk/subversion/libsvn_client/export.c Sat Dec 19 14:13:18 2009
@@ -101,6 +101,7 @@
                         svn_wc_context_t *wc_ctx,
                         const svn_opt_revision_t *revision,
                         const char *native_eol,
+                        svn_boolean_t ignore_keywords,
                         apr_pool_t *scratch_pool)
 {
   const svn_wc_entry_t *entry;
@@ -245,7 +246,7 @@
                                              eol,
                                              FALSE /* repair */,
                                              kw,
-                                             TRUE /* expand */,
+                                             ! ignore_keywords /* expand */,
                                              scratch_pool);
 
   /* ###: use cancel func/baton in place of NULL/NULL below. */
@@ -271,6 +272,7 @@
                      const svn_opt_revision_t *revision,
                      svn_boolean_t force,
                      svn_boolean_t ignore_externals,
+                     svn_boolean_t ignore_keywords,
                      svn_depth_t depth,
                      const char *native_eol,
                      svn_client_ctx_t *ctx,
@@ -369,7 +371,8 @@
 
                   SVN_ERR(copy_versioned_files(new_from, new_to,
                                                revision, force,
-                                               ignore_externals, depth,
+                                               ignore_externals,
+                                               ignore_keywords, depth,
                                                native_eol, ctx, iterpool));
                 }
             }
@@ -391,7 +394,8 @@
 
               SVN_ERR(copy_one_versioned_file(new_from_abspath, new_to_abspath,
                                               ctx->wc_ctx, revision,
-                                              native_eol, iterpool));
+                                              native_eol, ignore_keywords,
+                                              iterpool));
             }
         }
 
@@ -435,6 +439,7 @@
 
                   SVN_ERR(copy_versioned_files(new_from, new_to,
                                                revision, force, FALSE,
+                                               ignore_keywords,
                                                svn_depth_infinity, native_eol,
                                                ctx, iterpool));
                 }
@@ -446,7 +451,8 @@
   else if (from_kind == svn_node_file)
     {
       SVN_ERR(copy_one_versioned_file(from_abspath, to_abspath, ctx->wc_ctx,
-                                      revision, native_eol, pool));
+                                      revision, native_eol, ignore_keywords,
+                                      pool));
     }
 
   return SVN_NO_ERROR;
@@ -511,6 +517,7 @@
   svn_revnum_t *target_revision;
   apr_hash_t *externals;
   const char *native_eol;
+  svn_boolean_t ignore_keywords;
 
   svn_wc_notify_func2_t notify_func;
   void *notify_baton;
@@ -739,7 +746,8 @@
   if (strcmp(name, SVN_PROP_EOL_STYLE) == 0)
     fb->eol_style_val = svn_string_dup(value, fb->pool);
 
-  else if (strcmp(name, SVN_PROP_KEYWORDS) == 0)
+  else if (! fb->edit_baton->ignore_keywords &&
+           strcmp(name, SVN_PROP_KEYWORDS) == 0)
     fb->keywords_val = svn_string_dup(value, fb->pool);
 
   else if (strcmp(name, SVN_PROP_EXECUTABLE) == 0)
@@ -868,13 +876,14 @@
 /*** Public Interfaces ***/
 
 svn_error_t *
-svn_client_export4(svn_revnum_t *result_rev,
+svn_client_export5(svn_revnum_t *result_rev,
                    const char *from,
                    const char *to,
                    const svn_opt_revision_t *peg_revision,
                    const svn_opt_revision_t *revision,
                    svn_boolean_t overwrite,
                    svn_boolean_t ignore_externals,
+                   svn_boolean_t ignore_keywords,
                    svn_depth_t depth,
                    const char *native_eol,
                    svn_client_ctx_t *ctx,
@@ -915,6 +924,7 @@
       eb->notify_baton = ctx->notify_baton2;
       eb->externals = apr_hash_make(pool);
       eb->native_eol = native_eol;
+      eb->ignore_keywords = ignore_keywords;
 
       SVN_ERR(svn_ra_check_path(ra_session, "", revnum, &kind, pool));
 
@@ -1038,8 +1048,8 @@
       /* This is a working copy export. */
       /* just copy the contents of the working copy into the target path. */
       SVN_ERR(copy_versioned_files(from, to, revision, overwrite,
-                                   ignore_externals, depth, native_eol,
-                                   ctx, pool));
+                                   ignore_externals, ignore_keywords,
+                                   depth, native_eol, ctx, pool));
     }
 
 

Modified: subversion/trunk/subversion/svn/cl.h
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/svn/cl.h?rev=892471&r1=892470&r2=892471&view=diff
==============================================================================
--- subversion/trunk/subversion/svn/cl.h (original)
+++ subversion/trunk/subversion/svn/cl.h Sat Dec 19 14:13:18 2009
@@ -222,6 +222,7 @@
   svn_boolean_t trust_server_cert; /* trust server SSL certs that would
                                       otherwise be rejected as "untrusted" */
   int strip_count; /* number of leading path components to strip */
+  svn_boolean_t ignore_keywords;  /* do not expand keywords */
 } svn_cl__opt_state_t;
 
 

Modified: subversion/trunk/subversion/svn/export-cmd.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/svn/export-cmd.c?rev=892471&r1=892470&r2=892471&view=diff
==============================================================================
--- subversion/trunk/subversion/svn/export-cmd.c (original)
+++ subversion/trunk/subversion/svn/export-cmd.c Sat Dec 19 14:13:18 2009
@@ -91,12 +91,11 @@
     opt_state->depth = svn_depth_infinity;
 
   /* Do the export. */
-  err = svn_client_export4(NULL, truefrom, to, &peg_revision,
+  err = svn_client_export5(NULL, truefrom, to, &peg_revision,
                            &(opt_state->start_revision),
                            opt_state->force, opt_state->ignore_externals,
-                           opt_state->depth,
-                           opt_state->native_eol, ctx,
-                           pool);
+                           opt_state->ignore_keywords, opt_state->depth,
+                           opt_state->native_eol, ctx, pool);
   if (err && err->apr_err == SVN_ERR_WC_OBSTRUCTED_UPDATE && !opt_state->force)
     SVN_ERR_W(err,
               _("Destination directory exists; please remove "

Modified: subversion/trunk/subversion/svn/main.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/svn/main.c?rev=892471&r1=892470&r2=892471&view=diff
==============================================================================
--- subversion/trunk/subversion/svn/main.c (original)
+++ subversion/trunk/subversion/svn/main.c Sat Dec 19 14:13:18 2009
@@ -114,7 +114,8 @@
   opt_show_revs,
   opt_reintegrate,
   opt_trust_server_cert,
-  opt_show_copies_as_adds
+  opt_show_copies_as_adds,
+  opt_ignore_keywords
 } svn_cl__longopt_t;
 
 /* Option codes and descriptions for the command line client.
@@ -309,6 +310,10 @@
                        "while -p2 would give just crunchy.html")},
   {"show-copies-as-adds", opt_show_copies_as_adds, 0,
                     N_("don't diff copied or moved files with their source")},
+  {"ignore-keywords", opt_ignore_keywords, 0,
+                    N_("don't expand keywords\n"
+                       "                             "
+                       "[aliases: --ik]")},
 
   /* Long-opt Aliases
    *
@@ -318,6 +323,7 @@
 
   {"cl",            opt_changelist, 1, NULL},
   {"ie",            opt_ignore_externals, 0, NULL},
+  {"ik",            opt_ignore_keywords, 0, NULL},
 
   {0,               0, 0, 0},
 };
@@ -514,7 +520,8 @@
      "\n"
      "  If specified, PEGREV determines in which revision the target is 
first\n"
      "  looked up.\n"),
-    {'r', 'q', 'N', opt_depth, opt_force, opt_native_eol, 
opt_ignore_externals} },
+    {'r', 'q', 'N', opt_depth, opt_force, opt_native_eol, opt_ignore_externals,
+     opt_ignore_keywords} },
 
   { "help", svn_cl__help, {"?", "h"}, N_
     ("Describe the usage of this program or its subcommands.\n"
@@ -1660,6 +1667,9 @@
             }
         }
         break;
+      case opt_ignore_keywords:
+        opt_state.ignore_keywords = TRUE;
+        break;
       default:
         /* Hmmm. Perhaps this would be a good place to squirrel away
            opts that commands like svn diff might need. Hmmm indeed. */

Modified: subversion/trunk/subversion/tests/cmdline/export_tests.py
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/export_tests.py?rev=892471&r1=892470&r2=892471&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/export_tests.py (original)
+++ subversion/trunk/subversion/tests/cmdline/export_tests.py Sat Dec 19 
14:13:18 2009
@@ -422,6 +422,67 @@
                                         '.', expected_output,
                                         expected_disk)
 
+def export_ignoring_keyword_translation(sbox):
+  "export ignoring keyword translation"
+  sbox.build()
+
+  wc_dir = sbox.wc_dir
+
+  # Add a keyword to A/mu and set the svn:keywords property
+  # appropriately to make sure it's not translated during
+  # the export operation
+  mu_path = os.path.join(wc_dir, 'A', 'mu')
+  svntest.main.file_append(mu_path, '$LastChangedRevision$')
+  svntest.main.run_svn(None, 'ps', 'svn:keywords',
+                       'LastChangedRevision', mu_path)
+  svntest.main.run_svn(None, 'ci',
+                       '-m', 'Added keyword to mu', mu_path)
+
+  expected_disk = svntest.main.greek_state.copy()
+  expected_disk.tweak('A/mu',
+                      contents=expected_disk.desc['A/mu'].contents +
+                      '$LastChangedRevision$')
+
+  export_target = sbox.add_wc_path('export')
+
+  expected_output = svntest.main.greek_state.copy()
+  expected_output.wc_dir = export_target
+  expected_output.desc[''] = Item()
+  expected_output.tweak(contents=None, status='A ')
+
+  svntest.actions.run_and_verify_export(sbox.repo_url,
+                                        export_target,
+                                        expected_output,
+                                        expected_disk,
+                                        "--ignore-keywords")
+
+def export_working_copy_ignoring_keyword_translation(sbox):
+  "export working copy ignoring keyword translation"
+  sbox.build(read_only = True)
+
+  wc_dir = sbox.wc_dir
+
+  # Add a keyword to A/mu and set the svn:keywords property
+  # appropriately to make sure it's not translated during
+  # the export operation
+  mu_path = os.path.join(wc_dir, 'A', 'mu')
+  svntest.main.file_append(mu_path, '$LastChangedRevision$')
+  svntest.main.run_svn(None, 'ps', 'svn:keywords',
+                       'LastChangedRevision', mu_path)
+
+  expected_disk = svntest.main.greek_state.copy()
+  expected_disk.tweak('A/mu',
+                      contents=expected_disk.desc['A/mu'].contents +
+                      '$LastChangedRevision$')
+
+  export_target = sbox.add_wc_path('export')
+
+  svntest.actions.run_and_verify_export(wc_dir,
+                                        export_target,
+                                        svntest.wc.State(sbox.wc_dir, {}),
+                                        expected_disk,
+                                        "--ignore-keywords")
+
 ########################################################################
 # Run the tests
 
@@ -446,6 +507,8 @@
               export_creates_intermediate_folders,
               export_HEADplus1_fails,
               export_to_explicit_cwd,
+              export_ignoring_keyword_translation,
+              export_working_copy_ignoring_keyword_translation,
              ]
 
 if __name__ == '__main__':


Reply via email to