Index: subversion/include/svn_wc.h =================================================================== --- subversion/include/svn_wc.h (revision 16107) +++ subversion/include/svn_wc.h (working copy) @@ -542,7 +542,10 @@ svn_wc_notify_failed_lock, /** Failed to unlock a path. @since New in 1.2. */ - svn_wc_notify_failed_unlock + svn_wc_notify_failed_unlock, + + /** Got a replace in an update. @since New in 1.3 */ + svn_wc_notify_update_replace } svn_wc_notify_action_t; Index: subversion/libsvn_wc/update_editor.c =================================================================== --- subversion/libsvn_wc/update_editor.c (revision 16107) +++ subversion/libsvn_wc/update_editor.c (working copy) @@ -50,6 +50,12 @@ #include "lock.h" #include "props.h" +#define ADD "add" +#define DEL "del" +#define NESS_DEBUG 1 + +const char * hash_get_set (apr_hash_t * ht, const void * key, + const char * add_or_del); /*** batons ***/ @@ -147,6 +153,9 @@ /* The pool in which this baton itself is allocated. */ apr_pool_t *pool; + + /* Hash table to check if a target is being replaced */ + apr_hash_t *deleted_targets; }; @@ -341,6 +350,12 @@ d->bump_info = bdi; d->log_number = 0; + /* initalize the hash table for deleted directory targets */ +#ifdef NESS_DEBUG + fprintf(stderr, "Creating hash in pool in make_dir_baton()\n"); +#endif + d->deleted_targets = apr_hash_make (d->pool); + apr_pool_cleanup_register (d->pool, d, cleanup_dir_baton, cleanup_dir_baton_child); @@ -792,12 +807,15 @@ { struct edit_baton *eb = edit_baton; struct dir_baton *d; - + /* Note that something interesting is actually happening in this edit run. */ eb->root_opened = TRUE; *dir_baton = d = make_dir_baton (NULL, eb, NULL, FALSE, pool); +#ifdef NESS_DEBUG + fprintf(stderr, " open_root() started\n"); +#endif if (! *eb->target) { /* For an update with a NULL target, this is equivalent to open_dir(): */ @@ -995,18 +1013,6 @@ logfile_path, parent_path, pool)); *log_number = 0; - /* The passed-in `path' is relative to the anchor of the edit, so if - * the operation was invoked on something other than ".", then - * `path' will be wrong for purposes of notification. However, we - * can always count on the parent_path being the parent of base_name, - * so we just join them together to get a good notification path. - */ - if (eb->notify_func) - (*eb->notify_func) - (eb->notify_baton, - svn_wc_create_notify (svn_path_join (parent_path, base_name, pool), - svn_wc_notify_update_delete, pool), pool); - return SVN_NO_ERROR; } @@ -1018,6 +1024,26 @@ apr_pool_t *pool) { struct dir_baton *pb = parent_baton; + const char *exists = NULL; + /* Add the path to the deleted_targets hash table + They key and the value are both the path */ +#ifdef NESS_DEBUG + fprintf(stderr,"hash_get_set on '%s' in delete_entry()\n",path); +#endif + exists = hash_get_set (pb->deleted_targets, path, DEL); + + /* Does this path already exists and do we have notification? */ + if (exists && pb->edit_baton->notify_func) + { + (*pb->edit_baton->notify_func) + (pb->edit_baton->notify_baton, + svn_wc_create_notify (path, svn_wc_notify_update_replace, pool), pool); + /* Now we delete the hash entry since it is marked as replaced */ +#ifdef NESS_DEBUG + fprintf(stderr,"Removing key '%s' in delete_entry()\n",path); +#endif + apr_hash_set(pb->deleted_targets, path, APR_HASH_KEY_STRING, NULL); + } return do_entry_deletion (pb->edit_baton, pb->path, path, &pb->log_number, pool); } @@ -1117,7 +1143,7 @@ db->pool)); *child_baton = db; - + if (eb->notify_func) { svn_wc_notify_t *notify = svn_wc_create_notify (db->path, @@ -1150,6 +1176,9 @@ struct dir_baton *db = make_dir_baton (path, eb, pb, FALSE, pool); *child_baton = db; +#ifdef NESS_DEBUG + fprintf(stderr," open_directory() starting for '%s'\n", db->path); +#endif /* Mark directory as being at target_revision and URL, but incomplete. */ tmp_entry.revision = *(eb->target_revision); tmp_entry.url = db->new_URL; @@ -1216,7 +1245,58 @@ svn_wc_notify_state_t prop_state = svn_wc_notify_state_unknown; apr_array_header_t *entry_props, *wc_props, *regular_props; svn_wc_adm_access_t *adm_access; - + +#ifdef NESS_DEBUG + int i = 0; /* Lets count the for loop executions */ + fprintf(stderr," close_directory() starting for '%s'\n", db->path); +#endif + /* First thing is to print out deleted targets from the hash table */ + apr_hash_index_t *hi; + + for (hi = apr_hash_first(db->pool, db->deleted_targets); hi; hi = apr_hash_next(hi)) + { +#ifdef NESS_DEBUG + i++; +#endif + const void *vkey; + void *vval; + const char *key; + const svn_string_t *val; + + apr_hash_this(hi, &vkey, NULL, &vval); + key = vkey; + val = vval; +#ifdef NESS_DEBUG + fprintf(stderr, "[%d] hash key = '%s' was found with val = '%s'\n", i, key, (char *)val); +#endif + if ((char*)val == DEL && db->edit_baton->notify_func) + { + (*db->edit_baton->notify_func) + (db->edit_baton->notify_baton, + svn_wc_create_notify (key, + svn_wc_notify_update_delete, pool), pool); + } + } + + /* delete the entries */ + for (hi = apr_hash_first(db->pool, db->deleted_targets);hi;hi = apr_hash_next(hi)) + { + const void *vkey; + void *vval; + const char *key; + const svn_string_t *val; + + apr_hash_this(hi, &vkey, NULL, &vval); + key = vkey; + val = vval; + +#ifdef NESS_DEBUG + fprintf(stderr, " trying to remove key = '%s'\n", key); +#endif + /* We are done with this has entry, remove it */ + apr_hash_set (db->deleted_targets, key, APR_HASH_KEY_STRING, NULL); + } + SVN_ERR (svn_categorize_props (db->propchanges, &entry_props, &wc_props, ®ular_props, pool)); @@ -1378,7 +1458,6 @@ (*db->edit_baton->notify_func) (db->edit_baton->notify_baton, notify, pool); } - return SVN_NO_ERROR; } @@ -1554,6 +1633,7 @@ apr_pool_t *pool, void **file_baton) { + return add_or_open_file (name, parent_baton, copyfrom_path, copyfrom_revision, file_baton, TRUE, pool); } @@ -2424,10 +2504,30 @@ (lock_state != svn_wc_notify_lock_state_unchanged)) && eb->notify_func) { - svn_wc_notify_t *notify - = svn_wc_create_notify (fb->path, - fb->added ? svn_wc_notify_update_add - : svn_wc_notify_update_update, pool); + svn_wc_notify_t *notify; +#ifdef NESS_DEBUG + fprintf(stderr, " hash_get_set on path '%s' in close_file()\n", fb->path); +#endif + if (hash_get_set (fb->dir_baton->deleted_targets, fb->path, ADD) == NULL) + { + notify + = svn_wc_create_notify (fb->path, + fb->added ? svn_wc_notify_update_add + : svn_wc_notify_update_update, pool); + } + else + { + notify + = svn_wc_create_notify (fb->path, + fb->added ? svn_wc_notify_update_replace + : svn_wc_notify_update_update, pool); + /* Remove the entry from the hash, so we don't print it as deleted */ +#ifdef NESS_DEBUG + fprintf(stderr, " removing hash '%s' since maked as R\n", fb->path); +#endif + apr_hash_set(fb->dir_baton->deleted_targets, fb->path, + APR_HASH_KEY_STRING, NULL); + } notify->kind = svn_node_file; notify->content_state = content_state; notify->prop_state = prop_state; @@ -2983,3 +3083,26 @@ return SVN_NO_ERROR; } + + +/* Local Hash function + + hash_get_set() attempts to get a key value if it exists. + If the key value does not exist the function sets it in the hash + table and returns NULL. */ + +const char * hash_get_set (apr_hash_t * ht, const void * key, + const char * add_or_del) + { + const void * val = NULL; + + val = apr_hash_get (ht, key, APR_HASH_KEY_STRING); + + if (val) + return (const char *) key; + else + { + apr_hash_set (ht, key, APR_HASH_KEY_STRING, add_or_del); + return NULL; + } + } Index: subversion/clients/cmdline/notify.c =================================================================== --- subversion/clients/cmdline/notify.c (revision 16107) +++ subversion/clients/cmdline/notify.c (working copy) @@ -90,6 +90,12 @@ goto print_error; break; + case svn_wc_notify_update_replace: + nb->received_some_change = TRUE; + if ((err = svn_cmdline_printf (pool, "R %s\n", path_local))) + goto print_error; + break; + case svn_wc_notify_restore: if ((err = svn_cmdline_printf (pool, _("Restored '%s'\n"), path_local)))