Daniel Berlin <dberlin@dberlin.org> writes:
> Theoretically, one should be able to use the libsvn_diff API, which
> tells you "lines from start to end in original were modified to become
> lines start to end in new file", and produce the explicit adds and
> deletes from that, but i haven't been able to get it to work right.
>
> In fact, diff -n is more or less doing this in order to produce the info
> it gives us. So we should be able to do it too  :).
I'm not quite sure what you need, or what you can't get to work.
The patch below is a quick hack that overides the current diff output
vtable, so it's not suitable for the repository.  Diff clients, like
the test program 'subversion/tests/libsvn_diff/diff-test', will output
approximate 'diff -n' output (the patch reuses the unified code so
each line representing an added line has a leading space).
Subversion and GNU sometimes choose different sequences to convert one
file into another so their outputs don't always match but they should
effect the same transformation.
Index: subversion/libsvn_diff/diff_file.c
===================================================================
--- subversion/libsvn_diff/diff_file.c	(revision 13689)
+++ subversion/libsvn_diff/diff_file.c	(working copy)
@@ -805,6 +805,45 @@
 }
 
 static
+svn_error_t *
+file_output_rcs_diff_modified(void *baton,
+                                  apr_off_t original_start,
+                                  apr_off_t original_length,
+                                  apr_off_t modified_start,
+                                  apr_off_t modified_length,
+                                  apr_off_t latest_start,
+                                  apr_off_t latest_length)
+{
+  svn_diff__file_output_baton_t *output_baton = baton;
+
+  if (original_length > 0)
+    printf("d%ld %ld\n", original_start + 1, original_length);
+
+  if (modified_length > 0)
+    {
+      printf("a%ld %ld\n", original_start + original_length, modified_length);
+
+      while (output_baton->current_line[1] < modified_start)
+          SVN_ERR(svn_diff__file_output_unified_line
+                  (output_baton, svn_diff__file_output_unified_skip, 1));
+      while (output_baton->current_line[1] < modified_start + modified_length)
+          SVN_ERR(svn_diff__file_output_unified_line
+                  (output_baton, svn_diff__file_output_unified_context, 1));
+
+      {
+        apr_size_t hunk_len = output_baton->hunk->len;
+        SVN_ERR(svn_stream_write(output_baton->output_stream,
+                                 output_baton->hunk->data,
+                                 &hunk_len));
+        output_baton->hunk_length[1] = 0;
+        svn_stringbuf_setempty(output_baton->hunk);
+      }
+    }
+
+  return SVN_NO_ERROR;
+}
+
+static
 const char *
 svn_diff__file_output_unified_default_hdr(apr_pool_t *pool,
                                           const char *path)
@@ -826,7 +865,7 @@
 static const svn_diff_output_fns_t svn_diff__file_output_unified_vtable =
 {
   NULL, /* output_common */
-  svn_diff__file_output_unified_diff_modified,
+  file_output_rcs_diff_modified,
   NULL, /* output_diff_latest */
   NULL, /* output_diff_common */
   NULL  /* output_conflict */
-- 
Philip Martin
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Sat Mar 26 23:47:31 2005