You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2011/10/11 21:52:46 UTC

svn commit: r1182053 [6/30] - in /subversion/branches/svn_mutex: ./ build/ build/ac-macros/ build/generator/ build/generator/swig/ build/generator/templates/ contrib/client-side/ contrib/hook-scripts/enforcer/ contrib/server-side/ notes/ notes/merge-tr...

Modified: subversion/branches/svn_mutex/subversion/include/svn_repos.h
URL: http://svn.apache.org/viewvc/subversion/branches/svn_mutex/subversion/include/svn_repos.h?rev=1182053&r1=1182052&r2=1182053&view=diff
==============================================================================
--- subversion/branches/svn_mutex/subversion/include/svn_repos.h (original)
+++ subversion/branches/svn_mutex/subversion/include/svn_repos.h Tue Oct 11 19:52:34 2011
@@ -300,10 +300,10 @@ typedef struct svn_repos_notify_t
       #svn_repos_notify_pack_shard_end_revprop, the shard processed. */
   apr_int64_t shard;
 
-  /** For #svn_repos_notify_load_commited_rev, the revision committed. */
+  /** For #svn_repos_notify_load_node_done, the revision committed. */
   svn_revnum_t new_revision;
 
-  /** For #svn_repos_notify_load_commited_rev, the source revision, if
+  /** For #svn_repos_notify_load_node_done, the source revision, if
       different from @a new_revision, otherwise #SVN_INVALID_REVNUM.
       For #svn_repos_notify_load_txn_start, the source revision. */
   svn_revnum_t old_revision;
@@ -1625,11 +1625,12 @@ svn_repos_node_location_segments(svn_rep
  * If @a include_merged_revisions is set, log information for revisions
  * which have been merged to @a paths will also be returned, unless these
  * revisions are already part of @a start to @a end in @a repos's
- * filesystem, as limted by @a paths. In the latter case those revisions
+ * filesystem, as limited by @a paths. In the latter case those revisions
  * are skipped and @a receiver is not invoked.
  *
- * If @a revprops is NULL, retrieve all revprops; else, retrieve only the
- * revprops named in the array (i.e. retrieve none if the array is empty).
+ * If @a revprops is NULL, retrieve all revision properties; else, retrieve
+ * only the revision properties named by the (const char *) array elements
+ * (i.e. retrieve none if the array is empty).
  *
  * If any invocation of @a receiver returns error, return that error
  * immediately and without wrapping it.
@@ -1746,11 +1747,6 @@ svn_repos_get_logs(svn_repos_t *repos,
  * @a inherit indicates whether explicit, explicit or inherited, or
  * only inherited mergeinfo for @a paths is fetched.
  *
- * If the mergeinfo for any path is inherited and
- * @a validate_inherited_mergeinfo is TRUE, then the mergeinfo for
- * that path in @a *catalog will only contain merge source
- * path-revisions that actually exist in repository.
- *
  * If @a revision is #SVN_INVALID_REVNUM, it defaults to youngest.
  *
  * If @a include_descendants is TRUE, then additionally return the
@@ -1767,27 +1763,8 @@ svn_repos_get_logs(svn_repos_t *repos,
  *
  * Use @a pool for all allocations.
  *
- * @since New in 1.7.
- */
-svn_error_t *
-svn_repos_fs_get_mergeinfo2(svn_mergeinfo_catalog_t *catalog,
-                            svn_repos_t *repos,
-                            const apr_array_header_t *paths,
-                            svn_revnum_t revision,
-                            svn_mergeinfo_inheritance_t inherit,
-                            svn_boolean_t validate_inherited_mergeinfo,
-                            svn_boolean_t include_descendants,
-                            svn_repos_authz_func_t authz_read_func,
-                            void *authz_read_baton,
-                            apr_pool_t *pool);
-
-/**
- * Similar to svn_repos_fs_get_mergeinfo2(), but with
- * @a validate_inherited_mergeinfo always passed as FALSE.
- *
- * @deprecated Provided for backward compatibility with the 1.6 API.
+ * @since New in 1.5.
  */
-SVN_DEPRECATED
 svn_error_t *
 svn_repos_fs_get_mergeinfo(svn_mergeinfo_catalog_t *catalog,
                            svn_repos_t *repos,
@@ -2474,7 +2451,7 @@ svn_repos_verify_fs(svn_repos_t *repos,
  * revision up through @a end_rev.  Use @a pool for all allocation.  If
  * non-@c NULL, send feedback to @a feedback_stream.  If @a dumpstream is
  * @c NULL, this is effectively a primitive verify.  It is not complete,
- * however; see svn_fs_verify instead.
+ * however; svn_repos_verify_fs2() and svn_fs_verify().
  *
  * If @a start_rev is #SVN_INVALID_REVNUM, then start dumping at revision
  * 0.  If @a end_rev is #SVN_INVALID_REVNUM, then dump through the @c HEAD

Modified: subversion/branches/svn_mutex/subversion/include/svn_sorts.h
URL: http://svn.apache.org/viewvc/subversion/branches/svn_mutex/subversion/include/svn_sorts.h?rev=1182053&r1=1182052&r2=1182053&view=diff
==============================================================================
--- subversion/branches/svn_mutex/subversion/include/svn_sorts.h (original)
+++ subversion/branches/svn_mutex/subversion/include/svn_sorts.h Tue Oct 11 19:52:34 2011
@@ -145,7 +145,7 @@ svn_sort_compare_ranges(const void *a,
 /** Sort @a ht according to its keys, return an @c apr_array_header_t
  * containing @c svn_sort__item_t structures holding those keys and values
  * (i.e. for each @c svn_sort__item_t @a item in the returned array,
- * @a item->key and @a item->size are the hash key, and @a item->data points to
+ * @a item->key and @a item->size are the hash key, and @a item->value points to
  * the hash value).
  *
  * Storage is shared with the original hash, not copied.
@@ -182,6 +182,16 @@ svn_sort__array_insert(const void *new_e
                        int insert_index);
 
 
+/* Remove ELEMENTS_TO_DELETE elements starting  at DELETE_INDEX from the
+   array ARR. If DELETE_INDEX is not a valid element of ARR,
+   ELEMENTS_TO_DELETE is not greater than zero, or
+   DELETE_INDEX + ELEMENTS_TO_DELETE is greater than ARR->NELTS, then do
+   nothing. */
+void
+svn_sort__array_delete(apr_array_header_t *arr,
+                       int delete_index,
+                       int elements_to_delete);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */

Modified: subversion/branches/svn_mutex/subversion/include/svn_types.h
URL: http://svn.apache.org/viewvc/subversion/branches/svn_mutex/subversion/include/svn_types.h?rev=1182053&r1=1182052&r2=1182053&view=diff
==============================================================================
--- subversion/branches/svn_mutex/subversion/include/svn_types.h (original)
+++ subversion/branches/svn_mutex/subversion/include/svn_types.h Tue Oct 11 19:52:34 2011
@@ -81,6 +81,22 @@ extern "C" {
 # endif
 #endif
 
+
+
+/** YABT:  Yet Another Boolean Type */
+typedef int svn_boolean_t;
+
+#ifndef TRUE
+/** uhh... true */
+#define TRUE 1
+#endif /* TRUE */
+
+#ifndef FALSE
+/** uhh... false */
+#define FALSE 0
+#endif /* FALSE */
+
+
 
 /** Subversion error object.
  *
@@ -131,7 +147,7 @@ typedef struct svn_error_t
 
 } svn_error_t;
 
-/* See svn_version.h. 
+/* See svn_version.h.
    Defined here to avoid including svn_version.h from all public headers. */
 typedef struct svn_version_t svn_version_t;
 
@@ -188,7 +204,33 @@ svn__apr_hash_index_val(const apr_hash_i
 
 /** @} */
 
-/** The various types of nodes in the Subversion filesystem. */
+/** A node kind.
+ *
+ * @since New in 1.8. Replaces svn_node_kind_t.
+ */
+typedef enum svn_kind_t
+{
+  /** something's here, but we don't know what */
+  svn_kind_unknown,
+
+  /** absent */
+  svn_kind_none,
+
+  /** regular file */
+  svn_kind_file,
+
+  /** directory */
+  svn_kind_dir,
+
+  /** symbolic link */
+  svn_kind_symlink
+
+} svn_kind_t;
+
+/** The various types of nodes in the Subversion filesystem.
+ *
+ * This type is superseded by #svn_kind_t and will be deprecated when
+ * transition to the new type is complete. */
 typedef enum svn_node_kind_t
 {
   /** absent */
@@ -223,6 +265,24 @@ svn_node_kind_to_word(svn_node_kind_t ki
 svn_node_kind_t
 svn_node_kind_from_word(const char *word);
 
+/** Return the #svn_node_kind_t corresponding to the given #svn_kind_t;
+ * #svn_kind_symlink will become #svn_node_file.
+ *
+ * @since New in 1.8.
+ */
+svn_node_kind_t
+svn__node_kind_from_kind(svn_kind_t kind);
+
+/** Return the #svn_kind_t corresponding to the given #svn_node_kind_t,
+ * or #svn_kind_symlink if @a is_symlink is true.
+ *
+ * @since New in 1.8.
+ */
+svn_kind_t
+svn__kind_from_node_kind(svn_node_kind_t kind,
+                         svn_boolean_t is_symlink);
+
+
 /** Generic three-state property to represent an unknown value for values
  * that are just like booleans.  The values have been set deliberately to
  * make tristates disjoint from #svn_boolean_t.
@@ -356,20 +416,6 @@ typedef apr_int64_t svn_filesize_t;
 #endif
 
 
-/** YABT:  Yet Another Boolean Type */
-typedef int svn_boolean_t;
-
-#ifndef TRUE
-/** uhh... true */
-#define TRUE 1
-#endif /* TRUE */
-
-#ifndef FALSE
-/** uhh... false */
-#define FALSE 0
-#endif /* FALSE */
-
-
 /** An enum to indicate whether recursion is needed. */
 enum svn_recurse_kind
 {
@@ -757,7 +803,7 @@ svn_log_changed_path2_dup(const svn_log_
 
 /**
  * A structure to represent a path that changed for a log entry.  Same as
- * #svn_log_changed_path2_t, but without the node kind.
+ * the first three fields of #svn_log_changed_path2_t.
  *
  * @deprecated Provided for backward compatibility with the 1.5 API.
  */
@@ -810,7 +856,8 @@ typedef struct svn_log_entry_t
   svn_revnum_t revision;
 
   /** The hash of requested revision properties, which may be NULL if it
-   * would contain no revprops. */
+   * would contain no revprops.  Maps (const char *) property name to
+   * (svn_string_t *) property value. */
   apr_hash_t *revprops;
 
   /**

Modified: subversion/branches/svn_mutex/subversion/include/svn_version.h
URL: http://svn.apache.org/viewvc/subversion/branches/svn_mutex/subversion/include/svn_version.h?rev=1182053&r1=1182052&r2=1182053&view=diff
==============================================================================
--- subversion/branches/svn_mutex/subversion/include/svn_version.h (original)
+++ subversion/branches/svn_mutex/subversion/include/svn_version.h Tue Oct 11 19:52:34 2011
@@ -62,7 +62,7 @@ extern "C" {
  * Modify when new functionality is added or new interfaces are
  * defined, but all changes are backward compatible.
  */
-#define SVN_VER_MINOR      7
+#define SVN_VER_MINOR      8
 
 /**
  * Patch number.

Modified: subversion/branches/svn_mutex/subversion/include/svn_wc.h
URL: http://svn.apache.org/viewvc/subversion/branches/svn_mutex/subversion/include/svn_wc.h?rev=1182053&r1=1182052&r2=1182053&view=diff
==============================================================================
--- subversion/branches/svn_mutex/subversion/include/svn_wc.h (original)
+++ subversion/branches/svn_mutex/subversion/include/svn_wc.h Tue Oct 11 19:52:34 2011
@@ -1107,6 +1107,10 @@ typedef enum svn_wc_notify_action_t
    * @since New in 1.7. */
   svn_wc_notify_update_skip_working_only,
 
+  /** An update tried to update a file or directory to which access could
+   * not be obtained. @since New in 1.7. */
+  svn_wc_notify_update_skip_access_denied,
+
   /** An update operation removed an external working copy.
    * @since New in 1.7. */
   svn_wc_notify_update_external_removed,
@@ -1201,6 +1205,10 @@ typedef enum svn_wc_notify_action_t
    * @since New in 1.7. */
   svn_wc_notify_failed_forbidden_by_server,
 
+  /** The operation skipped the path because it was conflicted.
+   * @since New in 1.7. */
+  svn_wc_notify_skip_conflicted,
+
 } svn_wc_notify_action_t;
 
 
@@ -1263,7 +1271,7 @@ typedef enum svn_wc_notify_lock_state_t
  * @c kind, @c content_state, @c prop_state and @c lock_state are from
  * after @c action, not before.
  *
- * @note If @c action is #svn_wc_notify_update (### what?), then @c path has
+ * @note If @c action is #svn_wc_notify_update_completed, then @c path has
  * already been installed, so it is legitimate for an implementation of
  * #svn_wc_notify_func2_t to examine @c path in the working copy.
  *
@@ -1287,7 +1295,7 @@ typedef struct svn_wc_notify_t {
 
   /** Path, either absolute or relative to the current working directory
    * (i.e., not relative to an anchor).  @c path is "." or another valid path
-   * value for compatibility reasons when the real target is an url that
+   * value for compatibility reasons when the real target is a url that
    * is available in @c url. */
   const char *path;
 
@@ -1543,7 +1551,11 @@ typedef enum svn_wc_conflict_reason_t
   /** Object is already added or schedule-add. @since New in 1.6. */
   svn_wc_conflict_reason_added,
   /** Object is already replaced. @since New in 1.7. */
-  svn_wc_conflict_reason_replaced
+  svn_wc_conflict_reason_replaced,
+  /** Object is moved away. @since New in 1.8. */
+  svn_wc_conflict_reason_moved_away,
+  /** Object is moved here. @since New in 1.8. */
+  svn_wc_conflict_reason_moved_here
 
 } svn_wc_conflict_reason_t;
 
@@ -1747,7 +1759,7 @@ typedef struct svn_wc_conflict_descripti
   /** Info on the "merge-right source" or "their" version of incoming change. */
   const svn_wc_conflict_version_t *src_right_version;
 
-  /* Remember to adjust svn_wc__conflict_description_dup()
+  /* Remember to adjust svn_wc__conflict_description2_dup()
    * if you add new fields to this struct. */
 } svn_wc_conflict_description2_t;
 
@@ -1841,8 +1853,6 @@ typedef struct svn_wc_conflict_descripti
    * @since New in 1.6. */
   svn_wc_conflict_version_t *src_right_version;
 
-  /* Remember to adjust svn_wc__conflict_description_dup()
-   * if you add new fields to this struct. */
 } svn_wc_conflict_description_t;
 
 /**
@@ -2050,7 +2060,7 @@ svn_wc_create_conflict_result(svn_wc_con
  *
  * The values #svn_wc_conflict_choose_mine_conflict and
  * #svn_wc_conflict_choose_theirs_conflict are not legal for conflicts
- * in binary files or properties.
+ * in binary files or binary properties.
  *
  * Implementations of this callback are free to present the conflict
  * using any user interface.  This may include simple contextual
@@ -3033,12 +3043,25 @@ svn_wc_entry_dup(const svn_wc_entry_t *e
  */
 typedef struct svn_wc_info_t
 {
-  /* ### Do we still need schedule? */
+  /** The schedule of this item 
+   * ### Do we still need schedule? */
   svn_wc_schedule_t schedule;
+
+  /** If copied, the URL from which the copy was made, else @c NULL. */
   const char *copyfrom_url;
+
+  /** If copied, the revision from which the copy was made,
+   * else #SVN_INVALID_REVNUM. */
   svn_revnum_t copyfrom_rev;
+
+  /** The checksum of the node, if it is a file. */
   const svn_checksum_t *checksum;
+
+  /** A changelist the item is in, @c NULL if this node is not in a
+   * changelist. */
   const char *changelist;
+
+  /** The depth of the item, see #svn_depth_t */
   svn_depth_t depth;
 
   /**
@@ -3060,6 +3083,13 @@ typedef struct svn_wc_info_t
   /** The local absolute path of the working copy root.  */
   const char *wcroot_abspath;
 
+  /** The path the node was moved from, if it was moved here. Else NULL.
+   * @since New in 1.8. */
+  const char *moved_from_abspath;
+
+  /** The path the node was moved to, if it was moved away. Else NULL.
+   * @since New in 1.8. */
+  const char *moved_to_abspath;
 } svn_wc_info_t;
 
 /**
@@ -3539,6 +3569,9 @@ typedef struct svn_wc_status3_t
   /** The URL of the repository */
   const char *repos_root_url;
 
+  /** The UUID of the repository */
+  const char *repos_uuid;
+
   /** The in-repository path relative to the repository root. */
   const char *repos_relpath;
 
@@ -3601,6 +3634,43 @@ typedef struct svn_wc_status3_t
 
   /** @} */
 
+  /** Set to the local absolute path that this node was moved from, if this
+   * file or directory has been moved here locally and is the root of that
+   * move. Otherwise set to NULL.
+   *
+   * This will be NULL for moved-here nodes that are just part of a subtree
+   * that was moved along (and are not themselves a root of a different move
+   * operation).
+   * 
+   * @since New in 1.8. */
+  const char *moved_from_abspath;
+
+  /** Set to the local absolute path that this node was moved to, if this file
+   * or directory has been moved away locally and corresponds to the root
+   * of the destination side of the move. Otherwise set to NULL.
+   *
+   * Note: Saying just "root" here could be misleading. For example:
+   *   svn mv A AA;
+   *   svn mv AA/B BB;
+   * creates a situation where A/B is moved-to BB, but one could argue that
+   * the move source's root actually was AA/B. Note that, as far as the
+   * working copy is concerned, above case is exactly identical to:
+   *   svn mv A/B BB;
+   *   svn mv A AA;
+   * In both situations, @a moved_to_abspath would be set for nodes A (moved
+   * to AA) and A/B (moved to BB), only.
+   *
+   * This will be NULL for moved-away nodes that were just part of a subtree
+   * that was moved along (and are not themselves a root of a different move
+   * operation).
+   *
+   * @since New in 1.8. */
+  const char *moved_to_abspath;
+
+  /* TRUE iff the item is a file brought in by an svn:externals definition.
+   * @since New in 1.8. */
+  svn_boolean_t file_external;
+
   /* NOTE! Please update svn_wc_dup_status3() when adding new fields here. */
 } svn_wc_status3_t;
 
@@ -4011,6 +4081,10 @@ svn_wc_walk_status(svn_wc_context_t *wc_
  * If @a cancel_func is non-NULL, call it with @a cancel_baton while building
  * the @a statushash to determine if the client has canceled the operation.
  *
+ * If @a depth_as_sticky is set handle @a depth like when depth_is_sticky is
+ * passed for updating. This will show excluded nodes show up as added in the
+ * repository.
+ *
  * If @a server_performs_filtering is TRUE, assume that the server handles
  * the ambient depth filtering, so this doesn't have to be handled in the
  * editor.
@@ -4032,6 +4106,7 @@ svn_wc_get_status_editor5(const svn_delt
                           svn_depth_t depth,
                           svn_boolean_t get_all,
                           svn_boolean_t no_ignore,
+                          svn_boolean_t depth_as_sticky,
                           svn_boolean_t server_performs_filtering,
                           const apr_array_header_t *ignore_patterns,
                           svn_wc_status_func4_t status_func,
@@ -6476,7 +6551,8 @@ typedef enum svn_wc_merge_outcome_t
  * control, then set @a *merge_outcome to #svn_wc_merge_no_merge and
  * return success without merging anything.  (The reasoning is that if
  * the file is not versioned, then it is probably unrelated to the
- * changes being considered, so they should not be merged into it.)
+ * changes being considered, so they should not be merged into it.
+ * Furtheremore, merging into an unversioned file is a lossy operation.)
  *
  * @a dry_run determines whether the working copy is modified.  When it
  * is @c FALSE the merge will cause @a target_abspath to be modified, when
@@ -6923,7 +6999,7 @@ typedef svn_error_t *(*svn_wc_relocation
  * the @a root argument.
  *
  * If @a root is TRUE, then the implementation should make sure that @a url
- * is the repository root.  Else, it can be an URL inside the repository.
+ * is the repository root.  Else, it can be a URL inside the repository.
  *
  * @deprecated Provided for backwards compatibility with the 1.4 API.
  */

Modified: subversion/branches/svn_mutex/subversion/libsvn_client/blame.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn_mutex/subversion/libsvn_client/blame.c?rev=1182053&r1=1182052&r2=1182053&view=diff
==============================================================================
--- subversion/branches/svn_mutex/subversion/libsvn_client/blame.c (original)
+++ subversion/branches/svn_mutex/subversion/libsvn_client/blame.c Tue Oct 11 19:52:34 2011
@@ -85,7 +85,7 @@ struct file_rev_baton {
   struct rev *rev;     /* the rev for which blame is being assigned
                           during a diff */
   struct blame_chain *chain;      /* the original blame chain. */
-  const char *tmp_path; /* temp file name to feed svn_io_open_unique_file */
+  const char *repos_root_url;    /* To construct a url */
   apr_pool_t *mainpool;  /* lives during the whole sequence of calls */
   apr_pool_t *lastpool;  /* pool used during previous call */
   apr_pool_t *currpool;  /* pool used during this call */
@@ -108,7 +108,6 @@ struct delta_baton {
   void *wrapped_baton;
   struct file_rev_baton *file_rev_baton;
   svn_stream_t *source_stream;  /* the delta source */
-  svn_stream_t *stream;  /* the result of the delta */
   const char *filename;
 };
 
@@ -321,13 +320,12 @@ window_handler(svn_txdelta_window_t *win
   if (window)
     return SVN_NO_ERROR;
 
-  /* Close the files used for the delta.
+  /* Close the source file used for the delta.
      It is important to do this early, since otherwise, they will be deleted
      before all handles are closed, which leads to failures on some platforms
      when new tempfiles are to be created. */
   if (dbaton->source_stream)
     SVN_ERR(svn_stream_close(dbaton->source_stream));
-  SVN_ERR(svn_stream_close(dbaton->stream));
 
   /* If we are including merged revisions, we need to add each rev to the
      merged chain. */
@@ -426,7 +424,11 @@ file_rev_handler(void *baton, const char
   if (frb->ctx->notify_func2)
     {
       svn_wc_notify_t *notify
-        = svn_wc_create_notify(path, svn_wc_notify_blame_revision, pool);
+            = svn_wc_create_notify_url(
+                            svn_path_url_add_component2(frb->repos_root_url,
+                                                        path+1, pool),
+                            svn_wc_notify_blame_revision, pool);
+      notify->path = path;
       notify->kind = svn_node_none;
       notify->content_state = notify->prop_state
         = svn_wc_notify_state_inapplicable;
@@ -467,12 +469,9 @@ file_rev_handler(void *baton, const char
   else
     filepool = frb->currpool;
 
-  SVN_ERR(svn_stream_open_unique(&delta_baton->stream,
-                                 &delta_baton->filename,
-                                 NULL,
+  SVN_ERR(svn_stream_open_unique(&cur_stream, &delta_baton->filename, NULL,
                                  svn_io_file_del_on_pool_cleanup,
                                  filepool, filepool));
-  cur_stream = svn_stream_disown(delta_baton->stream, filepool);
 
   /* Get window handler for applying delta. */
   svn_txdelta_apply(last_stream, cur_stream, NULL, NULL,
@@ -647,8 +646,7 @@ svn_client_blame5(const char *target,
       frb.merged_chain->pool = pool;
     }
 
-  SVN_ERR(svn_io_temp_dir(&frb.tmp_path, pool));
-  frb.tmp_path = svn_dirent_join(frb.tmp_path, "tmp", pool),
+  SVN_ERR(svn_ra_get_repos_root2(ra_session, &frb.repos_root_url, pool));
 
   frb.mainpool = pool;
   /* The callback will flip the following two pools, because it needs

Modified: subversion/branches/svn_mutex/subversion/libsvn_client/cat.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn_mutex/subversion/libsvn_client/cat.c?rev=1182053&r1=1182052&r2=1182053&view=diff
==============================================================================
--- subversion/branches/svn_mutex/subversion/libsvn_client/cat.c (original)
+++ subversion/branches/svn_mutex/subversion/libsvn_client/cat.c Tue Oct 11 19:52:34 2011
@@ -50,6 +50,7 @@ svn_client__get_normalized_stream(svn_st
                                   const char *local_abspath,
                                   const svn_opt_revision_t *revision,
                                   svn_boolean_t expand_keywords,
+                                  svn_boolean_t normalize_eols,
                                   svn_cancel_func_t cancel_func,
                                   void *cancel_baton,
                                   apr_pool_t *result_pool,
@@ -163,8 +164,10 @@ svn_client__get_normalized_stream(svn_st
 
   /* Wrap the output stream if translation is needed. */
   if (eol != NULL || kw != NULL)
-    input = svn_subst_stream_translated(input, eol, FALSE, kw, expand_keywords,
-                                        result_pool);
+    input = svn_subst_stream_translated(
+      input,
+      (eol_style && normalize_eols) ? SVN_SUBST_NATIVE_EOL_STR : eol,
+      FALSE, kw, expand_keywords, result_pool);
 
   *normal_stream = input;
 
@@ -211,7 +214,7 @@ svn_client_cat2(svn_stream_t *out,
 
       SVN_ERR(svn_dirent_get_absolute(&local_abspath, path_or_url, pool));
       SVN_ERR(svn_client__get_normalized_stream(&normal_stream, ctx->wc_ctx,
-                                            local_abspath, revision, TRUE,
+                                            local_abspath, revision, TRUE, FALSE,
                                             ctx->cancel_func, ctx->cancel_baton,
                                             pool, pool));
 

Modified: subversion/branches/svn_mutex/subversion/libsvn_client/cleanup.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn_mutex/subversion/libsvn_client/cleanup.c?rev=1182053&r1=1182052&r2=1182053&view=diff
==============================================================================
--- subversion/branches/svn_mutex/subversion/libsvn_client/cleanup.c (original)
+++ subversion/branches/svn_mutex/subversion/libsvn_client/cleanup.c Tue Oct 11 19:52:34 2011
@@ -88,7 +88,7 @@ fetch_repos_info(const char **repos_root
   svn_ra_session_t *ra_session;
 
   /* The same info is likely to retrieved multiple times (e.g. externals) */
-  if (ri->last_repos && svn_uri__is_child(ri->last_repos, url, NULL))
+  if (ri->last_repos && svn_uri__is_child(ri->last_repos, url, scratch_pool))
     {
       *repos_root = apr_pstrdup(result_pool, ri->last_repos);
       *repos_uuid = apr_pstrdup(result_pool, ri->last_uuid);
@@ -120,6 +120,7 @@ svn_client_upgrade(const char *path,
   apr_hash_t *externals;
   apr_hash_index_t *hi;
   apr_pool_t *iterpool;
+  apr_pool_t *iterpool2;
   svn_opt_revision_t rev = {svn_opt_revision_unspecified, {0}};
   struct repos_info_baton info_baton;
 
@@ -148,62 +149,220 @@ svn_client_upgrade(const char *path,
                               scratch_pool, scratch_pool));
 
   iterpool = svn_pool_create(scratch_pool);
+  iterpool2 = svn_pool_create(scratch_pool);
 
   for (hi = apr_hash_first(scratch_pool, externals); hi;
        hi = apr_hash_next(hi))
     {
       int i;
+      const char *externals_parent_abspath;
+      const char *externals_parent_url;
+      const char *externals_parent_repos_root_url;
       const char *externals_parent = svn__apr_hash_index_key(hi);
       svn_string_t *external_desc = svn__apr_hash_index_val(hi);
       apr_array_header_t *externals_p;
+      svn_error_t *err;
 
       svn_pool_clear(iterpool);
       externals_p = apr_array_make(iterpool, 1,
                                    sizeof(svn_wc_external_item2_t*));
 
-      SVN_ERR(svn_wc_parse_externals_description3(
+      /* In this loop, an error causes the respective externals definition, or
+       * the external (inner loop), to be skipped, so that upgrade carries on
+       * with the other externals. */
+
+      err = svn_dirent_get_absolute(&externals_parent_abspath,
+                                    externals_parent, iterpool);
+
+      if (!err)
+        err = svn_wc__node_get_url(&externals_parent_url, ctx->wc_ctx,
+                                   externals_parent_abspath,
+                                   iterpool, iterpool);
+      if (!err)
+        err = svn_wc__node_get_repos_info(&externals_parent_repos_root_url,
+                                          NULL,
+                                          ctx->wc_ctx,
+                                          externals_parent_abspath,
+                                          iterpool, iterpool);
+      if (!err)
+        err = svn_wc_parse_externals_description3(
                   &externals_p, svn_dirent_dirname(path, iterpool),
-                  external_desc->data, TRUE, iterpool));
+                  external_desc->data, FALSE, iterpool);
+      if (err)
+        {
+          svn_wc_notify_t *notify =
+              svn_wc_create_notify(externals_parent,
+                                   svn_wc_notify_failed_external,
+                                   scratch_pool);
+          notify->err = err;
+
+          ctx->notify_func2(ctx->notify_baton2,
+                            notify, scratch_pool);
+
+          svn_error_clear(err);
+
+          /* Next externals definition, please... */
+          continue;
+        }
+
       for (i = 0; i < externals_p->nelts; i++)
         {
           svn_wc_external_item2_t *item;
+          const char *resolved_url;
           const char *external_abspath;
-          const char *external_path;
-          svn_node_kind_t kind;
-          svn_error_t *err;
+          const char *repos_relpath;
+          const char *repos_root_url;
+          const char *repos_uuid;
+          svn_node_kind_t external_kind;
+          svn_revnum_t peg_revision;
+          svn_revnum_t revision;
 
           item = APR_ARRAY_IDX(externals_p, i, svn_wc_external_item2_t*);
 
-          external_path = svn_dirent_join(externals_parent, item->target_dir,
-                                          iterpool);
-
-          SVN_ERR(svn_dirent_get_absolute(&external_abspath, external_path,
-                                          iterpool));
+          svn_pool_clear(iterpool2);
+          external_abspath = svn_dirent_join(externals_parent_abspath,
+                                             item->target_dir,
+                                             iterpool2);
+
+          err = svn_wc__resolve_relative_external_url(
+                                              &resolved_url,
+                                              item,
+                                              externals_parent_repos_root_url,
+                                              externals_parent_url,
+                                              scratch_pool, scratch_pool);
+          if (err)
+            goto handle_error;
+
+          /* This is a hack. We only need to call svn_wc_upgrade() on external
+           * dirs, as file externals are upgraded along with their defining
+           * WC.  Reading the kind will throw an exception on an external dir,
+           * saying that the wc must be upgraded.  If it's a file, the lookup
+           * is done in an adm_dir belonging to the defining wc (which has
+           * already been upgraded) and no error is returned.  If it doesn't
+           * exist (external that isn't checked out yet), we'll just get
+           * svn_node_none. */
+          err = svn_wc_read_kind(&external_kind, ctx->wc_ctx,
+                                 external_abspath, FALSE, iterpool2);
+          if (err && err->apr_err == SVN_ERR_WC_UPGRADE_REQUIRED)
+            {
+              svn_error_clear(err);
 
-          /* This is hack. We can only send dirs to svn_wc_upgrade(). This
-             way we will get an exception saying that the wc must be
-             upgraded if it's a dir. If it's a file then the lookup is done
-             in an adm_dir belonging to the real wc and since that was
-             updated before the externals no error is returned. */
-          err = svn_wc_read_kind(&kind, ctx->wc_ctx, external_abspath, FALSE,
-                                 iterpool);
+              err = svn_client_upgrade(external_abspath, ctx, iterpool2);
+              if (err)
+                goto handle_error;
+            }
+          else if (err)
+            goto handle_error;
 
-          if (err && err->apr_err == SVN_ERR_WC_UPGRADE_REQUIRED)
+          /* The upgrade of any dir should be done now, get the now reliable
+           * kind. */
+          err = svn_wc_read_kind(&external_kind, ctx->wc_ctx, external_abspath,
+                                 FALSE, iterpool2);
+          if (err)
+            goto handle_error;
+
+          /* Update the EXTERNALS table according to the root URL,
+           * relpath and uuid known in the upgraded external WC. */
+
+          /* We should probably have a function that provides all three
+           * of root URL, repos relpath and uuid at once, but here goes... */
+
+          /* First get the relpath, as that returns SVN_ERR_WC_PATH_NOT_FOUND
+           * when the node is not present in the file system.
+           * svn_wc__node_get_repos_info() would try to derive the URL. */
+          err = svn_wc__node_get_repos_relpath(&repos_relpath,
+                                               ctx->wc_ctx,
+                                               external_abspath,
+                                               iterpool2, iterpool2);
+          if (! err)
+            {
+              /* We got a repos relpath from a WC. So also get the root. */
+              err = svn_wc__node_get_repos_info(&repos_root_url,
+                                                &repos_uuid,
+                                                ctx->wc_ctx,
+                                                external_abspath,
+                                                iterpool2, iterpool2);
+              if (err)
+                goto handle_error;
+            }
+          else if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
             {
+              /* The external is not currently checked out. Try to figure out
+               * the URL parts via the defined URL and fetch_repos_info(). */
               svn_error_clear(err);
+              repos_relpath = NULL;
+              repos_root_url = NULL;
+              repos_uuid = NULL;
+            }
+          else if (err)
+            goto handle_error;
+
+          /* If we haven't got any information from the checked out external,
+           * or if the URL information mismatches the external's definition,
+           * ask fetch_repos_info() to find out the repos root. */
+          if (! repos_relpath || ! repos_root_url
+              || 0 != strcmp(resolved_url,
+                             svn_path_url_add_component2(repos_root_url,
+                                                         repos_relpath,
+                                                         scratch_pool)))
+            {
+              err = fetch_repos_info(&repos_root_url,
+                                     &repos_uuid,
+                                     &info_baton,
+                                     resolved_url,
+                                     scratch_pool, scratch_pool);
+              if (err)
+                goto handle_error;
+
+              repos_relpath = svn_uri_skip_ancestor(repos_root_url,
+                                                    resolved_url,
+                                                    iterpool2);
+
+              /* There's just the URL, no idea what kind the external is.
+               * That's fine, as the external isn't even checked out yet.
+               * The kind will be set during the next 'update'. */
+              external_kind = svn_node_unknown;
+            }
+
+          if (err)
+            goto handle_error;
 
-              SVN_ERR(svn_wc_upgrade(ctx->wc_ctx, external_abspath,
-                                     fetch_repos_info, &info_baton,
-                                     ctx->cancel_func, ctx->cancel_baton,
-                                     ctx->notify_func2, ctx->notify_baton2,
-                                     iterpool));
+          peg_revision = (item->peg_revision.kind == svn_opt_revision_number
+                          ? item->peg_revision.value.number
+                          : SVN_INVALID_REVNUM);
+
+          revision = (item->revision.kind == svn_opt_revision_number
+                      ? item->revision.value.number
+                      : SVN_INVALID_REVNUM);
+
+          err = svn_wc__upgrade_add_external_info(ctx->wc_ctx,
+                                                  external_abspath,
+                                                  external_kind,
+                                                  externals_parent,
+                                                  repos_relpath,
+                                                  repos_root_url,
+                                                  repos_uuid,
+                                                  peg_revision,
+                                                  revision,
+                                                  iterpool2);
+handle_error:
+          if (err)
+            {
+              svn_wc_notify_t *notify =
+                  svn_wc_create_notify(external_abspath,
+                                       svn_wc_notify_failed_external,
+                                       scratch_pool);
+              notify->err = err;
+              ctx->notify_func2(ctx->notify_baton2,
+                                notify, scratch_pool);
+              svn_error_clear(err);
+              /* Next external node, please... */
             }
-          else
-            SVN_ERR(err);
         }
     }
 
   svn_pool_destroy(iterpool);
+  svn_pool_destroy(iterpool2);
 
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/svn_mutex/subversion/libsvn_client/client.h
URL: http://svn.apache.org/viewvc/subversion/branches/svn_mutex/subversion/libsvn_client/client.h?rev=1182053&r1=1182052&r2=1182053&view=diff
==============================================================================
--- subversion/branches/svn_mutex/subversion/libsvn_client/client.h (original)
+++ subversion/branches/svn_mutex/subversion/libsvn_client/client.h Tue Oct 11 19:52:34 2011
@@ -105,10 +105,13 @@ svn_error_t *svn_client__get_copy_source
    specify the point(s) of interest (typically the revisions referred
    to as the "operative range" for a given operation) along that history.
 
-   END may be of kind svn_opt_revision_unspecified (in which case
+   END may be NULL or of kind svn_opt_revision_unspecified (in either case
    END_URL and END_REVISION are not touched by the function);
    START and REVISION may not.
 
+   If PATH is a WC path and REVISION is of kind svn_opt_revision_working,
+   then look at the PATH's copy-from URL instead of its base URL.
+
    RA_SESSION should be an open RA session pointing at the URL of PATH,
    or NULL, in which case this function will open its own temporary session.
 
@@ -191,7 +194,8 @@ svn_client__get_youngest_common_ancestor
    is not, then @c SVN_ERR_CLIENT_UNRELATED_RESOURCES is returned.
 
    BASE_DIR_ABSPATH is the working copy path the ra_session corresponds to,
-   should only be used if PATH_OR_URL is a url.
+   and should only be used if PATH_OR_URL is a url
+     ### else NULL? what's it for?
 
    If PEG_REVISION's kind is svn_opt_revision_unspecified, it is
    interpreted as "head" for a URL or "working" for a working-copy path.
@@ -223,21 +227,37 @@ svn_client__ra_session_from_path(svn_ra_
    NULL.
 
    If SESSION_URL is NULL, treat this as a magic value meaning "point
-   the RA session to the root of the repository".  */
+   the RA session to the root of the repository".
+
+   NOTE: The typical usage pattern for this functions is:
+
+       const char *old_session_url;
+       SVN_ERR(svn_client__ensure_ra_session_url(&old_session_url,
+                                                 ra_session,
+                                                 new_session_url,
+                                                 pool);
+
+       [...]
+
+       if (old_session_url)
+         SVN_ERR(svn_ra_reparent(ra_session, old_session_url, pool));
+*/
 svn_error_t *
 svn_client__ensure_ra_session_url(const char **old_session_url,
                                   svn_ra_session_t *ra_session,
                                   const char *session_url,
                                   apr_pool_t *pool);
 
-/* Set REPOS_ROOT, allocated in RESULT_POOL to the URL which represents
+/* Set *REPOS_ROOT and *REPOS_UUID, to the URL and UUID that represent
    the root of the repository in with ABSPATH_OR_URL is versioned.
    Use the authentication baton and working copy context cached in CTX as
-   necessary.
+   necessary.  REPOS_ROOT and/or REPOS_UUID may be NULL if not wanted.
 
+   Allocate *REPOS_ROOT and *REPOS_UUID in RESULT_POOL.
    Use SCRATCH_POOL for temporary allocations. */
 svn_error_t *
 svn_client__get_repos_root(const char **repos_root,
+                           const char **repos_uuid,
                            const char *abspath_or_url,
                            svn_client_ctx_t *ctx,
                            apr_pool_t *result_pool,
@@ -570,24 +590,28 @@ svn_client__switch_internal(svn_revnum_t
 /* Create an editor for a pure repository comparison, i.e. comparing one
    repository version against the other.
 
-   TARGET is a working-copy path, the base of the hierarchy to be
-   compared.  It corresponds to the URL opened in RA_SESSION below.
-
-   WC_CTX is a context for the working copy and should be NULL for
-   operations that do not involve a working copy.
-
    DIFF_CMD/DIFF_CMD_BATON represent the callback and callback argument that
    implement the file comparison function
 
    DEPTH is the depth to recurse.
 
-   DRY_RUN is set if this is a dry-run merge. It is not relevant for diff.
-
-   RA_SESSION defines the additional RA session for requesting file
-   contents.
+   RA_SESSION is an RA session through which this editor may fetch
+   properties, file contents and directory listings of the 'old' side of the
+   diff. It is a separate RA session from the one through which this editor
+   is being driven.
 
    REVISION is the start revision in the comparison.
 
+   For each deleted directory, if WALK_DELETED_DIRS is true then just call
+   the 'dir_deleted' callback once, otherwise call the 'file_deleted' or
+   'dir_deleted' callback for each individual node in that subtree.
+
+   If TEXT_DELTAS is FALSE, then do not expect text deltas from the edit
+   drive, nor send the 'before' and 'after' texts to the diff callbacks;
+   instead, send empty files to the diff callbacks if there was a change.
+   This must be FALSE if the edit producer is not sending text deltas,
+   otherwise the file content checksum comparisons will fail.
+
    If NOTIFY_FUNC is non-null, invoke it with NOTIFY_BATON for each
    file and directory operated on during the edit.
 
@@ -595,50 +619,41 @@ svn_client__switch_internal(svn_revnum_t
 svn_error_t *
 svn_client__get_diff_editor(const svn_delta_editor_t **editor,
                             void **edit_baton,
-                            svn_wc_context_t *wc_ctx,
-                            const char *target,
                             svn_depth_t depth,
                             svn_ra_session_t *ra_session,
                             svn_revnum_t revision,
                             svn_boolean_t walk_deleted_dirs,
-                            svn_boolean_t dry_run,
+                            svn_boolean_t text_deltas,
                             const svn_wc_diff_callbacks4_t *diff_callbacks,
                             void *diff_cmd_baton,
                             svn_cancel_func_t cancel_func,
                             void *cancel_baton,
                             svn_wc_notify_func2_t notify_func,
                             void *notify_baton,
-                            apr_pool_t *result_pool,
-                            apr_pool_t *scratch_pool);
+                            apr_pool_t *result_pool);
 
 
 /* ---------------------------------------------------------------- */
 
 /*** Editor for diff summary ***/
 
-/* Create an editor for a repository diff summary, i.e. comparing one
-   repository version against the other and only providing information
-   about the changed items without the text deltas.
+/* Set *CALLBACKS and *CALLBACK_BATON to a set of diff callbacks that will
+   report a diff summary, i.e. only providing information about the changed
+   items without the text deltas.
 
-   TARGET is the target of the diff, relative to the root of the edit.
+   TARGET is the target path, relative to the anchor, of the diff.
 
    SUMMARIZE_FUNC is called with SUMMARIZE_BATON as parameter by the
-   created svn_delta_editor_t for each changed item.
-
-   See svn_client__get_diff_editor() for a description of the other
-   parameters.  */
+   created callbacks for each changed item.
+*/
 svn_error_t *
-svn_client__get_diff_summarize_editor(const char *target,
-                                      svn_client_diff_summarize_func_t
-                                      summarize_func,
-                                      void *summarize_baton,
-                                      svn_ra_session_t *ra_session,
-                                      svn_revnum_t revision,
-                                      svn_cancel_func_t cancel_func,
-                                      void *cancel_baton,
-                                      const svn_delta_editor_t **editor,
-                                      void **edit_baton,
-                                      apr_pool_t *pool);
+svn_client__get_diff_summarize_callbacks(
+                        svn_wc_diff_callbacks4_t **callbacks,
+                        void **callback_baton,
+                        const char *target,
+                        svn_client_diff_summarize_func_t summarize_func,
+                        void *summarize_baton,
+                        apr_pool_t *pool);
 
 /* ---------------------------------------------------------------- */
 
@@ -1041,13 +1056,21 @@ svn_client__ensure_revprop_table(apr_has
 
 /* Return a potentially translated version of local file LOCAL_ABSPATH
    in NORMAL_STREAM.  REVISION must be one of the following: BASE, COMMITTED,
-   WORKING.  Uses SCRATCH_POOL for temporary allocations. */
+   WORKING.
+
+   EXPAND_KEYWORDS operates as per the EXPAND argument to
+   svn_subst_stream_translated, which see.  If NORMALIZE_EOLS is TRUE and
+   LOCAL_ABSPATH requires translation, then normalize the line endings in
+   *NORMAL_STREAM.
+
+   Uses SCRATCH_POOL for temporary allocations. */
 svn_error_t *
 svn_client__get_normalized_stream(svn_stream_t **normal_stream,
                                   svn_wc_context_t *wc_ctx,
                                   const char *local_abspath,
                                   const svn_opt_revision_t *revision,
                                   svn_boolean_t expand_keywords,
+                                  svn_boolean_t normalize_eols,
                                   svn_cancel_func_t cancel_func,
                                   void *cancel_baton,
                                   apr_pool_t *result_pool,

Modified: subversion/branches/svn_mutex/subversion/libsvn_client/cmdline.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn_mutex/subversion/libsvn_client/cmdline.c?rev=1182053&r1=1182052&r2=1182053&view=diff
==============================================================================
--- subversion/branches/svn_mutex/subversion/libsvn_client/cmdline.c (original)
+++ subversion/branches/svn_mutex/subversion/libsvn_client/cmdline.c Tue Oct 11 19:52:34 2011
@@ -114,8 +114,8 @@ check_root_url_of_target(const char **ro
   if (!svn_path_is_url(truepath))
     SVN_ERR(svn_dirent_get_absolute(&truepath, truepath, pool));
 
-  err =  svn_client__get_repos_root(&tmp_root_url, truepath,
-                                    ctx, pool, pool);
+  err = svn_client__get_repos_root(&tmp_root_url, NULL, truepath,
+                                   ctx, pool, pool);
 
   if (err)
     {
@@ -125,7 +125,7 @@ check_root_url_of_target(const char **ro
        *
        * If the target itself is a URL to a repository that does not exist,
        * that's fine, too. The callers will deal with this argument in an
-       * appropriate manter if it does not make any sense.
+       * appropriate manner if it does not make any sense.
        *
        * Also tolerate locally added targets ("bad revision" error).
        */
@@ -142,7 +142,7 @@ check_root_url_of_target(const char **ro
         return svn_error_trace(err);
      }
 
-   if (*root_url != NULL)
+   if (*root_url && tmp_root_url)
      {
        if (strcmp(*root_url, tmp_root_url) != 0)
          return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
@@ -292,7 +292,9 @@ svn_client_args_to_target_array2(apr_arr
                                                   original_target, pool));
                   err2 = svn_wc_read_kind(&kind, ctx->wc_ctx, target_abspath,
                                           FALSE, pool);
-                  if (err2 && err2->apr_err == SVN_ERR_WC_NOT_WORKING_COPY)
+                  if (err2
+                      && (err2->apr_err == SVN_ERR_WC_NOT_WORKING_COPY
+                          || err2->apr_err == SVN_ERR_WC_UPGRADE_REQUIRED))
                     {
                       svn_error_clear(err2);
                     }

Modified: subversion/branches/svn_mutex/subversion/libsvn_client/commit.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn_mutex/subversion/libsvn_client/commit.c?rev=1182053&r1=1182052&r2=1182053&view=diff
==============================================================================
--- subversion/branches/svn_mutex/subversion/libsvn_client/commit.c (original)
+++ subversion/branches/svn_mutex/subversion/libsvn_client/commit.c Tue Oct 11 19:52:34 2011
@@ -667,10 +667,12 @@ get_ra_editor(svn_ra_session_t **ra_sess
                                            log_msg, ctx, pool));
 
   /* Fetch RA commit editor. */
-  return svn_ra_get_commit_editor3(*ra_session, editor, edit_baton,
-                                   commit_revprops, commit_callback,
-                                   commit_baton, lock_tokens, keep_locks,
-                                   pool);
+  SVN_ERR(svn_ra_get_commit_editor3(*ra_session, editor, edit_baton,
+                                    commit_revprops, commit_callback,
+                                    commit_baton, lock_tokens, keep_locks,
+                                    pool));
+
+  return SVN_NO_ERROR;
 }
 
 
@@ -696,7 +698,6 @@ svn_client_import4(const char *path,
   apr_hash_t *excludes = apr_hash_make(pool);
   svn_node_kind_t kind;
   const char *local_abspath;
-  const char *base_dir_abspath;
   apr_array_header_t *new_entries = apr_array_make(pool, 4,
                                                    sizeof(const char *));
   const char *temp;
@@ -708,7 +709,6 @@ svn_client_import4(const char *path,
                              _("'%s' is not a local path"), path);
 
   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
-  base_dir_abspath = local_abspath;
 
   /* Create a new commit item and add it to the array. */
   if (SVN_CLIENT__HAS_LOG_MSG_FUNC(ctx))
@@ -739,8 +739,6 @@ svn_client_import4(const char *path,
     }
 
   SVN_ERR(svn_io_check_path(local_abspath, &kind, pool));
-  if (kind == svn_node_file)
-    base_dir_abspath = svn_dirent_dirname(local_abspath, pool);
 
   /* Figure out all the path components we need to create just to have
      a place to stick our imported tree. */
@@ -770,7 +768,7 @@ svn_client_import4(const char *path,
         }
     }
   while ((err = get_ra_editor(&ra_session,
-                              &editor, &edit_baton, ctx, url, base_dir_abspath,
+                              &editor, &edit_baton, ctx, url, NULL,
                               log_msg, NULL, revprop_table, FALSE, NULL, TRUE,
                               commit_callback, commit_baton, subpool)));
 
@@ -1356,6 +1354,128 @@ svn_client_commit5(const apr_array_heade
       goto cleanup;
   }
 
+  /* For every target that was moved verify that both halves of the
+   * move are part of the commit. */
+  for (i = 0; i < commit_items->nelts; i++)
+    {
+      svn_client_commit_item3_t *item =
+        APR_ARRAY_IDX(commit_items, i, svn_client_commit_item3_t *);
+
+      svn_pool_clear(iterpool);
+
+      if (item->state_flags & SVN_CLIENT_COMMIT_ITEM_IS_COPY)
+        {
+          const char *moved_from_abspath;
+          const char *delete_op_root_abspath;
+
+          cmt_err = svn_error_trace(svn_wc__node_was_moved_here(
+                                      &moved_from_abspath,
+                                      &delete_op_root_abspath,
+                                      ctx->wc_ctx, item->path,
+                                      iterpool, iterpool));
+          if (cmt_err)
+            goto cleanup;
+
+          if (moved_from_abspath && delete_op_root_abspath &&
+              strcmp(moved_from_abspath, delete_op_root_abspath) == 0)
+
+            {
+              svn_boolean_t found_delete_half =
+                (apr_hash_get(committables->by_path, delete_op_root_abspath,
+                               APR_HASH_KEY_STRING) != NULL);
+              
+              if (!found_delete_half)
+                {
+                  const char *delete_half_parent_abspath;
+
+                  /* The delete-half isn't in the commit target list.
+                   * However, it might itself be the child of a deleted node,
+                   * either because of another move or a deletion.
+                   *
+                   * For example, consider: mv A/B B; mv B/C C; commit;
+                   * C's moved-from A/B/C is a child of the deleted A/B.
+                   * A/B/C does not appear in the commit target list, but
+                   * A/B does appear.
+                   * (Note that moved-from information is always stored
+                   * relative to the BASE tree, so we have 'C moved-from
+                   * A/B/C', not 'C moved-from B/C'.)
+                   *
+                   * An example involving a move and a delete would be:
+                   * mv A/B C; rm A; commit;
+                   * Now C is moved-from A/B which does not appear in the
+                   * commit target list, but A does appear.
+                   */
+
+                  /* Scan upwards for a deletion op-root from the
+                   * delete-half's parent directory. */
+                  delete_half_parent_abspath =
+                    svn_dirent_dirname(delete_op_root_abspath, iterpool);
+                  if (strcmp(delete_op_root_abspath,
+                             delete_half_parent_abspath) != 0)
+                    {
+                      const char *parent_delete_op_root_abspath;
+
+                      cmt_err = svn_error_trace(
+                                  svn_wc__node_get_deleted_ancestor(
+                                    &parent_delete_op_root_abspath,
+                                    ctx->wc_ctx, delete_half_parent_abspath,
+                                    iterpool, iterpool));
+                      if (cmt_err)
+                        goto cleanup;
+
+                      if (parent_delete_op_root_abspath)
+                        found_delete_half =
+                          (apr_hash_get(committables->by_path,
+                                        parent_delete_op_root_abspath,
+                                        APR_HASH_KEY_STRING) != NULL);
+                    }
+                }
+
+              if (!found_delete_half)
+                {
+                  cmt_err = svn_error_createf(
+                              SVN_ERR_ILLEGAL_TARGET, NULL,
+                              _("Cannot commit '%s' because it was moved from "
+                                "'%s' which is not part of the commit; both "
+                                "sides of the move must be committed together"),
+                              svn_dirent_local_style(item->path, iterpool),
+                              svn_dirent_local_style(delete_op_root_abspath,
+                                                     iterpool));
+                  goto cleanup;
+                }
+            }
+        }
+      else if (item->state_flags & SVN_CLIENT_COMMIT_ITEM_DELETE)
+        {
+          const char *moved_to_abspath;
+          const char *copy_op_root_abspath;
+
+          cmt_err = svn_error_trace(svn_wc__node_was_moved_away(
+                                      &moved_to_abspath,
+                                      &copy_op_root_abspath,
+                                      ctx->wc_ctx, item->path,
+                                      iterpool, iterpool));
+          if (cmt_err)
+            goto cleanup;
+
+          if (moved_to_abspath && copy_op_root_abspath &&
+              strcmp(moved_to_abspath, copy_op_root_abspath) == 0 &&
+              apr_hash_get(committables->by_path, copy_op_root_abspath,
+                           APR_HASH_KEY_STRING) == NULL)
+            {
+              cmt_err = svn_error_createf(
+                          SVN_ERR_ILLEGAL_TARGET, NULL,
+                         _("Cannot commit '%s' because it was moved to '%s' "
+                           "which is not part of the commit; both sides of "
+                           "the move must be committed together"),
+                         svn_dirent_local_style(item->path, iterpool),
+                         svn_dirent_local_style(copy_op_root_abspath,
+                                                iterpool));
+              goto cleanup;
+            }
+        }
+    }
+
   /* Go get a log message.  If an error occurs, or no log message is
      specified, abort the operation. */
   if (SVN_CLIENT__HAS_LOG_MSG_FUNC(ctx))
@@ -1451,8 +1571,10 @@ svn_client_commit5(const apr_array_heade
 
  cleanup:
   /* Abort the commit if it is still in progress. */
+  svn_pool_clear(iterpool); /* Close open handles before aborting */
   if (commit_in_progress)
-    svn_error_clear(editor->abort_edit(edit_baton, pool));
+    cmt_err = svn_error_compose_create(cmt_err,
+                                       editor->abort_edit(edit_baton, pool));
 
   /* A bump error is likely to occur while running a working copy log file,
      explicitly unlocking and removing temporary files would be wrong in

Modified: subversion/branches/svn_mutex/subversion/libsvn_client/commit_util.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn_mutex/subversion/libsvn_client/commit_util.c?rev=1182053&r1=1182052&r2=1182053&view=diff
==============================================================================
--- subversion/branches/svn_mutex/subversion/libsvn_client/commit_util.c (original)
+++ subversion/branches/svn_mutex/subversion/libsvn_client/commit_util.c Tue Oct 11 19:52:34 2011
@@ -402,7 +402,7 @@ bail_on_tree_conflicted_ancestor(svn_wc_
    If COMMIT_RELPATH is not NULL, treat not-added nodes as if it is destined to
    be added as COMMIT_RELPATH, and add 'deleted' entries to COMMITTABLES as
    items to delete in the copy destination.  COPY_MODE_ROOT should be set TRUE
-   for the first call for which COPY_MODE is TRUE, i.e. not for for the
+   for the first call for which COPY_MODE is TRUE, i.e. not for the
    recursive calls, and FALSE otherwise.
 
    If CHANGELISTS is non-NULL, it is a hash whose keys are const char *
@@ -543,12 +543,12 @@ harvest_committables(svn_wc_context_t *w
          svn_dirent_local_style(local_abspath, scratch_pool));
     }
 
+  /* ### in need of comment */
   if (copy_mode
       && is_update_root
       && db_kind == svn_node_file)
     {
-      if (copy_mode)
-        return SVN_NO_ERROR;
+      return SVN_NO_ERROR;
     }
 
   /* If NODE is in our changelist, then examine it for conflicts. We
@@ -587,7 +587,7 @@ harvest_committables(svn_wc_context_t *w
   /* Check for the deletion case.
      * We delete explicitly deleted nodes (duh!)
      * We delete not-present children of copies
-     * We delete nodes that directly replace a node in it's ancestor
+     * We delete nodes that directly replace a node in its ancestor
    */
 
   if (is_deleted || is_replaced)
@@ -1341,14 +1341,9 @@ svn_client__condense_commit_items(const 
     {
       svn_client_commit_item3_t *this_item
         = APR_ARRAY_IDX(ci, i, svn_client_commit_item3_t *);
-      size_t url_len = strlen(this_item->url);
-      size_t base_url_len = strlen(*base_url);
 
-      if (url_len > base_url_len)
-        this_item->session_relpath = svn_uri__is_child(*base_url,
-                                                       this_item->url, pool);
-      else
-        this_item->session_relpath = "";
+      this_item->session_relpath = svn_uri_skip_ancestor(*base_url,
+                                                         this_item->url, pool);
     }
 #ifdef SVN_CLIENT_COMMIT_DEBUG
   /* ### TEMPORARY CODE ### */
@@ -1845,11 +1840,14 @@ svn_client__do_commit(const char *base_u
                                          result_pool, iterpool);
 
       if (err)
-        return svn_error_trace(fixup_commit_error(item->path,
-                                                  base_url,
-                                                  item->session_relpath,
-                                                  svn_node_file,
-                                                  err, ctx, iterpool));
+        {
+          svn_pool_destroy(iterpool); /* Close tempfiles */
+          return svn_error_trace(fixup_commit_error(item->path,
+                                                    base_url,
+                                                    item->session_relpath,
+                                                    svn_node_file,
+                                                    err, ctx, scratch_pool));
+        }
 
       if (md5_checksums)
         apr_hash_set(*md5_checksums, item->path, APR_HASH_KEY_STRING,

Modified: subversion/branches/svn_mutex/subversion/libsvn_client/copy.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn_mutex/subversion/libsvn_client/copy.c?rev=1182053&r1=1182052&r2=1182053&view=diff
==============================================================================
--- subversion/branches/svn_mutex/subversion/libsvn_client/copy.c (original)
+++ subversion/branches/svn_mutex/subversion/libsvn_client/copy.c Tue Oct 11 19:52:34 2011
@@ -123,8 +123,8 @@ calculate_target_mergeinfo(svn_ra_sessio
                                                 ra_session, src_url, pool));
       SVN_ERR(svn_client__get_repos_mergeinfo(ra_session, &src_mergeinfo,
                                               "", src_revnum,
-                                              svn_mergeinfo_inherited, TRUE,
-                                              FALSE, pool));
+                                              svn_mergeinfo_inherited,
+                                              TRUE, pool));
       if (old_session_url)
         SVN_ERR(svn_ra_reparent(ra_session, old_session_url, pool));
     }
@@ -761,7 +761,7 @@ repos_to_repos_copy(const apr_array_head
   apr_hash_t *action_hash = apr_hash_make(pool);
   apr_array_header_t *path_infos;
   const char *top_url, *top_url_all, *top_url_dst;
-  const char *message, *repos_root, *ignored_url;
+  const char *message, *repos_root;
   svn_revnum_t youngest = SVN_INVALID_REVNUM;
   svn_ra_session_t *ra_session = NULL;
   const svn_delta_editor_t *editor;
@@ -795,8 +795,7 @@ repos_to_repos_copy(const apr_array_head
       svn_client__copy_pair_t *pair = APR_ARRAY_IDX(copy_pairs, i,
                                                     svn_client__copy_pair_t *);
       apr_hash_t *mergeinfo;
-      svn_opt_revision_t *src_rev, *ignored_rev, dead_end_rev;
-      dead_end_rev.kind = svn_opt_revision_unspecified;
+      svn_opt_revision_t *src_rev;
 
       /* Are the source and destination URLs at or under REPOS_ROOT? */
       if (! (svn_uri__is_ancestor(repos_root, pair->src_abspath_or_url)
@@ -816,21 +815,17 @@ repos_to_repos_copy(const apr_array_head
 
       /* Run the history function to get the source's URL in the
          operational revision. */
-      SVN_ERR(svn_client__ensure_ra_session_url(&ignored_url, ra_session,
-                                                pair->src_abspath_or_url,
-                                                pool));
+      SVN_ERR(svn_ra_reparent(ra_session, pair->src_abspath_or_url, pool));
       SVN_ERR(svn_client__repos_locations(&pair->src_abspath_or_url, &src_rev,
-                                          &ignored_url, &ignored_rev,
+                                          NULL, NULL,
                                           ra_session,
                                           pair->src_abspath_or_url,
                                           &pair->src_peg_revision,
-                                          &pair->src_op_revision,
-                                          &dead_end_rev, ctx, pool));
+                                          &pair->src_op_revision, NULL,
+                                          ctx, pool));
 
       /* Go ahead and grab mergeinfo from the source, too. */
-      SVN_ERR(svn_client__ensure_ra_session_url(&ignored_url, ra_session,
-                                                pair->src_abspath_or_url,
-                                                pool));
+      SVN_ERR(svn_ra_reparent(ra_session, pair->src_abspath_or_url, pool));
       SVN_ERR(calculate_target_mergeinfo(ra_session, &mergeinfo, NULL,
                                          pair->src_abspath_or_url,
                                          pair->src_revnum, ctx, pool));
@@ -895,8 +890,7 @@ repos_to_repos_copy(const apr_array_head
     }
 
   /* Point the RA session to our current TOP_URL. */
-  SVN_ERR(svn_client__ensure_ra_session_url(&ignored_url, ra_session,
-                                            top_url, pool));
+  SVN_ERR(svn_ra_reparent(ra_session, top_url, pool));
 
   /* If we're allowed to create nonexistent parent directories of our
      destinations, then make a list in NEW_DIRS of the parent
@@ -1000,18 +994,12 @@ repos_to_repos_copy(const apr_array_head
       svn_node_kind_t dst_kind;
       const char *src_rel, *dst_rel;
 
-      src_rel = svn_uri__is_child(top_url, pair->src_abspath_or_url, pool);
+      src_rel = svn_uri_skip_ancestor(top_url, pair->src_abspath_or_url, pool);
       if (src_rel)
         {
           SVN_ERR(svn_ra_check_path(ra_session, src_rel, pair->src_revnum,
                                     &info->src_kind, pool));
         }
-      else if (strcmp(pair->src_abspath_or_url, top_url) == 0)
-        {
-          src_rel = "";
-          SVN_ERR(svn_ra_check_path(ra_session, src_rel, pair->src_revnum,
-                                    &info->src_kind, pool));
-        }
       else
         {
           const char *old_url = NULL;
@@ -1835,19 +1823,16 @@ repos_to_wc_copy(const apr_array_header_
     {
       svn_client__copy_pair_t *pair = APR_ARRAY_IDX(copy_pairs, i,
                                                     svn_client__copy_pair_t *);
-      const char *src, *ignored_url;
-      svn_opt_revision_t *new_rev, *ignored_rev, dead_end_rev;
+      const char *src;
+      svn_opt_revision_t *new_rev;
 
       svn_pool_clear(iterpool);
-      dead_end_rev.kind = svn_opt_revision_unspecified;
 
-      SVN_ERR(svn_client__repos_locations(&src, &new_rev,
-                                          &ignored_url, &ignored_rev,
+      SVN_ERR(svn_client__repos_locations(&src, &new_rev, NULL, NULL,
                                           NULL,
                                           pair->src_abspath_or_url,
                                           &pair->src_peg_revision,
-                                          &pair->src_op_revision,
-                                          &dead_end_rev,
+                                          &pair->src_op_revision, NULL,
                                           ctx, iterpool));
 
       pair->src_original = pair->src_abspath_or_url;
@@ -2161,9 +2146,9 @@ try_copy(const apr_array_header_t *sourc
     {
       if (!srcs_are_urls)
         {
-          /* If we are doing a wc->* move, but with an operational revision
+          /* If we are doing a wc->* copy, but with an operational revision
              other than the working copy revision, we are really doing a
-             repo->* move, because we're going to need to get the rev from the
+             repo->* copy, because we're going to need to get the rev from the
              repo. */
 
           svn_boolean_t need_repos_op_rev = FALSE;

Modified: subversion/branches/svn_mutex/subversion/libsvn_client/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn_mutex/subversion/libsvn_client/deprecated.c?rev=1182053&r1=1182052&r2=1182053&view=diff
==============================================================================
--- subversion/branches/svn_mutex/subversion/libsvn_client/deprecated.c (original)
+++ subversion/branches/svn_mutex/subversion/libsvn_client/deprecated.c Tue Oct 11 19:52:34 2011
@@ -38,6 +38,7 @@
 #include "svn_compat.h"
 #include "svn_props.h"
 #include "svn_utf.h"
+#include "svn_string.h"
 
 #include "client.h"
 #include "mergeinfo.h"
@@ -836,6 +837,37 @@ svn_client_delete(svn_client_commit_info
 /*** From diff.c ***/
 
 svn_error_t *
+svn_client_diff5(const apr_array_header_t *diff_options,
+                 const char *path1,
+                 const svn_opt_revision_t *revision1,
+                 const char *path2,
+                 const svn_opt_revision_t *revision2,
+                 const char *relative_to_dir,
+                 svn_depth_t depth,
+                 svn_boolean_t ignore_ancestry,
+                 svn_boolean_t no_diff_deleted,
+                 svn_boolean_t show_copies_as_adds,
+                 svn_boolean_t ignore_content_type,
+                 svn_boolean_t use_git_diff_format,
+                 const char *header_encoding,
+                 apr_file_t *outfile,
+                 apr_file_t *errfile,
+                 const apr_array_header_t *changelists,
+                 svn_client_ctx_t *ctx,
+                 apr_pool_t *pool)
+{
+  svn_stream_t *outstream = svn_stream_from_aprfile2(outfile, TRUE, pool);
+  svn_stream_t *errstream = svn_stream_from_aprfile2(errfile, TRUE, pool);
+
+  return svn_client_diff6(diff_options, path1, revision1, path2,
+                          revision2, relative_to_dir, depth,
+                          ignore_ancestry, no_diff_deleted,
+                          show_copies_as_adds, ignore_content_type,
+                          use_git_diff_format, header_encoding,
+                          outstream, errstream, changelists, ctx, pool);
+}
+
+svn_error_t *
 svn_client_diff4(const apr_array_header_t *options,
                  const char *path1,
                  const svn_opt_revision_t *revision1,
@@ -925,6 +957,49 @@ svn_client_diff(const apr_array_header_t
 }
 
 svn_error_t *
+svn_client_diff_peg5(const apr_array_header_t *diff_options,
+                     const char *path,
+                     const svn_opt_revision_t *peg_revision,
+                     const svn_opt_revision_t *start_revision,
+                     const svn_opt_revision_t *end_revision,
+                     const char *relative_to_dir,
+                     svn_depth_t depth,
+                     svn_boolean_t ignore_ancestry,
+                     svn_boolean_t no_diff_deleted,
+                     svn_boolean_t show_copies_as_adds,
+                     svn_boolean_t ignore_content_type,
+                     svn_boolean_t use_git_diff_format,
+                     const char *header_encoding,
+                     apr_file_t *outfile,
+                     apr_file_t *errfile,
+                     const apr_array_header_t *changelists,
+                     svn_client_ctx_t *ctx,
+                     apr_pool_t *pool)
+{
+  svn_stream_t *outstream = svn_stream_from_aprfile2(outfile, TRUE, pool);
+  svn_stream_t *errstream = svn_stream_from_aprfile2(errfile, TRUE, pool);
+
+  return svn_client_diff_peg6(diff_options,
+                              path,
+                              peg_revision,
+                              start_revision,
+                              end_revision,
+                              relative_to_dir,
+                              depth,
+                              ignore_ancestry,
+                              no_diff_deleted,
+                              show_copies_as_adds,
+                              ignore_content_type,
+                              use_git_diff_format,
+                              header_encoding,
+                              outstream,
+                              errstream,
+                              changelists,
+                              ctx,
+                              pool);
+}
+
+svn_error_t *
 svn_client_diff_peg4(const apr_array_header_t *options,
                      const char *path,
                      const svn_opt_revision_t *peg_revision,
@@ -1721,6 +1796,40 @@ svn_client_propget(apr_hash_t **props,
 }
 
 
+/* Duplicate a HASH containing (char * -> svn_string_t *) key/value
+   pairs using POOL. */
+static apr_hash_t *
+string_hash_dup(apr_hash_t *hash, apr_pool_t *pool)
+{
+  apr_hash_index_t *hi;
+  apr_hash_t *new_hash = apr_hash_make(pool);
+
+  for (hi = apr_hash_first(pool, hash); hi; hi = apr_hash_next(hi))
+    {
+      const char *key = apr_pstrdup(pool, svn__apr_hash_index_key(hi));
+      apr_ssize_t klen = svn__apr_hash_index_klen(hi);
+      svn_string_t *val = svn_string_dup(svn__apr_hash_index_val(hi), pool);
+
+      apr_hash_set(new_hash, key, klen, val);
+    }
+  return new_hash;
+}
+
+svn_client_proplist_item_t *
+svn_client_proplist_item_dup(const svn_client_proplist_item_t *item,
+                             apr_pool_t * pool)
+{
+  svn_client_proplist_item_t *new_item = apr_pcalloc(pool, sizeof(*new_item));
+
+  if (item->node_name)
+    new_item->node_name = svn_stringbuf_dup(item->node_name, pool);
+
+  if (item->prop_hash)
+    new_item->prop_hash = string_hash_dup(item->prop_hash, pool);
+
+  return new_item;
+}
+
 /* Receiver baton used by proplist2() */
 struct proplist_receiver_baton {
   apr_array_header_t *props;
@@ -2142,7 +2251,9 @@ info_from_info2(svn_info_t **new_info,
   info->last_changed_rev    = info2->last_changed_rev;
   info->last_changed_date   = info2->last_changed_date;
   info->last_changed_author = info2->last_changed_author;
-  info->lock                = info2->lock;
+
+  /* Stupid old structure has a non-const LOCK member. Sigh.  */
+  info->lock                = (svn_lock_t *)info2->lock;
 
   info->size64              = info2->size;
   if (info2->size == SVN_INVALID_FILESIZE)
@@ -2302,10 +2413,11 @@ svn_client_info2(const char *path_or_url
   SVN_ERR(svn_client_info3(abspath_or_url,
                            peg_revision,
                            revision,
-                           info_receiver_relpath_wrapper,
-                           &rb,
                            depth,
+                           FALSE, TRUE,
                            changelists,
+                           info_receiver_relpath_wrapper,
+                           &rb,
                            ctx,
                            pool));