Index: subversion/include/svn_error_codes.h
===================================================================
--- subversion/include/svn_error_codes.h
+++ subversion/include/svn_error_codes.h	Thu Sep 12 19:29:06 2002
@@ -643,6 +643,10 @@
               SVN_ERR_MISC_CATEGORY_START + 12,
               "Error calling external program")
 
+  SVN_ERRDEF (SVN_ERR_CANCELED,
+              SVN_ERR_MISC_CATEGORY_START + 13,
+              "Operation was canceled")
+
   /* command-line client errors */
 
   SVN_ERRDEF (SVN_ERR_CL_ARG_PARSING_ERROR,
Index: subversion/include/svn_error.h
===================================================================
--- subversion/include/svn_error.h
+++ subversion/include/svn_error.h	Thu Sep 12 22:49:39 2002
@@ -117,7 +117,7 @@
 /* Clear ERROR's pool.  Note that this is likely the top-level error
    pool shared with any other errors currently extant, though usually
    only one error exists at a time, so this is not a problem. */
-void svn_error_clear_all (svn_error_t *error);
+svn_error_t *svn_error_clear_all (svn_error_t *error);
 
 
 /* Very basic default error handler: print out error stack, and quit
@@ -130,6 +130,30 @@
    which must be passed in DATA.  Allocates from a subpool of POOL. */
 void svn_handle_warning (apr_pool_t *pool, void *data, const char *fmt, ...);
 
+/* XXX i doubt these should go here.  maybe an svn_cancel.h? */
+
+/* the next three prototypes are an implementation detail...
+   these are not the functions you are looking for...
+   move along, move along... */
+
+/* has the operation currently in progress been canceled by the client app? */
+svn_boolean_t svn__async_canceled (void);
+
+/* generate an SVN_ERR_CANCEL error allocated from the previously registered 
+   cancelation pool */
+svn_error_t *svn__async_cancelation_error (void);
+
+/* are we currenlty cleaning up from a cancelation? */
+svn_boolean_t svn__async_cancelation_in_progress (void);
+
+/* register a pool to be used to allocate SVN_ERR_CANCEL errors. */
+void svn_async_register_cancelation_pool (apr_pool_t *pool);
+
+/* cancel the currently in progress action. */
+void svn_async_cancel (void);
+
+/* reset the global cancelation flags after a cancelation has occured. */
+void svn_async_reset (void);
 
 /* A statement macro for checking error return values.
    Evaluate EXPR.  If it yields an error, return that error from the
@@ -151,6 +175,8 @@
     svn_error_t *svn_err__temp = (expr);        \
     if (svn_err__temp)                          \
       return svn_err__temp;                     \
+    else if (svn__async_canceled ())            \
+      return svn__async_cancelation_error ();   \
   } while (0)
 
 
@@ -162,6 +188,8 @@
     svn_error_t *svn_err__temp = (expr);                    \
     if (svn_err__temp)                                      \
       return svn_error_quick_wrap(svn_err__temp, wrap_msg); \
+    else if (svn__async_canceled ())                        \
+      return svn__async_cancelation_error ();               \
   } while (0)
 
 
Index: subversion/libsvn_fs/tree.c
===================================================================
--- subversion/libsvn_fs/tree.c
+++ subversion/libsvn_fs/tree.c	Thu Sep 12 21:45:12 2002
@@ -501,7 +501,7 @@
                  said it was optional, then don't return an error;
                  just put a NULL node pointer in the path.  */
               
-              svn_error_clear_all (err);
+              SVN_ERR (svn_error_clear_all (err));
               
               if ((flags & open_path_last_optional)
                   && (! next || *next == '\0'))
@@ -2345,7 +2345,7 @@
           if (youngest_rev == youngish_rev)
             return err;
           else
-            svn_error_clear_all (err);
+            SVN_ERR (svn_error_clear_all (err));
         }
       else if (err)
         return err;
Index: subversion/libsvn_wc/log.c
===================================================================
--- subversion/libsvn_wc/log.c
+++ subversion/libsvn_wc/log.c	Thu Sep 12 21:48:00 2002
@@ -626,7 +626,7 @@
   /* It's possible that locally modified files were left behind during
      the removal.  That's okay;  just check for this special case. */
   if (err && (err->apr_err == SVN_ERR_WC_LEFT_LOCAL_MOD))
-    svn_error_clear_all (err);
+    SVN_ERR (svn_error_clear_all (err));
   else if (err)
     return err;
 
Index: subversion/libsvn_wc/adm_ops.c
===================================================================
--- subversion/libsvn_wc/adm_ops.c
+++ subversion/libsvn_wc/adm_ops.c	Thu Sep 12 21:47:00 2002
@@ -723,7 +723,7 @@
   err = svn_wc_entry (&orig_entry, path, TRUE, pool);
   if (err)
     {
-      svn_error_clear_all (err);
+      SVN_ERR (svn_error_clear_all (err));
       orig_entry = NULL;
     }
 
@@ -1550,7 +1550,7 @@
 
               if (err && (err->apr_err == SVN_ERR_WC_LEFT_LOCAL_MOD))
                 {
-                  svn_error_clear_all (err);
+                  SVN_ERR (svn_error_clear_all (err));
                   left_something = TRUE;
                 }
               else if (err)
@@ -1570,7 +1570,7 @@
                                                          destroy_wf, subpool);
               if (err && (err->apr_err == SVN_ERR_WC_LEFT_LOCAL_MOD))
                 {
-                  svn_error_clear_all (err);
+                  SVN_ERR (svn_error_clear_all (err));
                   left_something = TRUE;
                 }
               else if (err)
Index: subversion/libsvn_wc/status.c
===================================================================
--- subversion/libsvn_wc/status.c
+++ subversion/libsvn_wc/status.c	Thu Sep 12 21:48:38 2002
@@ -554,7 +554,7 @@
                           if (svn_err->apr_err != SVN_ERR_WC_NOT_DIRECTORY)
                             return svn_err;
                           
-                          svn_error_clear_all (svn_err);
+                          SVN_ERR (svn_error_clear_all (svn_err));
                           fullpath_entry = entry;
                         }
                     }
Index: subversion/libsvn_wc/adm_files.c
===================================================================
--- subversion/libsvn_wc/adm_files.c
+++ subversion/libsvn_wc/adm_files.c	Thu Sep 12 21:46:27 2002
@@ -1020,7 +1020,7 @@
 
     if (err)
       {
-        svn_error_clear_all (err);
+        SVN_ERR (svn_error_clear_all (err));
         wc_exists = FALSE;
       }
     else if (wc_format > SVN_WC__VERSION)
Index: subversion/libsvn_wc/update_editor.c
===================================================================
--- subversion/libsvn_wc/update_editor.c
+++ subversion/libsvn_wc/update_editor.c	Thu Sep 12 21:49:02 2002
@@ -1118,7 +1118,7 @@
         }
       else if (err)
         {
-          svn_error_clear_all (err);
+          SVN_ERR (svn_error_clear_all (err));
           hb->source = NULL;  /* make sure */
         }
     }
@@ -2132,7 +2132,7 @@
   if (err || (! p_entry))
     {
       if (err)
-        svn_error_clear_all (err);
+        SVN_ERR (svn_error_clear_all (err));
 
       return SVN_NO_ERROR;
     }
Index: subversion/libsvn_wc/lock.c
===================================================================
--- subversion/libsvn_wc/lock.c
+++ subversion/libsvn_wc/lock.c	Thu Sep 12 21:47:35 2002
@@ -86,7 +86,7 @@
         {
           if (APR_STATUS_IS_EEXIST(err->apr_err))
             {
-              svn_error_clear_all (err);
+              SVN_ERR (svn_error_clear_all (err));
               if (wait_for <= 0)
                 break;
               wait_for--;
@@ -135,7 +135,7 @@
   if (err)
     {
       apr_status_t apr_err = err->apr_err;
-      svn_error_clear_all (err);
+      SVN_ERR (svn_error_clear_all (err));
       return apr_err;
     }
   else
@@ -198,7 +198,7 @@
   if (err)
     {
       if (err->apr_err == SVN_ERR_WC_LOCKED)
-        svn_error_clear_all (err);  /* Steal existing lock */
+        SVN_ERR (svn_error_clear_all (err));  /* Steal existing lock */
       else
         return err;
     }
Index: subversion/libsvn_wc/questions.c
===================================================================
--- subversion/libsvn_wc/questions.c
+++ subversion/libsvn_wc/questions.c	Thu Sep 12 21:48:20 2002
@@ -74,7 +74,7 @@
              wrong at all, then for our purposes this is not a working
              copy, so return 0. */
           if (err)
-            svn_error_clear_all (err);
+            SVN_ERR (svn_error_clear_all (err));
 
           *wc_format = 0;
         }
Index: subversion/libsvn_subr/svn_error.c
===================================================================
--- subversion/libsvn_subr/svn_error.c
+++ subversion/libsvn_subr/svn_error.c	Thu Sep 12 23:04:45 2002
@@ -305,10 +305,16 @@
 }
 
 
-void
+svn_error_t *
 svn_error_clear_all (svn_error_t *err)
 {
-  svn_pool_clear (err->pool);
+  if (svn__async_cancelation_in_progress ())
+    return svn__async_cancelation_error ();
+  else
+    {
+      svn_pool_clear (err->pool);
+      return SVN_NO_ERROR;
+    }
 }
 
 
Index: subversion/libsvn_subr/cancel.c
===================================================================
--- subversion/libsvn_subr/cancel.c
+++ subversion/libsvn_subr/cancel.c	Thu Sep 12 22:36:31 2002
@@ -0,0 +1,80 @@
+/*
+ * cancel.c:  support for asyncronous cancelation of subversion functions
+ *
+ * ====================================================================
+ * Copyright (c) 2000-2002 CollabNet.  All rights reserved.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution.  The terms
+ * are also available at http://subversion.tigris.org/license-1.html.
+ * If newer versions of this license are posted there, you may use a
+ * newer version instead, at your option.
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals.  For exact contribution history, see the revision
+ * history and logs, available at http://subversion.tigris.org/.
+ * ====================================================================
+ */
+
+
+
+#include "svn_error.h"
+#include "svn_pools.h"
+
+
+/*** Code. ***/
+
+static volatile sig_atomic_t canceled = FALSE;
+
+static svn_boolean_t cancelation_in_progress = FALSE;
+
+static apr_pool_t *cancelation_pool;
+
+svn_boolean_t
+svn__async_canceled(void)
+{
+  return canceled;
+}
+
+svn_error_t *
+svn__async_cancelation_error(void)
+{
+  canceled = FALSE;
+
+  cancelation_in_progress = TRUE;
+
+  return svn_error_create (SVN_ERR_CANCELED, 0, NULL, cancelation_pool, NULL);
+}
+
+svn_boolean_t
+svn__async_cancelation_in_progress (void)
+{
+  return cancelation_in_progress;
+}
+
+void
+svn_async_register_cancelation_pool (apr_pool_t *pool)
+{
+  cancelation_pool = pool;
+}
+
+void
+svn_async_cancel(void)
+{
+  if (! cancelation_in_progress)
+    canceled = TRUE;
+}
+
+void
+svn_async_reset(void)
+{
+  canceled = FALSE;
+
+  cancelation_in_progress = FALSE;
+}
+
+
+/* 
+ * local variables:
+ * eval: (load-file "../../tools/dev/svn-dev.el")
+ * end: */
Index: subversion/libsvn_client/commit_util.c
===================================================================
--- subversion/libsvn_client/commit_util.c
+++ subversion/libsvn_client/commit_util.c	Thu Sep 12 21:44:48 2002
@@ -148,7 +148,7 @@
       err = svn_wc_entries_read (&entries, path, FALSE, subpool);
       if (err)
         {
-          svn_error_clear_all (err);
+          SVN_ERR (svn_error_clear_all (err));
           entries = NULL;
         }
 
Index: subversion/mod_dav_svn/repos.c
===================================================================
--- subversion/mod_dav_svn/repos.c
+++ subversion/mod_dav_svn/repos.c	Thu Sep 12 21:49:23 2002
@@ -1487,7 +1487,7 @@
                                 resource->pool);
   if (serr != NULL && serr->apr_err == SVN_ERR_FS_NOT_FOUND)
     {
-      svn_error_clear_all(serr);
+      SVN_ERR (svn_error_clear_all(serr));
       serr = svn_fs_make_file(resource->info->root.root,
                               resource->info->repos_path,
                               resource->pool);
Index: subversion/clients/cmdline/add-cmd.c
===================================================================
--- subversion/clients/cmdline/add-cmd.c
+++ subversion/clients/cmdline/add-cmd.c	Thu Sep 12 21:49:49 2002
@@ -71,7 +71,7 @@
           if (err->apr_err == SVN_ERR_ENTRY_EXISTS)
             {
               svn_handle_warning (err->pool, stderr, err->message);
-              svn_error_clear_all (err);
+              SVN_ERR (svn_error_clear_all (err));
             }
           else
             return err;
Index: subversion/clients/cmdline/resolve-cmd.c
===================================================================
--- subversion/clients/cmdline/resolve-cmd.c
+++ subversion/clients/cmdline/resolve-cmd.c	Thu Sep 12 21:50:08 2002
@@ -68,7 +68,7 @@
       if (err)
         {
           svn_handle_warning (err->pool, stderr, err->message);
-          svn_error_clear_all (err);
+          SVN_ERR (svn_error_clear_all (err));
         }
       
       svn_pool_clear (subpool);
Index: subversion/clients/cmdline/main.c
===================================================================
--- subversion/clients/cmdline/main.c
+++ subversion/clients/cmdline/main.c	Thu Sep 12 21:20:14 2002
@@ -873,6 +873,12 @@
 }
 
 
+static void
+cancel (int sig)
+{
+  svn_async_cancel();
+}
+
 
 /*** Main. ***/
 
@@ -913,6 +919,11 @@
 
   /* Create our top-level pool. */
   pool = svn_pool_create (NULL);
+
+  /* XXX where should this go? */
+  svn_async_register_cancelation_pool (pool);
+
+  signal(SIGINT, cancel);
 
   /* Begin processing arguments. */
   memset (&opt_state, 0, sizeof (opt_state));
Index: subversion/libsvn_repos/delta.c
===================================================================
--- subversion/libsvn_repos/delta.c
+++ subversion/libsvn_repos/delta.c	Thu Sep 12 21:46:06 2002
@@ -266,7 +266,7 @@
         {
           /* Caller thinks that target still exists, but it doesn't.
              So just delete the target and go home.  */
-          svn_error_clear_all (err);
+          SVN_ERR (svn_error_clear_all (err));
           SVN_ERR (delete (&c, root_baton, src_entry, pool));
           goto cleanup;
         }
@@ -282,7 +282,7 @@
         {
           /* The target has been deleted from our working copy. Add
              back a new one. */
-          svn_error_clear_all (err);
+          SVN_ERR (svn_error_clear_all (err));
           SVN_ERR (add_file_or_dir (&c, root_baton,
                                     tgt_parent_dir->data,
                                     tgt_entry->data,
Index: subversion/libsvn_ra_dav/commit.c
===================================================================
--- subversion/libsvn_ra_dav/commit.c
+++ subversion/libsvn_ra_dav/commit.c	Thu Sep 12 21:45:31 2002
@@ -972,7 +972,7 @@
         {
           /* ### TODO: This is what we get if the file doesn't exist
              but an explicit not-found error might be better */
-          svn_error_clear_all(err);
+          SVN_ERR (svn_error_clear_all(err));
         }
       else
         {
