You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by hw...@apache.org on 2010/08/10 22:56:05 UTC

svn commit: r984206 [13/35] - in /subversion/branches/ignore-mergeinfo: ./ build/ build/generator/ build/generator/templates/ build/hudson/ build/hudson/jobs/subversion-1.6.x-solaris/ build/hudson/jobs/subversion-1.6.x-ubuntu/ build/hudson/jobs/subvers...

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/adm_files.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/adm_files.c?rev=984206&r1=984205&r2=984206&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/adm_files.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/adm_files.c Tue Aug 10 20:55:56 2010
@@ -101,73 +101,39 @@ svn_wc_set_adm_dir(const char *name, apr
         adm_dir_name = *dir_name;
         return SVN_NO_ERROR;
       }
-  return svn_error_createf
-    (SVN_ERR_BAD_FILENAME, NULL,
-     _("'%s' is not a valid administrative directory name"),
-     svn_dirent_local_style(name, pool));
+  return svn_error_createf(SVN_ERR_BAD_FILENAME, NULL,
+                           _("'%s' is not a valid administrative "
+                             "directory name"),
+                           svn_dirent_local_style(name, pool));
 }
 
 
-/* Return the path to something in PATH's administrative area.
- *
- * First, the adm subdir is appended to PATH as a component, then the
- * "tmp" directory is added iff USE_TMP is set, then each of the
- * varargs in AP (char *'s) is appended as a path component.  The list
- * must be terminated with a NULL argument.
- *
- * Adding an empty component results in no effect (i.e., the separator
- * char is not doubled).
- *
- * If EXTENSION is non-null, it will be appended to the final string
- * without a separator character.
- */
 static const char *
-v_extend_with_adm_name(const char *path,
-                       const char *extension,
-                       svn_boolean_t use_tmp,
-                       apr_pool_t *pool,
-                       va_list ap)
+simple_extend(const char *adm_path,  /* ### adm_abspath?  */
+              svn_boolean_t use_tmp,
+              const char *subdir,
+              const char *child,
+              const char *extension,
+              apr_pool_t *result_pool)
 {
-  const char *this;
-
-  /* Tack on the administrative subdirectory. */
-  path = svn_dirent_join(path, adm_dir_name, pool);
-
-  /* If this is a tmp file, name it into the tmp area. */
-  if (use_tmp)
-    path = svn_dirent_join(path, SVN_WC__ADM_TMP, pool);
-
-  /* Tack on everything else. */
-  while ((this = va_arg(ap, const char *)) != NULL)
-    {
-      if (this[0] == '\0')
-        continue;
-
-      path = svn_dirent_join(path, this, pool);
-    }
-
+  if (subdir)
+    child = svn_dirent_join(subdir, child, result_pool);
   if (extension)
-    path = apr_pstrcat(pool, path, extension, NULL);
+    child = apr_pstrcat(result_pool, child, extension, NULL);
 
-  return path;
-}
-
-
-/* See v_extend_with_adm_name() for details. */
-static const char *
-extend_with_adm_name(const char *path,
-                     const char *extension,
-                     svn_boolean_t use_tmp,
-                     apr_pool_t *pool,
-                     ...)
-{
-  va_list ap;
-
-  va_start(ap, pool);
-  path = v_extend_with_adm_name(path, extension, use_tmp, pool, ap);
-  va_end(ap);
-
-  return path;
+  if (use_tmp)
+    return svn_dirent_join_many(result_pool,
+                                adm_path,
+                                adm_dir_name,
+                                SVN_WC__ADM_TMP,
+                                child,
+                                NULL);
+
+  return svn_dirent_join_many(result_pool,
+                              adm_path,
+                              adm_dir_name,
+                              child,
+                              NULL);
 }
 
 
@@ -175,16 +141,15 @@ const char *svn_wc__adm_child(const char
                               const char *child,
                               apr_pool_t *result_pool)
 {
-  return extend_with_adm_name(path, NULL, FALSE, result_pool, child, NULL);
+  return simple_extend(path, FALSE, NULL, child, NULL, result_pool);
 }
 
 
 svn_boolean_t
-svn_wc__adm_area_exists(const svn_wc_adm_access_t *adm_access,
+svn_wc__adm_area_exists(const char *adm_abspath,
                         apr_pool_t *pool)
 {
-  const char *path = svn_wc__adm_child(svn_wc_adm_access_path(adm_access),
-                                       NULL, pool);
+  const char *path = svn_wc__adm_child(adm_abspath, NULL, pool);
   svn_node_kind_t kind;
   svn_error_t *err;
 
@@ -213,7 +178,7 @@ make_adm_subdir(const char *path,
 {
   const char *fullpath;
 
-  fullpath = extend_with_adm_name(path, NULL, tmp, pool, subdir, NULL);
+  fullpath = simple_extend(path, tmp, NULL, subdir, NULL, pool);
 
   return svn_io_dir_make(fullpath, APR_OS_DEFAULT, pool);
 }
@@ -223,31 +188,29 @@ make_adm_subdir(const char *path,
 /*** Syncing files in the adm area. ***/
 
 
+#ifndef SVN_EXPERIMENTAL_PRISTINE
 svn_error_t *
-svn_wc__sync_text_base(const char *local_abspath,
+svn_wc__sync_text_base(svn_wc__db_t *db,
+                       const char *local_abspath,
                        const char *tmp_text_base_abspath,
-                       apr_pool_t *pool)
+                       apr_pool_t *scratch_pool)
 {
-  const char *parent_path;
-  const char *base_name;
   const char *base_path;
 
-  svn_dirent_split(local_abspath, &parent_path, &base_name, pool);
+  SVN_ERR(svn_wc__text_base_path(&base_path, db, local_abspath, scratch_pool));
 
-  /* Extend real name. */
-  base_path = extend_with_adm_name(parent_path, SVN_WC__BASE_EXT, FALSE, pool,
-                                   SVN_WC__ADM_TEXT_BASE, base_name, NULL);
-
-  /* Rename. */
-  SVN_ERR(svn_io_file_rename(tmp_text_base_abspath, base_path, pool));
-  return svn_io_set_file_read_only(base_path, FALSE, pool);
+  SVN_ERR(svn_io_file_rename(tmp_text_base_abspath, base_path, scratch_pool));
+  SVN_ERR(svn_io_set_file_read_only(base_path, FALSE, scratch_pool));
+
+  return SVN_NO_ERROR;
 }
+#endif
 
+#ifndef SVN_EXPERIMENTAL_PRISTINE
 svn_error_t *
 svn_wc__text_base_path(const char **result_abspath,
                        svn_wc__db_t *db,
                        const char *local_abspath,
-                       svn_boolean_t tmp,
                        apr_pool_t *pool)
 {
   const char *newpath, *base_name;
@@ -255,17 +218,35 @@ svn_wc__text_base_path(const char **resu
   SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
 
   svn_dirent_split(local_abspath, &newpath, &base_name, pool);
-  *result_abspath = extend_with_adm_name(newpath,
-                                         SVN_WC__BASE_EXT,
-                                         tmp,
-                                         pool,
-                                         SVN_WC__ADM_TEXT_BASE,
-                                         base_name,
-                                         NULL);
+  *result_abspath = simple_extend(newpath,
+                                  FALSE,
+                                  SVN_WC__ADM_TEXT_BASE,
+                                  base_name,
+                                  SVN_WC__BASE_EXT,
+                                  pool);
+
+  return SVN_NO_ERROR;
+}
+#endif
+
+svn_error_t *
+svn_wc__text_base_deterministic_tmp_path(const char **result_abspath,
+                                         svn_wc__db_t *db,
+                                         const char *local_abspath,
+                                         apr_pool_t *pool)
+{
+  const char *newpath, *base_name;
+
+  SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
+
+  svn_dirent_split(local_abspath, &newpath, &base_name, pool);
+  *result_abspath = simple_extend(newpath, TRUE, SVN_WC__ADM_TEXT_BASE,
+                                  base_name, SVN_WC__BASE_EXT, pool);
 
   return SVN_NO_ERROR;
 }
 
+#ifndef SVN_EXPERIMENTAL_PRISTINE
 svn_error_t *
 svn_wc__text_revert_path(const char **result_abspath,
                          svn_wc__db_t *db,
@@ -277,40 +258,380 @@ svn_wc__text_revert_path(const char **re
   SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
 
   svn_dirent_split(local_abspath, &newpath, &base_name, pool);
-  *result_abspath = extend_with_adm_name(newpath,
-                                         SVN_WC__REVERT_EXT,
-                                         FALSE,
-                                         pool,
-                                         SVN_WC__ADM_TEXT_BASE,
-                                         base_name,
-                                         NULL);
+  *result_abspath = simple_extend(newpath,
+                                  FALSE,
+                                  SVN_WC__ADM_TEXT_BASE,
+                                  base_name,
+                                  SVN_WC__REVERT_EXT,
+                                  pool);
 
   return SVN_NO_ERROR;
 }
+#endif
 
 
 svn_error_t *
-svn_wc__get_revert_contents(svn_stream_t **contents,
-                            svn_wc__db_t *db,
-                            const char *local_abspath,
-                            apr_pool_t *result_pool,
-                            apr_pool_t *scratch_pool)
-{
+svn_wc__text_base_path_to_read(const char **result_abspath,
+                               svn_wc__db_t *db,
+                               const char *local_abspath,
+                               apr_pool_t *result_pool,
+                               apr_pool_t *scratch_pool)
+{
+#ifdef SVN_EXPERIMENTAL_PRISTINE
+  const svn_checksum_t *checksum;
+
+  SVN_ERR(svn_wc__db_read_info(NULL, NULL, NULL, NULL, NULL, NULL,
+                               NULL, NULL, NULL, NULL, NULL, &checksum,
+                               NULL, NULL, NULL, NULL, NULL, NULL,
+                               NULL, NULL, NULL, NULL, NULL, NULL,
+                               db, local_abspath,
+                               scratch_pool, scratch_pool));
+  if (checksum == NULL)
+    return svn_error_createf(SVN_ERR_WC_PATH_UNEXPECTED_STATUS, NULL,
+                             _("Node '%s' has no pristine text"),
+                             svn_dirent_local_style(local_abspath,
+                                                    scratch_pool));
+  SVN_ERR(svn_wc__db_pristine_get_path(result_abspath, db, local_abspath,
+                                       checksum,
+                                       result_pool, scratch_pool));
+#else
+  SVN_ERR(svn_wc__text_base_path(result_abspath, db, local_abspath,
+                                 result_pool));
+  /* Return an error if the file does not exist */
+  {
+    svn_node_kind_t kind;
+
+    SVN_ERR(svn_io_check_path(*result_abspath, &kind, result_pool));
+    if (kind != svn_node_file)
+      return svn_error_createf(SVN_ERR_WC_PATH_UNEXPECTED_STATUS, NULL,
+                               _("File '%s' has no text base"),
+                               svn_dirent_local_style(local_abspath,
+                                                      result_pool));
+  }
+#endif
+
+  return SVN_NO_ERROR;
+}
+
+
+#ifndef SVN_EXPERIMENTAL_PRISTINE
+svn_error_t *
+svn_wc__text_revert_path_to_read(const char **result_abspath,
+                                 svn_wc__db_t *db,
+                                 const char *local_abspath,
+                                 apr_pool_t *result_pool)
+{
+  SVN_ERR(svn_wc__text_revert_path(result_abspath, db, local_abspath,
+                                   result_pool));
+  /* Return an error if the file does not exist */
+  {
+    svn_node_kind_t kind;
+
+    SVN_ERR(svn_io_check_path(*result_abspath, &kind, result_pool));
+    if (kind != svn_node_file)
+      return svn_error_createf(SVN_ERR_WC_PATH_UNEXPECTED_STATUS, NULL,
+                               _("File '%s' has no text base"),
+                               svn_dirent_local_style(local_abspath,
+                                                      result_pool));
+  }
+
+  return SVN_NO_ERROR;
+}
+#endif
+
+
+svn_error_t *
+svn_wc__ultimate_base_text_path(const char **result_abspath,
+                                svn_wc__db_t *db,
+                                const char *local_abspath,
+                                apr_pool_t *result_pool,
+                                apr_pool_t *scratch_pool)
+{
+#ifdef SVN_EXPERIMENTAL_PRISTINE
+  const svn_checksum_t *checksum;
+
+  SVN_ERR(svn_wc__db_base_get_info(NULL, NULL, NULL, NULL, NULL, NULL,
+                                   NULL, NULL, NULL, NULL, NULL, &checksum,
+                                   NULL, NULL, NULL,
+                                   db, local_abspath,
+                                   scratch_pool, scratch_pool));
+  if (checksum == NULL)
+    return svn_error_createf(SVN_ERR_WC_PATH_UNEXPECTED_STATUS, NULL,
+                             _("Node '%s' has no pristine base text"),
+                             svn_dirent_local_style(local_abspath,
+                                                    scratch_pool));
+  SVN_ERR(svn_wc__db_pristine_get_path(result_abspath, db, local_abspath,
+                                       checksum,
+                                       result_pool, scratch_pool));
+#else
+  svn_error_t *err;
+  svn_boolean_t replaced;
+
+  err = svn_wc__internal_is_replaced(&replaced, db, local_abspath,
+                                     scratch_pool);
+  if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
+    {
+      svn_error_clear(err);
+      replaced = FALSE;
+    }
+  else
+    SVN_ERR(err);
+
+  if (replaced)
+    SVN_ERR(svn_wc__text_revert_path(result_abspath, db, local_abspath,
+                                     result_pool));
+  else
+    SVN_ERR(svn_wc__text_base_path(result_abspath, db, local_abspath,
+                                   result_pool));
+#endif
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_wc__ultimate_base_text_path_to_read(const char **result_abspath,
+                                        svn_wc__db_t *db,
+                                        const char *local_abspath,
+                                        apr_pool_t *result_pool,
+                                        apr_pool_t *scratch_pool)
+{
+  SVN_ERR(svn_wc__ultimate_base_text_path(result_abspath, db, local_abspath,
+                                          result_pool, scratch_pool));
+  /* Return an error if the file does not exist */
+  {
+    svn_node_kind_t kind;
+
+    SVN_ERR(svn_io_check_path(*result_abspath, &kind, scratch_pool));
+    if (kind != svn_node_file)
+      return svn_error_createf(SVN_ERR_WC_PATH_UNEXPECTED_STATUS, NULL,
+                               _("File '%s' has no text base"),
+                               svn_dirent_local_style(local_abspath,
+                                                      scratch_pool));
+  }
+
+  return SVN_NO_ERROR;
+}
+
+
+svn_error_t *
+svn_wc__get_ultimate_base_contents(svn_stream_t **contents,
+                                   svn_wc__db_t *db,
+                                   const char *local_abspath,
+                                   apr_pool_t *result_pool,
+                                   apr_pool_t *scratch_pool)
+{
+#ifdef SVN_EXPERIMENTAL_PRISTINE
+  svn_wc__db_kind_t kind;
+  svn_wc__db_status_t status;
+  const svn_checksum_t *checksum;
+
+  SVN_ERR(svn_wc__db_base_get_info(&status, &kind, NULL, NULL, NULL, NULL,
+                                   NULL, NULL, NULL, NULL, NULL, &checksum,
+                                   NULL, NULL, NULL,
+                                   db, local_abspath,
+                                   scratch_pool, scratch_pool));
+  if (kind != svn_wc__db_kind_file)
+    return svn_error_createf(SVN_ERR_WC_NOT_FILE, NULL,
+                             _("Base node of '%s' is not a file"),
+                             svn_dirent_local_style(local_abspath,
+                                                    scratch_pool));
+  if (status != svn_wc__db_status_normal)
+    {
+      SVN_ERR_ASSERT(checksum == NULL);
+      *contents = NULL;
+      return SVN_NO_ERROR;
+    }
+  SVN_ERR_ASSERT(checksum != NULL);
+  SVN_ERR(svn_wc__db_pristine_read(contents, db, local_abspath,
+                                   checksum, result_pool, scratch_pool));
+#else
   const char *revert_base;
+  svn_error_t *err;
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
 
-  SVN_ERR(svn_wc__text_revert_path(&revert_base, db, local_abspath,
-                                   scratch_pool));
+  /* If there's a WC-1 "revert base", open that. */
+  err = svn_wc__text_revert_path_to_read(&revert_base, db, local_abspath,
+                                         scratch_pool);
+  if (err && err->apr_err == SVN_ERR_WC_PATH_UNEXPECTED_STATUS)
+    {
+      svn_error_clear(err);
+
+      /* There's no "revert base", so open the "normal base". */
+      err = svn_wc__text_base_path_to_read(&revert_base, db, local_abspath,
+                                           scratch_pool, scratch_pool);
+      if (err && err->apr_err == SVN_ERR_WC_PATH_UNEXPECTED_STATUS)
+        {
+          svn_error_clear(err);
+          *contents = NULL;
+          return SVN_NO_ERROR;
+        }
+    }
+  SVN_ERR(err);
+  SVN_ERR(svn_stream_open_readonly(contents, revert_base,
+                                   result_pool, scratch_pool));
+#endif
+
+  return SVN_NO_ERROR;
+}
+
+
+svn_error_t *
+svn_wc__get_pristine_contents(svn_stream_t **contents,
+                              svn_wc__db_t *db,
+                              const char *local_abspath,
+                              apr_pool_t *result_pool,
+                              apr_pool_t *scratch_pool)
+{
+  svn_wc__db_status_t status;
+  svn_wc__db_kind_t kind;
+  const svn_checksum_t *sha1_checksum;
+
+  SVN_ERR(svn_wc__db_read_info(&status, &kind, NULL, NULL, NULL, NULL,
+                               NULL, NULL, NULL, NULL, NULL, &sha1_checksum,
+                               NULL, NULL, NULL, NULL, NULL, NULL,
+                               NULL, NULL, NULL, NULL, NULL, NULL,
+                               db, local_abspath, scratch_pool, scratch_pool));
+
+  /* Sanity */
+  if (kind != svn_wc__db_kind_file)
+    return svn_error_createf(SVN_ERR_NODE_UNEXPECTED_KIND, NULL,
+                             _("Can only get the pristine contents of files; "
+                               "'%s' is not a file"),
+                             svn_dirent_local_style(local_abspath,
+                                                    scratch_pool));
 
-  if (revert_base == NULL)
+  if (status == svn_wc__db_status_added)
     {
-      *contents = NULL;
+      /* For an added node, we return "no stream". Make sure this is not
+         copied-here or moved-here, in which case we return the copy/move
+         source's contents.  */
+      SVN_ERR(svn_wc__db_scan_addition(&status,
+                                       NULL, NULL, NULL, NULL, NULL, NULL,
+                                       NULL, NULL,
+                                       db, local_abspath,
+                                       scratch_pool, scratch_pool));
+      if (status == svn_wc__db_status_added)
+        {
+          /* Simply added. The pristine base does not exist. */
+          *contents = NULL;
+          return SVN_NO_ERROR;
+        }
+    }
+  else if (status == svn_wc__db_status_not_present)
+    /* We know that the delete of this node has been committed.
+       This should be the same as if called on an unknown path. */
+    return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND, NULL,
+                             _("Cannot get the pristine contents of '%s' "
+                               "because its delete is already committed"),
+                             svn_dirent_local_style(local_abspath,
+                                                    scratch_pool));
+  else if (status == svn_wc__db_status_absent
+      || status == svn_wc__db_status_excluded
+      || status == svn_wc__db_status_incomplete)
+    return svn_error_createf(SVN_ERR_WC_PATH_UNEXPECTED_STATUS, NULL,
+                             _("Cannot get the pristine contents of '%s' "
+                               "because it has an unexpected status"),
+                             svn_dirent_local_style(local_abspath,
+                                                    scratch_pool));
+  else
+    /* We know that it is a file, so we can't hit the _obstructed stati.
+       Also, we should never see _base_deleted here. */
+    SVN_ERR_ASSERT(status != svn_wc__db_status_obstructed
+                   && status != svn_wc__db_status_obstructed_add
+                   && status != svn_wc__db_status_obstructed_delete
+                   && status != svn_wc__db_status_base_deleted);
+
+#ifdef SVN_EXPERIMENTAL_PRISTINE
+  if (sha1_checksum)
+    SVN_ERR(svn_wc__db_pristine_read(contents, db, local_abspath,
+                                     sha1_checksum,
+                                     result_pool, scratch_pool));
+  else
+    *contents = NULL;
+#else
+  {
+    const char *text_base;
+    svn_error_t *err, *err2;
+
+    err = svn_wc__text_base_path_to_read(&text_base, db, local_abspath,
+                                         scratch_pool, scratch_pool);
+    /* ### now for some ugly hackiness. right now, file externals will
+       ### sometimes put their pristine contents into the revert base,
+       ### because they think they're *replaced* nodes, rather than
+       ### simple BASE nodes. watch out for this scenario, and
+       ### compensate appropriately.  */
+    if (err)
+      {
+        svn_boolean_t file_external;
+
+        if (err->apr_err != SVN_ERR_WC_PATH_UNEXPECTED_STATUS)
+          return svn_error_return(err);
+
+        err2 = svn_wc__internal_is_file_external(&file_external,
+                                                 db, local_abspath,
+                                                 scratch_pool);
+        if (err2 || !file_external)
+          return svn_error_return(svn_error_compose_create(err, err2));
+
+        svn_error_clear(err);
+
+        SVN_ERR(svn_wc__text_revert_path_to_read(&text_base, db, local_abspath,
+                                                 scratch_pool));
+      }
+    SVN_ERR(svn_stream_open_readonly(contents, text_base,
+                                     result_pool, scratch_pool));
+  }
+#endif
+
+  return SVN_NO_ERROR;
+}
+
+
+svn_error_t *
+svn_wc__get_ultimate_base_md5_checksum(const svn_checksum_t **md5_checksum,
+                                       svn_wc__db_t *db,
+                                       const char *local_abspath,
+                                       apr_pool_t *result_pool,
+                                       apr_pool_t *scratch_pool)
+{
+  svn_error_t *err;
+
+  err = svn_wc__db_base_get_info(NULL, NULL, NULL, NULL, NULL, NULL,
+                                 NULL, NULL, NULL, NULL, NULL, md5_checksum,
+                                 NULL, NULL, NULL,
+                                 db, local_abspath,
+                                 scratch_pool, scratch_pool);
+  if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
+    {
+      svn_error_clear(err);
+      *md5_checksum = NULL;
       return SVN_NO_ERROR;
     }
+  if (*md5_checksum && (*md5_checksum)->kind != svn_checksum_md5)
+    SVN_ERR(svn_wc__db_pristine_get_md5(md5_checksum, db, local_abspath,
+                                        *md5_checksum,
+                                        scratch_pool, scratch_pool));
+  return SVN_NO_ERROR;
+}
+
 
-  return svn_stream_open_readonly(contents, revert_base, result_pool,
-                                  scratch_pool);
+svn_error_t *
+svn_wc__get_pristine_text_status(apr_finfo_t *finfo,
+                                 svn_wc__db_t *db,
+                                 const char *local_abspath,
+                                 apr_pool_t *result_pool,
+                                 apr_pool_t *scratch_pool)
+{
+  const char *text_base_abspath;
+
+  SVN_ERR(svn_wc__text_base_path_to_read(&text_base_abspath,
+                                         db, local_abspath,
+                                         scratch_pool, scratch_pool));
+  SVN_ERR(svn_io_stat(finfo, text_base_abspath,
+                      APR_FINFO_MIN | APR_FINFO_LINK,
+                      result_pool));
+  return SVN_NO_ERROR;
 }
 
 
@@ -329,13 +650,8 @@ svn_wc__prop_path(const char **prop_path
         SVN_WC__ADM_DIR_PROPS         /* svn_wc__props_working */
       };
 
-      *prop_path = extend_with_adm_name
-        (path,
-         NULL,
-         FALSE,
-         pool,
-         names[props_kind],
-         NULL);
+      *prop_path = simple_extend(path, FALSE, NULL, names[props_kind], NULL,
+                                 pool);
     }
   else  /* It's a file */
     {
@@ -354,14 +670,8 @@ svn_wc__prop_path(const char **prop_path
       const char *base_name;
 
       svn_dirent_split(path, prop_path, &base_name, pool);
-      *prop_path = extend_with_adm_name
-        (*prop_path,
-         extensions[props_kind],
-         FALSE,
-         pool,
-         dirs[props_kind],
-         base_name,
-         NULL);
+      *prop_path = simple_extend(*prop_path, FALSE, dirs[props_kind],
+                                 base_name, extensions[props_kind], pool);
     }
 
   return SVN_NO_ERROR;
@@ -390,6 +700,8 @@ svn_wc__open_adm_stream(svn_stream_t **s
 svn_error_t *
 svn_wc__open_writable_base(svn_stream_t **stream,
                            const char **temp_base_abspath,
+                           svn_checksum_t **md5_checksum,
+                           svn_checksum_t **sha1_checksum,
                            svn_wc__db_t *db,
                            const char *local_abspath,
                            apr_pool_t *result_pool,
@@ -398,15 +710,20 @@ svn_wc__open_writable_base(svn_stream_t 
   const char *temp_dir_abspath;
   SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
 
-  /* Select a directory in which to put a WC-1-style temp text-base file. */
-  /* See update_editor.c:get_pristine_tee_stream() for the WC-NG way. */
-  SVN_ERR(svn_wc__db_temp_wcroot_tempdir(&temp_dir_abspath, db, local_abspath,
-                                         scratch_pool, scratch_pool));
+  SVN_ERR(svn_wc__db_pristine_get_tempdir(&temp_dir_abspath, db, local_abspath,
+                                          scratch_pool, scratch_pool));
   SVN_ERR(svn_stream_open_unique(stream,
                                  temp_base_abspath,
                                  temp_dir_abspath,
                                  svn_io_file_del_none,
                                  result_pool, scratch_pool));
+  if (md5_checksum)
+    *stream = svn_stream_checksummed2(*stream, NULL, md5_checksum,
+                                      svn_checksum_md5, FALSE, result_pool);
+  if (sha1_checksum)
+    *stream = svn_stream_checksummed2(*stream, NULL, sha1_checksum,
+                                      svn_checksum_sha1, FALSE, result_pool);
+
   return SVN_NO_ERROR;
 }
 
@@ -429,28 +746,25 @@ init_adm_tmp_area(const char *path, apr_
   SVN_ERR(make_adm_subdir(path, SVN_WC__ADM_PROP_BASE, TRUE, pool));
 
   /* SVN_WC__ADM_TMP/SVN_WC__ADM_PROPS */
-  return make_adm_subdir(path, SVN_WC__ADM_PROPS, TRUE, pool);
+  return svn_error_return(make_adm_subdir(path, SVN_WC__ADM_PROPS, TRUE,
+                                          pool));
 }
 
 
-/* Set up a new adm area for PATH, with URL as the ancestor url, and
+/* Set up a new adm area for PATH, with REPOS_* as the repos info, and
    INITIAL_REV as the starting revision.  The entries file starts out
    marked as 'incomplete.  The adm area starts out locked; remember to
    unlock it when done. */
 static svn_error_t *
 init_adm(svn_wc__db_t *db,
          const char *local_abspath,
-         const char *url,
+         const char *repos_relpath,
          const char *repos_root_url,
          const char *repos_uuid,
          svn_revnum_t initial_rev,
          svn_depth_t depth,
          apr_pool_t *pool)
 {
-  const char *repos_relpath;
-
-  SVN_ERR_ASSERT(svn_uri_is_ancestor(repos_root_url, url));
-
   /* First, make an empty administrative area. */
   SVN_ERR(svn_io_dir_make_hidden(svn_wc__adm_child(local_abspath, NULL, pool),
                                  APR_OS_DEFAULT, pool));
@@ -469,16 +783,17 @@ init_adm(svn_wc__db_t *db,
   /* SVN_WC__ADM_PRISTINE */
   SVN_ERR(make_adm_subdir(local_abspath, SVN_WC__ADM_PRISTINE, FALSE, pool));
 
+  /* ### want to add another directory? do a format bump to ensure that
+     ### all existing working copies get the new directories. or maybe
+     ### create-on-demand (more expensive)  */
+
   /** Init the tmp area. ***/
   SVN_ERR(init_adm_tmp_area(local_abspath, pool));
 
   /* Lastly, create the SDB.  */
-  repos_relpath = svn_uri_is_child(repos_root_url, url, pool);
   SVN_ERR(svn_wc__db_init(db, local_abspath,
-                          repos_relpath == NULL
-                            ? ""
-                            : svn_path_uri_decode(repos_relpath, pool),
-                          repos_root_url, repos_uuid, initial_rev, depth,
+                          repos_relpath, repos_root_url, repos_uuid,
+                          initial_rev, depth,
                           pool));
 
   return SVN_NO_ERROR;
@@ -496,18 +811,28 @@ svn_wc__internal_ensure_adm(svn_wc__db_t
 {
   const svn_wc_entry_t *entry;
   int format;
+  const char *repos_relpath;
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
+  SVN_ERR_ASSERT(url != NULL);
   SVN_ERR_ASSERT(repos_root_url != NULL);
   SVN_ERR_ASSERT(repos_uuid != NULL);
+  SVN_ERR_ASSERT(svn_uri_is_ancestor(repos_root_url, url));
 
   SVN_ERR(svn_wc__internal_check_wc(&format, db, local_abspath, scratch_pool));
 
+  repos_relpath = svn_uri_is_child(repos_root_url, url, scratch_pool);
+  if (repos_relpath == NULL)
+    repos_relpath = "";
+  else
+    repos_relpath = svn_path_uri_decode(repos_relpath, scratch_pool);
+
   /* Early out: we know we're not dealing with an existing wc, so
      just create one. */
   if (format == 0)
-    return init_adm(db, local_abspath, url, repos_root_url, repos_uuid,
-                    revision, depth, scratch_pool);
+    return svn_error_return(init_adm(db, local_abspath,
+                                     repos_relpath, repos_root_url, repos_uuid,
+                                     revision, depth, scratch_pool));
 
   /* Now, get the existing url and repos for PATH. */
   SVN_ERR(svn_wc__get_entry(&entry, db, local_abspath, FALSE, svn_node_unknown,
@@ -521,10 +846,10 @@ svn_wc__internal_ensure_adm(svn_wc__db_t
     {
       if (entry->revision != revision)
         return
-          svn_error_createf
-          (SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL,
-           _("Revision %ld doesn't match existing revision %ld in '%s'"),
-           revision, entry->revision, local_abspath);
+          svn_error_createf(SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL,
+                            _("Revision %ld doesn't match existing "
+                              "revision %ld in '%s'"),
+                            revision, entry->revision, local_abspath);
 
       /* The caller gives us a URL which should match the entry. However,
          some callers compensate for an old problem in entry->url and pass
@@ -539,10 +864,10 @@ svn_wc__internal_ensure_adm(svn_wc__db_t
               || strcmp(entry->uuid, repos_uuid) != 0))
         {
           return
-            svn_error_createf
-            (SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL,
-             _("URL '%s' doesn't match existing URL '%s' in '%s'"),
-             url, entry->url, local_abspath);
+            svn_error_createf(SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL,
+                              _("URL '%s' doesn't match existing "
+                                "URL '%s' in '%s'"),
+                              url, entry->url, local_abspath);
         }
     }
 
@@ -603,7 +928,7 @@ svn_wc__adm_cleanup_tmp_area(svn_wc__db_
   SVN_ERR(svn_io_remove_dir2(tmp_path, TRUE, NULL, NULL, scratch_pool));
 
   /* Now, rebuild the tmp area. */
-  return init_adm_tmp_area(adm_abspath, scratch_pool);
+  return svn_error_return(init_adm_tmp_area(adm_abspath, scratch_pool));
 }
 
 
@@ -615,12 +940,26 @@ svn_wc_create_tmp_file2(apr_file_t **fp,
                         svn_io_file_del_t delete_when,
                         apr_pool_t *pool)
 {
+  svn_wc__db_t *db;
+  const char *local_abspath;
   const char *temp_dir;
   apr_file_t *file;
+  svn_error_t *err;
 
   SVN_ERR_ASSERT(fp || new_name);
 
-  temp_dir = svn_wc__adm_child(path, SVN_WC__ADM_TMP, pool);
+  SVN_ERR(svn_wc__db_open(&db, svn_wc__db_openmode_readonly,
+                          NULL /* config */,
+                          TRUE /* auto_upgrade */,
+                          TRUE /* enforce_empty_wq */,
+                          pool, pool));
+
+  SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
+  err = svn_wc__db_temp_wcroot_tempdir(&temp_dir, db, local_abspath,
+                                       pool, pool);
+  err = svn_error_compose_create(err, svn_wc__db_close(db));
+  if (err)
+    return svn_error_return(err);
 
   SVN_ERR(svn_io_open_unique_file3(&file, new_name, temp_dir,
                                    delete_when, pool, pool));
@@ -632,3 +971,13 @@ svn_wc_create_tmp_file2(apr_file_t **fp,
 
   return SVN_NO_ERROR;
 }
+
+
+const char *
+svn_wc__nonexistent_path(svn_wc__db_t *db,
+                         const char *adm_abspath,
+                         apr_pool_t *scratch_pool)
+{
+  return svn_wc__adm_child(adm_abspath, SVN_WC__ADM_NONEXISTENT_PATH,
+                           scratch_pool);
+}

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/adm_files.h
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/adm_files.h?rev=984206&r1=984205&r2=984206&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/adm_files.h (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_wc/adm_files.h Tue Aug 10 20:55:56 2010
@@ -48,31 +48,56 @@ const char *svn_wc__adm_child(const char
                               apr_pool_t *result_pool);
 
 /* Return TRUE if the administrative area exists for this directory. */
-svn_boolean_t svn_wc__adm_area_exists(const svn_wc_adm_access_t *adm_access,
+svn_boolean_t svn_wc__adm_area_exists(const char *adm_abspath,
                                       apr_pool_t *pool);
 
 
+#ifndef SVN_EXPERIMENTAL_PRISTINE
 /* Atomically rename a temporary text-base file TMP_TEXT_BASE_ABSPATH to its
-   canonical location.  LOCAL_ABSPATH is the path of the working file whose
+   canonical location.  LOCAL_ABSPATH in DB is the working file whose
    text-base is to be moved.  The tmp file should be closed already. */
 svn_error_t *
-svn_wc__sync_text_base(const char *local_abspath,
+svn_wc__sync_text_base(svn_wc__db_t *db,
+                       const char *local_abspath,
                        const char *tmp_text_base_path,
-                       apr_pool_t *pool);
+                       apr_pool_t *scratch_pool);
+#endif
 
 
-/* Set *RESULT_ABSPATH to the absolute path to LOCAL_ABSPATH's text-base file,
-   or, if TMP is set, to its temporary text-base file. */
+#ifndef SVN_EXPERIMENTAL_PRISTINE
+/* Set *RESULT_ABSPATH to the absolute path to where LOCAL_ABSPATH's
+   "normal text-base" file is or should be created.  The file does not
+   necessarily exist.
+
+   "Normal text-base" means the base of the copied file, if copied or moved,
+   else nothing if it's a simple add (even if replacing an existing node),
+   else the ultimate base. */
 svn_error_t *
 svn_wc__text_base_path(const char **result_abspath,
                        svn_wc__db_t *db,
                        const char *local_abspath,
-                       svn_boolean_t tmp,
                        apr_pool_t *pool);
+#endif
 
-/* Set *CONTENTS to a readonly stream on the LOCAL_ABSPATH's base file.
- * For more detail, please see the description of
- * svn_wc_get_pristine_contents2().*/
+/* Set *RESULT_ABSPATH to the deterministic absolute path to where
+   LOCAL_ABSPATH's temporary text-base file is or should be created. */
+svn_error_t *
+svn_wc__text_base_deterministic_tmp_path(const char **result_abspath,
+                                         svn_wc__db_t *db,
+                                         const char *local_abspath,
+                                         apr_pool_t *pool);
+
+/* Set *CONTENTS to a readonly stream on the pristine text of the working
+ * version of the file LOCAL_ABSPATH in DB.  If the file is locally copied
+ * or moved to this path, this means the pristine text of the copy source,
+ * even if the file replaces a previously existing base node at this path.
+ *
+ * Set *CONTENTS to NULL if there is no pristine text because the file is
+ * locally added (even if it replaces an existing base node).  Return an
+ * error if there is no pristine text for any other reason.
+ *
+ * For more detail, see the description of svn_wc_get_pristine_contents2().
+ */
 svn_error_t *
 svn_wc__get_pristine_contents(svn_stream_t **contents,
                               svn_wc__db_t *db,
@@ -81,22 +106,33 @@ svn_wc__get_pristine_contents(svn_stream
                               apr_pool_t *scratch_pool);
 
 
-
-/* Set *CONTENTS to a readonly stream on the LOCAL_ABSPATH's revert file. */
-svn_error_t *
-svn_wc__get_revert_contents(svn_stream_t **contents,
-                            svn_wc__db_t *db,
-                            const char *local_abspath,
-                            apr_pool_t *result_pool,
-                            apr_pool_t *scratch_pool);
+/* Set *CONTENTS to a readonly stream on the pristine text of the base
+ * version of LOCAL_ABSPATH in DB.  If LOCAL_ABSPATH is locally replaced,
+ * this is distinct from svn_wc__get_pristine_contents(), otherwise it is
+ * the same.
+ *
+ * (In WC-1 terminology, this was known as "the revert base" if the node is
+ * replaced by a copy, otherwise simply as "the base".)
+ *
+ * If the base version of LOCAL_ABSPATH is not present (e.g. because the
+ * file is locally added), set *CONTENTS to NULL.
+ * The base version of LOCAL_ABSPATH must be a file. */
+svn_error_t *
+svn_wc__get_ultimate_base_contents(svn_stream_t **contents,
+                                   svn_wc__db_t *db,
+                                   const char *local_abspath,
+                                   apr_pool_t *result_pool,
+                                   apr_pool_t *scratch_pool);
 
 
+#ifndef SVN_EXPERIMENTAL_PRISTINE
 /* Set *RESULT_ABSPATH to the absolute path to LOCAL_ABSPATH's revert file. */
 svn_error_t *
 svn_wc__text_revert_path(const char **result_abspath,
                          svn_wc__db_t *db,
                          const char *local_abspath,
                          apr_pool_t *pool);
+#endif
 
 /* Set *PROP_PATH to PATH's PROPS_KIND properties file.
    PATH can be a directory or file, and even have changed w.r.t. the
@@ -108,6 +144,93 @@ svn_error_t *svn_wc__prop_path(const cha
                                svn_wc__props_kind_t props_kind,
                                apr_pool_t *pool);
 
+/* Set *RESULT_ABSPATH to the absolute path to a readable file containing
+   the WC-1 "normal text-base" of LOCAL_ABSPATH in DB.
+
+   "Normal text-base" means the same as in svn_wc__text_base_path().
+   ### May want to check the callers' exact requirements and replace this
+       definition with something easier to comprehend.
+
+   What the callers want:
+     A path to a file that will remain available and unchanged as long as
+     the caller wants it - such as for the lifetime of RESULT_POOL.
+
+   What the current implementation provides:
+     A path to the file in the pristine store.  This file will be removed or
+     replaced the next time this or another Subversion client updates the WC.
+
+   If the node LOCAL_ABSPATH has no such pristine text, return an error of
+   type SVN_ERR_WC_PATH_UNEXPECTED_STATUS.
+
+   Allocate *RESULT_PATH in RESULT_POOL.  */
+svn_error_t *
+svn_wc__text_base_path_to_read(const char **result_abspath,
+                               svn_wc__db_t *db,
+                               const char *local_abspath,
+                               apr_pool_t *result_pool,
+                               apr_pool_t *scratch_pool);
+
+/* Set *FINFO to the status of the pristine text of LOCAL_ABSPATH in DB.
+   Only the following fields are guaranteed to be set:
+     APR_FINFO_TYPE
+     APR_FINFO_SIZE
+     APR_FINFO_MTIME
+ */
+svn_error_t *
+svn_wc__get_pristine_text_status(apr_finfo_t *finfo,
+                                 svn_wc__db_t *db,
+                                 const char *local_abspath,
+                                 apr_pool_t *result_pool,
+                                 apr_pool_t *scratch_pool);
+
+#ifndef SVN_EXPERIMENTAL_PRISTINE
+/* Set *RESULT_ABSPATH to the path of the WC-1 "revert-base" text of the
+   versioned file LOCAL_ABSPATH in DB.
+
+   If the node LOCAL_ABSPATH has no such pristine text, return an error of
+   type SVN_ERR_WC_PATH_UNEXPECTED_STATUS.  */
+svn_error_t *
+svn_wc__text_revert_path_to_read(const char **result_abspath,
+                                 svn_wc__db_t *db,
+                                 const char *local_abspath,
+                                 apr_pool_t *result_pool);
+#endif
+
+/* Set *RESULT_ABSPATH to the path of the ultimate base text of the
+   versioned file LOCAL_ABSPATH in DB.  In WC-1 terms this means the
+   "normal text-base" or, if the node is replaced by a copy or move, the
+   "revert-base".  */
+svn_error_t *
+svn_wc__ultimate_base_text_path(const char **result_abspath,
+                                svn_wc__db_t *db,
+                                const char *local_abspath,
+                                apr_pool_t *result_pool,
+                                apr_pool_t *scratch_pool);
+
+/* Set *RESULT_ABSPATH to the path of the ultimate base text of the
+   versioned file LOCAL_ABSPATH in DB.  In WC-1 terms this means the
+   "normal text-base" or, if the node is replaced by a copy or move, the
+   "revert-base".
+
+   If the node LOCAL_ABSPATH has no such pristine text, return an error of
+   type SVN_ERR_WC_PATH_UNEXPECTED_STATUS.  */
+svn_error_t *
+svn_wc__ultimate_base_text_path_to_read(const char **result_abspath,
+                                        svn_wc__db_t *db,
+                                        const char *local_abspath,
+                                        apr_pool_t *result_pool,
+                                        apr_pool_t *scratch_pool);
+
+/* Set *MD5_CHECKSUM to the MD-5 checksum of the BASE_NODE pristine text
+ * of LOCAL_ABSPATH in DB, or to NULL if it has no BASE_NODE.
+ * Allocate *MD5_CHECKSUM in RESULT_POOL. */
+svn_error_t *
+svn_wc__get_ultimate_base_md5_checksum(const svn_checksum_t **md5_checksum,
+                                       svn_wc__db_t *db,
+                                       const char *local_abspath,
+                                       apr_pool_t *result_pool,
+                                       apr_pool_t *scratch_pool);
+
 
 
 /*** Opening all kinds of adm files ***/
@@ -123,12 +246,21 @@ svn_error_t *svn_wc__open_adm_stream(svn
 /* Open a writable stream to a temporary (normal or revert) text base,
    associated with the versioned file LOCAL_ABSPATH in DB.  Set *STREAM to
    the opened stream and *TEMP_BASE_ABSPATH to the path to the temporary
-   file, both allocated in RESULT_POOL.  The temporary file will have an
-   arbitrary unique name, in contrast to the deterministic name that
-   svn_wc__text_base_path(tmp=TRUE) returns. */
+   file.  The temporary file will have an arbitrary unique name, in contrast
+   to the deterministic name that svn_wc__text_base_deterministic_tmp_path()
+   returns.
+
+   Arrange that, on stream closure, *MD5_CHECKSUM and *SHA1_CHECKSUM will be
+   set to the MD-5 and SHA-1 checksums respectively of that file.
+   MD5_CHECKSUM and/or SHA1_CHECKSUM may be NULL if not wanted.
+
+   Allocate the new stream, path and checksums in RESULT_POOL.
+ */
 svn_error_t *
 svn_wc__open_writable_base(svn_stream_t **stream,
                            const char **temp_base_abspath,
+                           svn_checksum_t **md5_checksum,
+                           svn_checksum_t **sha1_checksum,
                            svn_wc__db_t *db,
                            const char *local_abspath,
                            apr_pool_t *result_pool,
@@ -149,6 +281,14 @@ svn_wc__adm_cleanup_tmp_area(svn_wc__db_
                              apr_pool_t *scratch_pool);
 
 
+/* Return a path where nothing exists on disk, within the admin directory
+   belonging to the versioned directory ADM_ABSPATH in DB. */
+const char *
+svn_wc__nonexistent_path(svn_wc__db_t *db,
+                         const char *adm_abspath,
+                         apr_pool_t *scratch_pool);
+
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */