[prev in list] [next in list] [prev in thread] [next in thread] 

List:       subversion-cvs
Subject:    svn commit: rev 1610 - trunk/subversion/include trunk/subversion/libsvn_wc trunk/subversion/libsvn_c
From:       sussman () tigris ! org
Date:       2002-03-29 21:35:07
[Download RAW message or body]

Author: sussman
Date: 2002-03-29 21:34 GMT
New Revision: 1610

Modified:
   trunk/subversion/include/svn_delta.h
   trunk/subversion/include/svn_types.h
   trunk/subversion/include/svn_wc.h
   trunk/subversion/libsvn_client/client.h
   trunk/subversion/libsvn_client/diff.c
   trunk/subversion/libsvn_client/repos_diff.c
   trunk/subversion/libsvn_wc/diff.c
Log:

Reorganize the way 'svn diff' and 'svn merge' share a common diff
editor: instead of a single overloaded callback function to do
diff-related things, use a cleaner vtable.  This allows us to smoothly
deal with directory additions and removals, and with propchanges.
('svn merge' can make use of the entire table, while 'svn diff'
implements only part of the table for now.)

* svn_types.h 
  
  (svn_diff_action_t, svn_diff_cmd_t):  remove these prototypes...

* svn_delta.h
  
  (svn_diff_callbacks_t): ... in favor of a cleaner, less confusing,
  less overloaded vtable.

* libsvn_client/diff.c

  (diff_file_changed, diff_file_added, diff_file_deleted,
  diff_dir_added, diff_dir_deleted, diff_prop_changed): new vtable
  funcs for 'svn diff'...

  (diff_callbacks):  ...placed in here.

  (diff_cmd): removed.  this functionality migrated into diff_file_changed.

  (merge_file_changed, merge_file_added, merge_file_deleted,
  merge_dir_added, merge_dir_deleted, merge_prop_changed): new vtable
  funcs for 'svn merge'...

  (merge_callbacks):  ...placed in here.

  (merge_cmd): removed.  this functionality migrated into merge_file_changed.

  (diff_or_merge): take an svn_diff_callbacks_t table and baton,
  instead of an svn_diff_cmd_t.

  (svn_client_diff, svn_client_merge): pass appropriate vtable to
  diff_or_merge.

* libsvn_client/repos_diff.c 

  (svn_client__get_diff_editor, struct edit_baton): take a callback
  table instead of a single callback.

  (delete_entry):  invoke deletion callbacks for both files *and* dirs.
  (add_directory):  invoke dir_added callback.
  (close_file):  invoke either file_changed or file_added callback.
  (change_file_prop, change_dir_prop): new editor funcs, call
  prop_changed callback.

  (run_diff_cmd):  removed, no longer needed.

* libsvn_client/client.h

  (svn_client__get_diff_editor): take a callback table instead of a
  single callback.

* svn_wc.h

  (svn_wc_diff, svn_wc_get_diff_editor): take a callback table instead
  of a single callback.

* libsvn_wc/diff.c

  (svn_wc_diff, svn_wc_get_diff_editor, struct edit_baton,
  make_editor_baton): take a callback table instead of a single
  callback.

  (file_diff): call either file_changed, file_added, file_deleted callback.
  (delete_entry):  call file_added callback.
  (close_file):  call either file_deleted or file_changed callback.




Modified: trunk/subversion/include/svn_types.h
==============================================================================
--- trunk/subversion/include/svn_types.h	(original)
+++ trunk/subversion/include/svn_types.h	Fri Mar 29 15:35:01 2002
@@ -269,44 +269,6 @@
 
 /*** Shared function types ***/
 
-/* An enum to indicate an action to a diff callback. */
-enum svn_diff_action_t
-{
-  svn_diff_action_modify = 1,
-  svn_diff_action_add,
-  svn_diff_action_delete
-};
-
-
-/* The function type called by the diff editor when it has determined
- * the two files that are to be diffed.  The diff editor is shared by
- * 'svn diff' and 'svn merge' functionality, which differ by their own
- * implementations of this callback.
- *
- * PATH1 and PATH2 are the two files to be compared, these files
- * exist. Since the PATH1 file may be temporary, it is possible that it is
- * not in the "correct" location in the working copy, if this is the case
- * then LABEL will be non-null and will contain the "correct" location.
- *
- * PATH3 is ignored by 'svn diff', but required for 'svn merge'.  It
- * is needed for svn_wc_merge() to perform 3-way diffs; it specifies
- * the 'mine' file, as PATH1 and PATH2 represent 'older' and 'yours'.
- * Similarly, ACTION tells 'merge' how to modify the working copy, and
- * PATH1_REV and PATH2_REV are the revisions of PATH1 and PATH2.  All
- * of these arguments are probably ignored by the 'svn diff' use case.
- *
- * BATON is passed through by the diff editor.
- */
-typedef svn_error_t *(*svn_diff_cmd_t)(const char *path1,
-                                       const char *path2,
-                                       const char *path3,
-                                       const char *label,
-                                       enum svn_diff_action_t action,
-                                       svn_revnum_t path1_rev,
-                                       svn_revnum_t path2_rev,
-                                       void *baton);
-
-
 /* The callback invoked by log message loopers, such as
  * svn_ra_plugin_t.get_log() and svn_repos_get_logs().
  *

Modified: trunk/subversion/include/svn_wc.h
==============================================================================
--- trunk/subversion/include/svn_wc.h	(original)
+++ trunk/subversion/include/svn_wc.h	Fri Mar 29 15:35:01 2002
@@ -903,7 +903,7 @@
  *
  * ANCHOR/TARGET represent the base of the hierarchy to be compared.
  *
- * DIFF_CMD/DIFF_CMD_BATON are the function/baton to be called when two
+ * DIFF_CALLBACKS/DIFF_CMD_BATON is the callback table to use when two
  * files are to be compared.
  *
  * RECURSE determines whether to descend into subdirectories when TARGET
@@ -911,7 +911,7 @@
  */
 svn_error_t *svn_wc_get_diff_editor (svn_stringbuf_t *anchor,
                                      svn_stringbuf_t *target,
-                                     svn_diff_cmd_t diff_cmd,
+                                     svn_diff_callbacks_t *diff_callbacks,
                                      void *diff_cmd_baton,
                                      svn_boolean_t recurse,
                                      const svn_delta_edit_fns_t **editor,
@@ -923,7 +923,7 @@
  *
  * ANCHOR/TARGET represent the base of the hierarchy to be compared.
  *
- * DIFF_CMD/DIFF_CMD_BATON are the function/baton to be called when two
+ * DIFF_CALLBACKS/DIFF_CMD_BATON is the callback table to use when two
  * files are to be compared.
  *
  * RECURSE determines whether to descend into subdirectories when TARGET
@@ -931,7 +931,7 @@
  */
 svn_error_t *svn_wc_diff (svn_stringbuf_t *anchor,
                           svn_stringbuf_t *target,
-                          svn_diff_cmd_t diff_cmd,
+                          svn_diff_callbacks_t *diff_callbacks,
                           void *diff_cmd_baton,
                           svn_boolean_t recurse,
                           apr_pool_t *pool);

Modified: trunk/subversion/include/svn_delta.h
==============================================================================
--- trunk/subversion/include/svn_delta.h	(original)
+++ trunk/subversion/include/svn_delta.h	Fri Mar 29 15:35:01 2002
@@ -969,6 +969,53 @@
 
 
 
+
+
+/* A callback vtable invoked by our diff-editors, as they receive
+   diffs from the server.  'svn diff' and 'svn merge' both implement
+   their own versions of this table. */
+typedef struct svn_diff_callbacks_t
+{
+  /* A file PATH has changed.  The changes can be seen by comparing
+     TMPFILE1 and TMPFILE2, which represent REV1 and REV2 of the file,
+     respectively. */
+  svn_error_t *(*file_changed) (const char *path,
+                                const char *tmpfile1,
+                                const char *tmpfile2,
+                                svn_revnum_t rev1,
+                                svn_revnum_t rev2,
+                                void *diff_baton);
+
+  /* A file PATH was added.  The contents can be seen by comparing
+     TMPFILE1 and TMPFILE2. */
+  svn_error_t *(*file_added) (const char *path,
+                              const char *tmpfile1,
+                              const char *tmpfile2,
+                              void *diff_baton);
+  
+  /* A file PATH was deleted.  The [loss of] contents can be seen by
+     comparing TMPFILE1 and TMPFILE2. */
+  svn_error_t *(*file_deleted) (const char *path,
+                                const char *tmpfile1,
+                                const char *tmpfile2,
+                                void *diff_baton);
+  
+  /* A directory PATH was added. */
+  svn_error_t *(*dir_added) (const char *path,
+                             void *diff_baton);
+  
+  /* A directory PATH was deleted. */
+  svn_error_t *(*dir_deleted) (const char *path,
+                               void *diff_baton);
+  
+  /* A property NAME attached to PATH changed value to VALUE. */
+  svn_error_t *(*prop_changed) (const char *path,
+                                const char *name,
+                                const svn_string_t *value,
+                                void *diff_baton);
+
+} svn_diff_callbacks_t;
+
 
 
 #ifdef __cplusplus

Modified: trunk/subversion/libsvn_wc/diff.c
==============================================================================
--- trunk/subversion/libsvn_wc/diff.c	(original)
+++ trunk/subversion/libsvn_wc/diff.c	Fri Mar 29 15:35:02 2002
@@ -56,9 +56,9 @@
   svn_stringbuf_t *anchor;
   svn_stringbuf_t *target;
 
-  /* The callback and callback argument that implement the file comparison
-     function */
-  svn_diff_cmd_t diff_cmd;
+  /* The callbacks and callback argument that implement the file comparison
+     functions */
+  svn_diff_callbacks_t *diff_callbacks;
   void *diff_cmd_baton;
 
   /* Flags whether to diff recursively or not. If set the diff is
@@ -127,14 +127,14 @@
 
 
 /* Create a new edit baton. TARGET/ANCHOR are working copy paths that
- * describe the root of the comparison. DIFF_CMD/DIFF_CMD_BATON define the
- * callback to compare files. RECURSE defines whether to descend into
- * subdirectories.
+ * describe the root of the comparison. DIFF_CALLBACKS/DIFF_CMD_BATON
+ * define the callbacks to compare files. RECURSE defines whether to
+ * descend into subdirectories.
  */
 static struct edit_baton *
 make_editor_baton (svn_stringbuf_t *anchor,
                    svn_stringbuf_t *target,
-                   svn_diff_cmd_t diff_cmd,
+                   svn_diff_callbacks_t *diff_callbacks,
                    void *diff_cmd_baton,
                    svn_boolean_t recurse,
                    apr_pool_t *pool)
@@ -144,7 +144,7 @@
 
   eb->anchor = anchor;
   eb->target = target;
-  eb->diff_cmd = diff_cmd;
+  eb->diff_callbacks = diff_callbacks;
   eb->diff_cmd_baton = diff_cmd_baton;
   eb->recurse = recurse;
   eb->pool = subpool;
@@ -262,7 +262,6 @@
            svn_wc_entry_t *entry,
            svn_boolean_t added)
 {
-  svn_diff_cmd_t diff_cmd = dir_baton->edit_baton->diff_cmd;
   svn_stringbuf_t *pristine_copy, *empty_file;
   svn_boolean_t modified;
   enum svn_wc_schedule_t schedule = entry->schedule;
@@ -284,12 +283,11 @@
       pristine_copy = svn_wc__text_base_path (path, FALSE, dir_baton->pool);
       empty_file = svn_wc__empty_file_path (path, dir_baton->pool);
 
-      SVN_ERR (diff_cmd (pristine_copy->data, empty_file->data,
-                         path->data, path->data,
-                         svn_diff_action_delete,
-                         entry->revision,
-                         0,     /* non-existent revision of file?  :-) */
-                         dir_baton->edit_baton->diff_cmd_baton));
+      SVN_ERR (dir_baton->edit_baton->diff_callbacks->file_deleted
+               (path->data, 
+                pristine_copy->data, 
+                empty_file->data,
+                dir_baton->edit_baton->diff_cmd_baton));
 
       /* Replace will fallthrough! */
       if (schedule == svn_wc_schedule_delete)
@@ -298,12 +296,11 @@
     case svn_wc_schedule_add:
       empty_file = svn_wc__empty_file_path (path, dir_baton->pool);
 
-      SVN_ERR (diff_cmd (empty_file->data, path->data,
-                         path->data, path->data,
-                         svn_diff_action_add,
-                         0,     /* non-existent revision of file */
-                         entry->revision,
-                         dir_baton->edit_baton->diff_cmd_baton));
+      SVN_ERR (dir_baton->edit_baton->diff_callbacks->file_added
+               (path->data,
+                empty_file->data,
+                path->data,
+                dir_baton->edit_baton->diff_cmd_baton));
       break;
 
     default:
@@ -323,13 +320,14 @@
              modularity is liveable. */
           SVN_ERR (svn_wc_translated_file (&translated, path,
                                            dir_baton->pool));
-
-          err = diff_cmd (pristine_copy->data, translated->data,
-                          path->data, path->data,
-                          svn_diff_action_modify,
-                          entry->revision,
-                          entry->revision,
-                          dir_baton->edit_baton->diff_cmd_baton);
+          
+          err = dir_baton->edit_baton->diff_callbacks->file_changed
+            (path->data,
+             pristine_copy->data, 
+             translated->data,
+             entry->revision,
+             entry->revision,
+             dir_baton->edit_baton->diff_cmd_baton);
           
           if (translated != path)
             SVN_ERR (svn_io_remove_file (translated->data, dir_baton->pool));
@@ -497,14 +495,10 @@
       /* A delete is required to change working-copy into requested
          revision, so diff should show this as and add. Thus compare the
          empty file against the current working copy. */
-      SVN_ERR (pb->edit_baton->diff_cmd
-               ((svn_wc__empty_file_path (path, pool))->data,
-                path->data,
+      SVN_ERR (pb->edit_baton->diff_callbacks->file_added
+               (path->data,
+                (svn_wc__empty_file_path (path, pool))->data,
                 path->data,
-                path->data,
-                svn_diff_action_add,
-                0,              /* non-existent revision */
-                entry->revision,
                 pb->edit_baton->diff_cmd_baton));
       break;
 
@@ -740,7 +734,6 @@
 close_file (void *file_baton)
 {
   struct file_baton *b = file_baton;
-  svn_diff_cmd_t diff_cmd = b->edit_baton->diff_cmd;
   svn_wc_entry_t *entry;
 
   /* The path to the temporary copy of the pristine repository version. */
@@ -753,14 +746,11 @@
       /* Add is required to change working-copy into requested revision, so
          diff should show this as and delete. Thus compare the current
          working copy against the empty file. */
-      SVN_ERR (diff_cmd (temp_file_path->data,
-                         (svn_wc__empty_file_path (b->wc_path, b->pool))->data,
-                         b->path->data,
-                         b->path->data,
-                         svn_diff_action_delete,
-                         0,     /* non-existent revision */
-                         entry ? entry->revision : SVN_INVALID_REVNUM,
-                         b->edit_baton->diff_cmd_baton));
+      SVN_ERR (b->edit_baton->diff_callbacks->file_deleted
+               (b->path->data,
+                temp_file_path->data,
+                (svn_wc__empty_file_path (b->wc_path, b->pool))->data,
+                b->edit_baton->diff_cmd_baton));
     }
   else
     {
@@ -770,13 +760,14 @@
       svn_stringbuf_t *translated;
       
       SVN_ERR (svn_wc_translated_file (&translated, b->path, b->pool));
-      
-      err1 = diff_cmd (temp_file_path->data, translated->data, 
-                       b->path->data, b->path->data,
-                       svn_diff_action_modify,
-                       0,       /* non-existent revision */
-                       entry ? entry->revision : SVN_INVALID_REVNUM,
-                       b->edit_baton->diff_cmd_baton);
+
+      err1 = b->edit_baton->diff_callbacks->file_changed
+        (b->path->data,
+         temp_file_path->data,
+         translated->data,
+         0,       /* non-existent revision */
+         entry ? entry->revision : SVN_INVALID_REVNUM,
+         b->edit_baton->diff_cmd_baton);
       
       if (translated != b->path)
         err2 = svn_io_remove_file (translated->data, b->pool);
@@ -828,7 +819,7 @@
 svn_error_t *
 svn_wc_get_diff_editor (svn_stringbuf_t *anchor,
                         svn_stringbuf_t *target,
-                        svn_diff_cmd_t diff_cmd,
+                        svn_diff_callbacks_t *diff_callbacks,
                         void *diff_cmd_baton,
                         svn_boolean_t recurse,
                         const svn_delta_edit_fns_t **editor,
@@ -838,8 +829,8 @@
   struct edit_baton *eb;
   svn_delta_edit_fns_t *tree_editor;
 
-  eb = make_editor_baton (anchor, target, diff_cmd, diff_cmd_baton, recurse,
-                          pool);
+  eb = make_editor_baton (anchor, target, diff_callbacks, diff_cmd_baton,
+                          recurse, pool);
   tree_editor = svn_delta_old_default_editor (eb->pool);
 
   tree_editor->set_target_revision = set_target_revision;
@@ -864,7 +855,7 @@
 svn_error_t *
 svn_wc_diff (svn_stringbuf_t *anchor,
              svn_stringbuf_t *target,
-             svn_diff_cmd_t diff_cmd,
+             svn_diff_callbacks_t *diff_callbacks,
              void *diff_cmd_baton,
              svn_boolean_t recurse,
              apr_pool_t *pool)
@@ -874,8 +865,8 @@
   svn_wc_entry_t *entry;
   svn_stringbuf_t *target_path;
 
-  eb = make_editor_baton (anchor, target, diff_cmd, diff_cmd_baton, recurse,
-                          pool);
+  eb = make_editor_baton (anchor, target, diff_callbacks, diff_cmd_baton,
+                          recurse, pool);
 
   target_path = svn_stringbuf_dup (anchor, eb->pool);
   if (target)

Modified: trunk/subversion/libsvn_client/diff.c
==============================================================================
--- trunk/subversion/libsvn_client/diff.c	(original)
+++ trunk/subversion/libsvn_client/diff.c	Fri Mar 29 15:35:02 2002
@@ -37,6 +37,12 @@
 #include "client.h"
 #include <assert.h>
 
+
+/*-----------------------------------------------------------------*/
+
+/*** Callbacks for 'svn diff', invoked by the repos-diff editor. ***/
+
+
 struct diff_cmd_baton {
   const apr_array_header_t *options;
   apr_pool_t *pool;
@@ -44,29 +50,25 @@
   apr_file_t *errfile;
 };
 
-/* This is an svn_diff_cmd_t callback, used by 'svn diff' */
+
+/* The main workhorse, which invokes an external 'diff' program on the
+   two temporary files.   The path is the "true" label to use in the
+   diff output, and the revnums are ignored. */
 static svn_error_t *
-diff_cmd (const char *path1,
-          const char *path2,
-          const char *path3,
-          const char *label,
-          enum svn_diff_action_t action,
-          svn_revnum_t path1_rev,
-          svn_revnum_t path2_rev,
-          void *baton)
+diff_file_changed (const char *path,
+                   const char *tmpfile1,
+                   const char *tmpfile2,
+                   svn_revnum_t rev1,
+                   svn_revnum_t rev2,
+                   void *diff_baton)
 {
-  struct diff_cmd_baton *diff_cmd_baton = baton;
+  struct diff_cmd_baton *diff_cmd_baton = diff_baton;
   const char **args = NULL;
   int nargs, exitcode;
   apr_file_t *outfile = diff_cmd_baton->outfile;
   apr_file_t *errfile = diff_cmd_baton->errfile;
   apr_pool_t *subpool = svn_pool_create (diff_cmd_baton->pool);
-
-  /* ### In the case of adds or deletes, the diff editor is already
-     guaranteeing that either PATH1 or PATH2 is an empty file.
-     However, perhaps someday this callback might want to look at
-     ACTION and print something more informative:  "file was deleted"
-     or somesuch, instead of printing all '-' or '+' signs.  Dunno.  */
+  const char *label = path;
 
   /* Execute local diff command on these two paths, print to stdout. */
   nargs = diff_cmd_baton->options->nelts;
@@ -83,12 +85,12 @@
     }
 
   /* Print out the diff header. */
-  apr_file_printf (outfile, "Index: %s\n", label ? label : path1);
+  apr_file_printf (outfile, "Index: %s\n", label ? label : tmpfile1);
   apr_file_printf (outfile, 
      "===================================================================\n");
 
-  SVN_ERR (svn_io_run_diff (".", args, nargs, label, 
-                            path1, path2, 
+  SVN_ERR (svn_io_run_diff (".", args, nargs, path, 
+                            tmpfile1, tmpfile2, 
                             &exitcode, outfile, errfile, subpool));
 
   /* ### todo: Handle exit code == 2 (i.e. errors with diff) here */
@@ -103,6 +105,76 @@
   return SVN_NO_ERROR;
 }
 
+/* The because the repos-diff editor passes at least one empty file to
+   each of these next two functions, they can be dumb wrappers around
+   the main workhorse routine. */
+static svn_error_t *
+diff_file_added (const char *path,
+                 const char *tmpfile1,
+                 const char *tmpfile2,
+                 void *diff_baton)
+{
+  return diff_file_changed (path, tmpfile1, tmpfile2, 
+                            SVN_INVALID_REVNUM, SVN_INVALID_REVNUM,
+                            diff_baton);
+}
+
+static svn_error_t *
+diff_file_deleted (const char *path,
+                   const char *tmpfile1,
+                   const char *tmpfile2,
+                   void *diff_baton)
+{
+  return diff_file_changed (path, tmpfile1, tmpfile2, 
+                            SVN_INVALID_REVNUM, SVN_INVALID_REVNUM,
+                            diff_baton);
+}
+
+/* For now, let's have 'svn diff' send feedback to the top-level
+   application, so that something reasonable about directories and
+   propsets gets printed to stdout. */
+static svn_error_t *
+diff_dir_added (const char *path,
+                void *diff_baton)
+{
+  /* ### todo:  send feedback to app */
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+diff_dir_deleted (const char *path,
+                  void *diff_baton)
+{
+  /* ### todo:  send feedback to app */
+  return SVN_NO_ERROR;
+}
+  
+static svn_error_t *
+diff_prop_changed (const char *path,
+                   const char *name,
+                   const svn_string_t *value,
+                   void *diff_baton)
+{
+  /* ### todo:  send feedback to app */
+  return SVN_NO_ERROR;
+}
+
+/* The main callback table for 'svn diff'.  */
+static svn_diff_callbacks_t 
+diff_callbacks =
+  {
+    diff_file_changed,
+    diff_file_added,
+    diff_file_deleted,
+    diff_dir_added,
+    diff_dir_deleted,
+    diff_prop_changed
+  };
+
+
+/*-----------------------------------------------------------------*/
+
+/*** Callbacks for 'svn merge', invoked by the repos-diff editor. ***/
 
 
 struct merge_cmd_baton {
@@ -110,16 +182,13 @@
 };
 
 
-/* This is an svn_diff_cmd_t callback, used by 'svn merge' */
 static svn_error_t *
-merge_cmd (const char *older,
-           const char *yours,
-           const char *mine,
-           const char *label,
-           enum svn_diff_action_t action,
-           svn_revnum_t older_rev,
-           svn_revnum_t yours_rev,
-           void *baton)
+merge_file_changed (const char *mine,
+                    const char *older,
+                    const char *yours,
+                    svn_revnum_t older_rev,
+                    svn_revnum_t yours_rev,
+                    void *baton)
 {
   struct merge_cmd_baton *merge_b = baton;
   apr_pool_t *subpool = svn_pool_create (merge_b->pool);
@@ -133,64 +202,122 @@
      diff-editor-mechanisms are doing the hard work of getting the
      fulltexts! */
 
-  /* ### Remove the printf stuff below once we have the update
-     trace-editor composed with the diff editor.  But we need to
-     convert the diff editor to the "new" interface first, before we
-     can do the composition.  */
-
-  /* ### <REMOVE ME> 
-  const char *act = "NONE";
-  switch (action)
-    {
-    case svn_diff_action_delete:
-      act = "delete";
-      break;
-    case svn_diff_action_add:
-      act = "add";
-      break;
-    case svn_diff_action_modify:
-      act = "modify";
-      break;
-    }
-  printf ("------------------------\n");
-  printf ("Hello, world!\n");
-  printf ("Action is: %s\n", act);
-  printf ("Older = %s, revision %d\n", older, (int) older_rev);
-  printf ("Yours = %s, revision %d\n", yours, (int) yours_rev);
-  printf ("Mine  = %s\n", mine);
-  ### </REMOVE ME> */
+  err = svn_wc_merge (older, yours, mine,
+                      left_label, right_label, target_label,
+                      subpool);
+  if (err && (err->apr_err != SVN_ERR_WC_CONFLICT))
+    return err;  
 
-  switch (action)
-    {
-      /* ### should all this stuff be done -loggily- like the
-         update-editor does things??  */
+  svn_pool_destroy (subpool);
+  return SVN_NO_ERROR;
+}
 
-    case svn_diff_action_modify: /* patch the file */
-      err = svn_wc_merge (older, yours, mine,
-                         left_label, right_label, target_label,
-                         subpool);
-      if (err && (err->apr_err != SVN_ERR_WC_CONFLICT))
-        return err;  
-      break;
-      
-    case svn_diff_action_add:
-      SVN_ERR (svn_io_copy_file (yours, mine, TRUE, subpool));
-      SVN_ERR (svn_client_add (svn_stringbuf_create (mine, subpool), 
-                               FALSE, NULL, NULL, subpool));
-      break;
-      
-    case svn_diff_action_delete: /*  */
-      SVN_ERR (svn_client_delete (NULL, 
-                                  svn_stringbuf_create (mine, subpool),
-                                  FALSE, /* don't force */
-                                  NULL, NULL, NULL, NULL, subpool));
-      break;
-    }
+static svn_error_t *
+merge_file_added (const char *mine,
+                  const char *older,
+                  const char *yours,
+                  void *baton)
+{
+  struct merge_cmd_baton *merge_b = baton;
+  apr_pool_t *subpool = svn_pool_create (merge_b->pool);
+
+  /* ### if file already exists, this should call svn_wc_merge. */
   
+  SVN_ERR (svn_io_copy_file (yours, mine, TRUE, subpool));
+  SVN_ERR (svn_client_add (svn_stringbuf_create (mine, subpool), 
+                           FALSE, NULL, NULL, subpool));
+
   svn_pool_destroy (subpool);
   return SVN_NO_ERROR;
 }
 
+static svn_error_t *
+merge_file_deleted (const char *mine,
+                    const char *older,
+                    const char *yours,
+                    void *baton)
+{
+  struct merge_cmd_baton *merge_b = baton;
+  apr_pool_t *subpool = svn_pool_create (merge_b->pool);
+
+  /* ### if file is already non-existent, this should be a no-op. */
+
+  SVN_ERR (svn_client_delete (NULL, 
+                              svn_stringbuf_create (mine, subpool),
+                              FALSE, /* don't force */
+                              NULL, NULL, NULL, NULL, subpool));
+  
+  svn_pool_destroy (subpool);
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+merge_dir_added (const char *path,
+                 void *baton)
+{
+  struct merge_cmd_baton *merge_b = baton;
+  apr_pool_t *subpool = svn_pool_create (merge_b->pool);
+  svn_stringbuf_t *path_s = svn_stringbuf_create (path, subpool);
+
+  /* ### if directory already exists, this should be a no-op */
+
+  SVN_ERR (svn_client_mkdir (NULL, path_s, NULL, NULL, NULL, NULL, subpool));
+  SVN_ERR (svn_client_add (path_s, FALSE, NULL, NULL, subpool));
+  
+  svn_pool_destroy (subpool);
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+merge_dir_deleted (const char *path,
+                   void *baton)
+{
+  struct merge_cmd_baton *merge_b = baton;
+  apr_pool_t *subpool = svn_pool_create (merge_b->pool);
+
+  /* ### if directory is already non-existent, this should be a no-op */
+
+  SVN_ERR (svn_client_delete (NULL, 
+                              svn_stringbuf_create (path, subpool),
+                              FALSE, /* don't force */
+                              NULL, NULL, NULL, NULL, subpool));
+  
+  svn_pool_destroy (subpool);
+  return SVN_NO_ERROR;
+}
+  
+static svn_error_t *
+merge_prop_changed (const char *path,
+                    const char *name,
+                    const svn_string_t *value,
+                    void *baton)
+{
+  struct merge_cmd_baton *merge_b = baton;
+  apr_pool_t *subpool = svn_pool_create (merge_b->pool);
+
+  SVN_ERR (svn_client_propset (name, value, path, FALSE, subpool));
+  
+  svn_pool_destroy (subpool);
+  return SVN_NO_ERROR;
+  return SVN_NO_ERROR;
+}
+
+/* The main callback table for 'svn merge'.  */
+static svn_diff_callbacks_t 
+merge_callbacks =
+  {
+    merge_file_changed,
+    merge_file_added,
+    merge_file_deleted,
+    merge_dir_added,
+    merge_dir_deleted,
+    merge_prop_changed
+  };
+
+
+/*-----------------------------------------------------------------------*/
+
+/** The shared logic behind 'svn diff' and 'svn merge'.  */
 
 
 /* Hi!  I'm a soon-to-be-out-of-date comment regarding a
@@ -224,8 +351,8 @@
                svn_stringbuf_t *path2,
                const svn_client_revision_t *revision2,
                svn_boolean_t recurse,
-               svn_diff_cmd_t cmd,
-               void *cmd_baton,
+               svn_diff_callbacks_t *callbacks,
+               void *callback_baton,
                apr_pool_t *pool)
 {
   svn_revnum_t start_revnum, end_revnum;
@@ -275,7 +402,8 @@
           || (revision1->kind == svn_client_revision_base))
       && (revision2->kind == svn_client_revision_working))
     {
-      return svn_wc_diff (anchor, target, cmd, cmd_baton, recurse, pool);
+      return svn_wc_diff (anchor, target, callbacks, callback_baton,
+                          recurse, pool);
     }
 
   /* Else we must contact the repository. */
@@ -309,7 +437,7 @@
     {
       /* The working copy is involved in this case. */
       SVN_ERR (svn_wc_get_diff_editor (anchor, target,
-                                       cmd, cmd_baton,
+                                       callbacks, callback_baton,
                                        recurse,
                                        &diff_editor, &diff_edit_baton,
                                        pool));
@@ -354,8 +482,8 @@
 
       /* Get the true diff editor. */
       SVN_ERR (svn_client__get_diff_editor (target,
-                                            cmd,
-                                            cmd_baton,
+                                            callbacks,
+                                            callback_baton,
                                             recurse,
                                             ra_lib, session2,
                                             start_revnum,
@@ -399,9 +527,9 @@
   return SVN_NO_ERROR;
 }
 
-
+/*----------------------------------------------------------------------- */
 
-/*** Public Interface. ***/
+/*** Public Interfaces. ***/
 
 /* Display context diffs between two PATH/REVISION pairs.  Each of
    these input will be one of the following:
@@ -471,7 +599,7 @@
                         path2,
                         revision2,
                         recurse,
-                        diff_cmd,
+                        &diff_callbacks,
                         &diff_cmd_baton,
                         pool);
 }
@@ -501,7 +629,7 @@
                         path2,
                         revision2,
                         recurse,
-                        merge_cmd,
+                        &merge_callbacks,
                         &merge_cmd_baton,
                         pool);
 }

Modified: trunk/subversion/libsvn_client/repos_diff.c
==============================================================================
--- trunk/subversion/libsvn_client/repos_diff.c	(original)
+++ trunk/subversion/libsvn_client/repos_diff.c	Fri Mar 29 15:35:02 2002
@@ -43,7 +43,7 @@
 
   /* The callback and calback argument that implement the file comparison
      function */
-  svn_diff_cmd_t diff_cmd;
+  svn_diff_callbacks_t *diff_callbacks;
   void *diff_cmd_baton;
 
   /* Flags whether to diff recursively or not. If set the diff is
@@ -300,28 +300,6 @@
   return SVN_NO_ERROR;
 }
 
-/* Runs the diff callback to display the difference for a single file. At
- * this stage both versions of the file exist as temporary files.
- * ACTION describes the action to be passed to the diff-callback.
- */
-static svn_error_t *
-run_diff_cmd (struct file_baton *b,
-              enum svn_diff_action_t action)
-{
-  svn_diff_cmd_t diff_cmd = b->edit_baton->diff_cmd;
-
-  SVN_ERR (diff_cmd (b->path_start_revision->data, /* rev1 ("older") */
-                     b->path_end_revision->data,   /* rev2 ("yours") */
-                     b->path,                     /* possible "mine" */
-                     b->path,      /* correct label to show in diffs */
-                     action,
-                     b->edit_baton->revision,                /* rev1 */
-                     b->edit_baton->target_revision,         /* rev2 */
-                     b->edit_baton->diff_cmd_baton));
-
-  return SVN_NO_ERROR;
-}
-
 /* An svn_delta_edit_fns_t editor function. The root of the comparison
  * hierarchy
  */
@@ -369,6 +347,9 @@
   svn_node_kind_t kind;
 
   /* We need to know if this is a directory or a file */
+  /* ### over ra_dav, this breaks if PATH doesn't exist in HEAD; see
+       issue #581.  Obviously, this kind of misses the point of
+       passing in a revision.  :-)  */
   SVN_ERR (pb->edit_baton->ra_lib->check_path (&kind,
                                                pb->edit_baton->ra_session,
                                                path,
@@ -385,13 +366,21 @@
                                                 pool);
         SVN_ERR (get_file_from_ra (b));
         SVN_ERR (get_empty_file(b->edit_baton, &b->path_end_revision));
-        SVN_ERR (run_diff_cmd (b, svn_diff_action_delete));
+        
+        SVN_ERR (pb->edit_baton->diff_callbacks->file_deleted 
+                 (b->path,
+                  b->path_start_revision->data,
+                  b->path_end_revision->data,
+                  b->edit_baton->diff_cmd_baton));
+        break;
       }
-      break;
     case svn_node_dir:
-      /* ### TODO: need to get the directory entries to show
-         deleted files */
-      break;
+      {
+        SVN_ERR (pb->edit_baton->diff_callbacks->dir_deleted 
+                 (pb->path,
+                  pb->edit_baton->diff_cmd_baton));
+        break;
+      }
     default:
       break;
     }
@@ -417,6 +406,10 @@
   b = make_dir_baton (path, pb, TRUE, pool);
   *child_baton = b;
 
+  SVN_ERR (pb->edit_baton->diff_callbacks->dir_added 
+           (path,
+            pb->edit_baton->diff_cmd_baton));
+
   return SVN_NO_ERROR;
 }
 
@@ -561,6 +554,7 @@
 close_file (void *file_baton)
 {
   struct file_baton *b = file_baton;
+  struct edit_baton *eb = b->edit_baton;
 
   /* Maybe only the properties changed, not the text content.  In that
      case, no difference is reported, and no need to run diff.
@@ -570,9 +564,19 @@
   if (b->path_end_revision)
     {
       if (b->added)
-        SVN_ERR (run_diff_cmd (b, svn_diff_action_add));
+        SVN_ERR (eb->diff_callbacks->file_added
+                 (b->path,
+                  b->path_start_revision->data,
+                  b->path_end_revision->data,
+                  b->edit_baton->diff_cmd_baton));
       else
-        SVN_ERR (run_diff_cmd (b, svn_diff_action_modify));
+        SVN_ERR (eb->diff_callbacks->file_changed
+                 (b->path,
+                  b->path_start_revision->data,
+                  b->path_end_revision->data,
+                  b->edit_baton->revision,
+                  b->edit_baton->target_revision,
+                  b->edit_baton->diff_cmd_baton));
     }
 
   return SVN_NO_ERROR;
@@ -581,6 +585,43 @@
 /* An svn_delta_edit_fns_t editor function.
  */
 static svn_error_t *
+change_file_prop (void *file_baton,
+                  const char *name,
+                  const svn_string_t *value,
+                  apr_pool_t *pool)
+{
+  struct file_baton *b = file_baton;
+  struct edit_baton *eb = b->edit_baton;
+
+  SVN_ERR (eb->diff_callbacks->prop_changed
+           (b->path, name, value,
+            eb->diff_cmd_baton));
+  
+  return SVN_NO_ERROR;
+}
+
+/* An svn_delta_edit_fns_t editor function.
+ */
+static svn_error_t *
+change_dir_prop (void *dir_baton,
+                 const char *name,
+                 const svn_string_t *value,
+                 apr_pool_t *pool)
+{
+  struct dir_baton *db = dir_baton;
+  struct edit_baton *eb = db->edit_baton;
+
+  SVN_ERR (eb->diff_callbacks->prop_changed
+           (db->path, name, value,
+            eb->diff_cmd_baton));
+  
+  return SVN_NO_ERROR;
+}
+
+
+/* An svn_delta_edit_fns_t editor function.
+ */
+static svn_error_t *
 close_edit (void *edit_baton)
 {
   struct edit_baton *eb = edit_baton;
@@ -594,7 +635,7 @@
  */
 svn_error_t *
 svn_client__get_diff_editor (svn_stringbuf_t *target,
-                             svn_diff_cmd_t diff_cmd,
+                             svn_diff_callbacks_t *diff_callbacks,
                              void *diff_cmd_baton,
                              svn_boolean_t recurse,
                              svn_ra_plugin_t *ra_lib,
@@ -609,7 +650,7 @@
   struct edit_baton *eb = apr_palloc (subpool, sizeof (*eb));
 
   eb->target = target;
-  eb->diff_cmd = diff_cmd;
+  eb->diff_callbacks = diff_callbacks;
   eb->diff_cmd_baton = diff_cmd_baton;
   eb->recurse = recurse;
   eb->ra_lib = ra_lib;
@@ -627,6 +668,8 @@
   tree_editor->open_file = open_file;
   tree_editor->apply_textdelta = apply_textdelta;
   tree_editor->close_file = close_file;
+  tree_editor->change_file_prop = change_file_prop;
+  tree_editor->change_dir_prop = change_dir_prop;
   tree_editor->close_edit = close_edit;
 
   *edit_baton = eb;

Modified: trunk/subversion/libsvn_client/client.h
==============================================================================
--- trunk/subversion/libsvn_client/client.h	(original)
+++ trunk/subversion/libsvn_client/client.h	Fri Mar 29 15:35:02 2002
@@ -199,7 +199,7 @@
  */
 svn_error_t *
 svn_client__get_diff_editor (svn_stringbuf_t *target,
-                             svn_diff_cmd_t diff_cmd,
+                             svn_diff_callbacks_t *diff_cmd,
                              void *diff_cmd_baton,
                              svn_boolean_t recurse,
                              svn_ra_plugin_t *ra_lib,


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic