subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From s...@apache.org
Subject svn commit: r903284 - in /subversion/trunk/subversion: include/svn_wc.h libsvn_client/patch.c svn/notify.c tests/cmdline/patch_tests.py
Date Tue, 26 Jan 2010 15:46:59 GMT
Author: stsp
Date: Tue Jan 26 15:46:59 2010
New Revision: 903284

URL: http://svn.apache.org/viewvc?rev=903284&view=rev
Log:
Make svn patch provide notifications about individual hunks.
Make the CLI client print them.

* subversion/include/svn_wc.h
  (svn_wc_notify_action_t): New actions svn_wc_notify_patch_applied_hunk
   and svn_wc_notify_patch_rejected_hunk.
  (svn_wc_notify_t): New fields hunk_original_start, hunk_original_length,
   hunk_modified_start, hunk_modified_length, and hunk_matched_line.

* subversion/libsvn_client/patch.c
  (hunk_info_t): New field REJECTED.
  (patch_target_t): Rename MATCHED_HUNKS to just HUNKS.
  (init_patch_target): Track renamed field.
  (get_hunk_info): Initialise new field in hunk_info_t.
  (reject_hunk): Accept a hunk_info_t instead of a plain hunk,
   and mark it rejected. Add docstring.
  (apply_one_hunk): Swap TARGET and HI parameters for consistency.
   Pass HI to reject_hunk().
  (maybe_send_patch_notification): Send notifications for all hunks
   if the target was patched (or we attempted to patch it).
  (apply_one_patch): Pass a hunk info to reject_hunk. Track renamed
   field in patch_target_t. Put all hunks into TARGET->HUNKS, not
   just the ones we could match. The ones we could not match are
   marked rejected, don't apply those.

* subversion/svn/notify.c
  (notify): Print hunk-level notifications.

* subversion/tests/cmdline/patch_tests.py
  (patch_unidiff, patch_unidiff_absolute_paths, patch_unidiff_offset,
   patch_chopped_leading_spaces, patch_unidiff_strip1): Adjust expected output.


Modified:
    subversion/trunk/subversion/include/svn_wc.h
    subversion/trunk/subversion/libsvn_client/patch.c
    subversion/trunk/subversion/svn/notify.c
    subversion/trunk/subversion/tests/cmdline/patch_tests.py

Modified: subversion/trunk/subversion/include/svn_wc.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_wc.h?rev=903284&r1=903283&r2=903284&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_wc.h (original)
+++ subversion/trunk/subversion/include/svn_wc.h Tue Jan 26 15:46:59 2010
@@ -1064,6 +1064,14 @@
   /** A file in the working copy was patched.
    * @since New in 1.7. */
   svn_wc_notify_patch,
+
+  /** A hunk from a patch was applied.
+   * @since New in 1.7. */
+  svn_wc_notify_patch_applied_hunk,
+
+  /** A hunk from a patch was rejected.
+   * @since New in 1.7. */
+  svn_wc_notify_patch_rejected_hunk,
 } svn_wc_notify_action_t;
 
 
@@ -1227,6 +1235,19 @@
    * @since New in 1.7 */
   svn_revnum_t old_revision;
 
+  /* These fields are used by svn patch to identify the
+   * hunk the notification is for. They are line-based
+   * offsets and lengths parsed from the unidiff hunk header.
+   * @since New in 1.7. */
+  svn_linenum_t hunk_original_start;
+  svn_linenum_t hunk_original_length;
+  svn_linenum_t hunk_modified_start;
+  svn_linenum_t hunk_modified_length;
+
+  /* The line at which a hunk was matched (and applied).
+   * @since New in 1.7. */
+  svn_linenum_t hunk_matched_line;
+
   /* NOTE: Add new fields at the end to preserve binary compatibility.
      Also, if you add fields here, you have to update svn_wc_create_notify
      and svn_wc_dup_notify. */

Modified: subversion/trunk/subversion/libsvn_client/patch.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/patch.c?rev=903284&r1=903283&r2=903284&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/patch.c (original)
+++ subversion/trunk/subversion/libsvn_client/patch.c Tue Jan 26 15:46:59 2010
@@ -48,6 +48,9 @@
 
   /* The line where the hunk matched in the target file. */
   svn_linenum_t matched_line;
+
+  /* Whether this hunk has been rejected. */
+  svn_boolean_t rejected;
 } hunk_info_t;
 
 typedef struct {
@@ -112,7 +115,7 @@
   apr_array_header_t *lines;
 
   /* An array containing hunk_info_t structures for hunks already matched. */
-  apr_array_header_t *matched_hunks;
+  apr_array_header_t *hunks;
 
   /* The node kind of the target as found on disk prior
    * to patch application. */
@@ -439,8 +442,7 @@
   new_target->pool = result_pool;
   new_target->lines = apr_array_make(result_pool, 0,
                                      sizeof(svn_stream_mark_t *));
-  new_target->matched_hunks = apr_array_make(result_pool, 0,
-                                             sizeof(hunk_info_t *));
+  new_target->hunks = apr_array_make(result_pool, 0, sizeof(hunk_info_t *));
   *target = new_target;
   return SVN_NO_ERROR;
 }
@@ -608,11 +610,11 @@
           svn_boolean_t taken = FALSE;
 
           /* Don't allow hunks to match at overlapping locations. */
-          for (i = 0; i < target->matched_hunks->nelts; i++)
+          for (i = 0; i < target->hunks->nelts; i++)
             {
-              const hunk_info_t *hi;
+              hunk_info_t *hi;
               
-              hi = APR_ARRAY_IDX(target->matched_hunks, i, hunk_info_t *);
+              hi = APR_ARRAY_IDX(target->hunks, i, hunk_info_t *);
               taken = (target->current_line >= hi->matched_line &&
                        target->current_line < hi->matched_line +
                                               hi->hunk->original_length);
@@ -690,8 +692,9 @@
     }
 
   (*hi) = apr_palloc(result_pool, sizeof(hunk_info_t));
-  (*hi)->matched_line = matched_line;
   (*hi)->hunk = hunk;
+  (*hi)->matched_line = matched_line;
+  (*hi)->rejected = FALSE;
 
   return SVN_NO_ERROR;
 }
@@ -782,29 +785,37 @@
 }
 
 
+/* Write a hunk described by hunk info HI to the reject stream of TARGET,
+ * mark the hunk as rejected, and mark TARGET as having had rejects.
+ * Do all allocations in POOL. */
 static svn_error_t *
-reject_hunk(patch_target_t *target, const svn_hunk_t *hunk, apr_pool_t *pool)
+reject_hunk(patch_target_t *target, hunk_info_t *hi, apr_pool_t *pool)
 {
   const char *hunk_header;
   apr_size_t len;
 
   hunk_header = apr_psprintf(pool, "@@ -%lu,%lu +%lu,%lu @@%s",
-                             hunk->original_start, hunk->original_length,
-                             hunk->modified_start, hunk->modified_length,
+                             hi->hunk->original_start,
+                             hi->hunk->original_length,
+                             hi->hunk->modified_start,
+                             hi->hunk->modified_length,
                              target->eol_str);
   len = strlen(hunk_header);
   SVN_ERR(svn_stream_write(target->reject, hunk_header, &len));
 
-  SVN_ERR(copy_hunk_text(hunk->diff_text, target->reject,
+  SVN_ERR(copy_hunk_text(hi->hunk->diff_text, target->reject,
                          target->reject_path, pool));
 
   target->had_rejects = TRUE;
+  hi->rejected = TRUE;
+
   return SVN_NO_ERROR;
 }
 
-/* Apply a HUNK to a patch TARGET. Do all allocations in POOL. */
+/* Apply a hunk described by hunk info HI to a patch TARGET.
+ * Do all allocations in POOL. */
 static svn_error_t *
-apply_one_hunk(const hunk_info_t *hi, patch_target_t *target, apr_pool_t *pool)
+apply_one_hunk(patch_target_t *target, hunk_info_t *hi, apr_pool_t *pool)
 {
   if (target->kind == svn_node_file)
     {
@@ -813,7 +824,7 @@
       if (target->eof)
         {
           /* File is shorter than it should be. */
-          SVN_ERR(reject_hunk(target, hi->hunk, pool));
+          SVN_ERR(reject_hunk(target, hi, pool));
           return SVN_NO_ERROR;
         }
 
@@ -881,6 +892,39 @@
 
   (*ctx->notify_func2)(ctx->notify_baton2, notify, pool);
 
+  if (action == svn_wc_notify_patch)
+    {
+      int i;
+      apr_pool_t *iterpool;
+
+      iterpool = svn_pool_create(pool);
+      for (i = 0; i < target->hunks->nelts; i++)
+        {
+          hunk_info_t *hi;
+
+          svn_pool_clear(iterpool);
+
+          hi = APR_ARRAY_IDX(target->hunks, i, hunk_info_t *);
+
+          if (hi->rejected)
+            action = svn_wc_notify_patch_rejected_hunk;
+          else
+            action = svn_wc_notify_patch_applied_hunk;
+
+          notify = svn_wc_create_notify(target->abs_path ? target->abs_path
+                                                         : target->rel_path,
+                                        action, pool);
+          notify->hunk_original_start = hi->hunk->original_start;
+          notify->hunk_original_length = hi->hunk->original_length;
+          notify->hunk_modified_start = hi->hunk->modified_start;
+          notify->hunk_modified_length = hi->hunk->original_length;
+          notify->hunk_matched_line = hi->matched_line;
+
+          (*ctx->notify_func2)(ctx->notify_baton2, notify, pool);
+        }
+      svn_pool_destroy(iterpool);
+    }
+
   return SVN_NO_ERROR;
 }
 
@@ -927,21 +971,22 @@
       if (hi->matched_line == 0)
         {
           /* The hunk does not apply, reject it. */
-          SVN_ERR(reject_hunk(target, hunk, iterpool));
+          SVN_ERR(reject_hunk(target, hi, iterpool));
         }
       else
-        APR_ARRAY_PUSH(target->matched_hunks, hunk_info_t *) = hi;
+        APR_ARRAY_PUSH(target->hunks, hunk_info_t *) = hi;
     }
 
   /* Apply hunks. */
-  for (i = 0; i < target->matched_hunks->nelts; i++)
+  for (i = 0; i < target->hunks->nelts; i++)
     {
-      const hunk_info_t *hi;
+      hunk_info_t *hi;
 
       svn_pool_clear(iterpool);
 
-      hi = APR_ARRAY_IDX(target->matched_hunks, i, const hunk_info_t *);
-      SVN_ERR(apply_one_hunk(hi, target, iterpool));
+      hi = APR_ARRAY_IDX(target->hunks, i, hunk_info_t *);
+      if (! hi->rejected)
+        SVN_ERR(apply_one_hunk(target, hi, iterpool));
     }
   svn_pool_destroy(iterpool);
 

Modified: subversion/trunk/subversion/svn/notify.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/svn/notify.c?rev=903284&r1=903283&r2=903284&view=diff
==============================================================================
--- subversion/trunk/subversion/svn/notify.c (original)
+++ subversion/trunk/subversion/svn/notify.c Tue Jan 26 15:46:59 2010
@@ -288,6 +288,52 @@
         goto print_error;
       break;
 
+    case svn_wc_notify_patch_applied_hunk:
+      nb->received_some_change = TRUE;
+      if ((err = svn_cmdline_printf(pool,
+                                    ">         applied hunk "
+                                    "@@ -%lu,%lu +%lu,%lu @@",
+                                    n->hunk_original_start,
+                                    n->hunk_original_length,
+                                    n->hunk_modified_start,
+                                    n->hunk_modified_length)))
+        goto print_error;
+      if (n->hunk_original_start != n->hunk_matched_line)
+        {
+          apr_int64_t off;
+          const char *s;
+
+          if (n->hunk_matched_line > n->hunk_original_start)
+            {
+              off = n->hunk_matched_line - n->hunk_original_start;
+              s = "";
+            }
+          else
+            {
+              off = n->hunk_original_start - n->hunk_matched_line;
+              s = "-";
+            }
+          if ((err = svn_cmdline_printf(pool,
+                                        " with offset %s%"APR_INT64_T_FMT,
+                                        s, off)))
+            goto print_error;
+        }
+      if ((err = svn_cmdline_printf(pool, "\n")))
+        goto print_error;
+      break;
+
+    case svn_wc_notify_patch_rejected_hunk:
+      nb->received_some_change = TRUE;
+      if ((err = svn_cmdline_printf(pool,
+                                    ">         rejected hunk "
+                                    "@@ -%lu,%lu +%lu,%lu @@\n",
+                                    n->hunk_original_start,
+                                    n->hunk_original_length,
+                                    n->hunk_modified_start,
+                                    n->hunk_modified_length)))
+        goto print_error;
+      break;
+
     case svn_wc_notify_update_update:
     case svn_wc_notify_merge_record_info:
       {

Modified: subversion/trunk/subversion/tests/cmdline/patch_tests.py
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/patch_tests.py?rev=903284&r1=903283&r2=903284&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/patch_tests.py (original)
+++ subversion/trunk/subversion/tests/cmdline/patch_tests.py Tue Jan 26 15:46:59 2010
@@ -187,9 +187,13 @@
 
   expected_output = [
     'U         %s\n' % os.path.join(wc_dir, 'A', 'D', 'gamma'),
+    '>         applied hunk @@ -1,1 +1,1 @@\n',
     'U         %s\n' % os.path.join(wc_dir, 'iota'),
+    '>         applied hunk @@ -1,1 +1,1 @@\n',
     'A         %s\n' % os.path.join(wc_dir, 'new'),
     'U         %s\n' % os.path.join(wc_dir, 'A', 'mu'),
+    '>         applied hunk @@ -6,6 +6,6 @@\n',
+    '>         applied hunk @@ -14,11 +17,11 @@\n',
     'D         %s\n' % os.path.join(wc_dir, 'A', 'B', 'E', 'beta'),
   ]
 
@@ -257,6 +261,7 @@
   lambda_path = os.path.join(os.path.sep, 'A', 'B', 'lambda')
   expected_output = [
     'U         %s\n' % os.path.join('A', 'B', 'E', 'alpha'),
+    '>         applied hunk @@ -1,1 +1,1 @@\n',
     'Skipped \'%s\'\n' % lambda_path,
     'Summary of conflicts:\n',
     '  Skipped paths: 1\n'
@@ -471,7 +476,10 @@
 
   expected_output = [
     'U         %s\n' % os.path.join('A', 'mu'),
-    'U         iota\n'
+    '>         applied hunk @@ -6,6 +6,6 @@ with offset -1\n',
+    '>         applied hunk @@ -14,11 +17,11 @@ with offset 4\n',
+    'U         iota\n',
+    '>         applied hunk @@ -5,6 +5,6 @@ with offset -3\n',
   ]
 
   expected_disk = svntest.main.greek_state.copy()
@@ -631,9 +639,13 @@
 
   expected_output = [
     'U         %s\n' % os.path.join(wc_dir, 'A', 'D', 'gamma'),
+    '>         applied hunk @@ -1,1 +1,1 @@\n',
     'U         %s\n' % os.path.join(wc_dir, 'iota'),
+    '>         applied hunk @@ -1,1 +1,1 @@\n',
     'A         %s\n' % os.path.join(wc_dir, 'new'),
     'U         %s\n' % os.path.join(wc_dir, 'A', 'mu'),
+    '>         applied hunk @@ -6,6 +6,6 @@\n',
+    '>         applied hunk @@ -14,11 +17,11 @@\n',
     'D         %s\n' % os.path.join(wc_dir, 'A', 'B', 'E', 'beta'),
   ]
 
@@ -801,9 +813,13 @@
 
   expected_output = [
     'U         %s\n' % os.path.join(wc_dir, 'A', 'D', 'gamma'),
+    '>         applied hunk @@ -1,1 +1,1 @@\n',
     'U         %s\n' % os.path.join(wc_dir, 'iota'),
+    '>         applied hunk @@ -1,1 +1,1 @@\n',
     'A         %s\n' % os.path.join(wc_dir, 'new'),
     'U         %s\n' % os.path.join(wc_dir, 'A', 'mu'),
+    '>         applied hunk @@ -6,6 +6,6 @@\n',
+    '>         applied hunk @@ -14,11 +17,11 @@\n',
     'D         %s\n' % os.path.join(wc_dir, 'A', 'B', 'E', 'beta'),
   ]
 



Mime
View raw message