[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

Re: Subversion AppleDouble patch

From: Matt Slot <fprefect_at_ambrosiasw.com>
Date: Tue, 12 Aug 2008 02:24:42 -0400

I've enclosed the latest diff that adds AppleDouble support to 1.5.1,
applying many of the suggestions posted earlier. Some notes and
questions regarding the patch:

  -- The patch now responds to SVN_HAVE_APPLEDOUBLE instead of DARWIN,
but I'm leery of touching the configure script to make it recognize
the platform and enable the feature.

  -- I've replaced the controversial "applefile.h" with a rewritten-
from-scratch interface file "svn_applefile.h" that uses standard APR
types. This should avoid any legal issues with the header from the RFC.

  -- It was necessary to add a parameter to install_committed_file()
in libsvn_wc/log.c, but I'm not sure that conditionally changing a
function declaration is necessarily the best way to go. Is there a
preferred way to conditionalize this?

  -- I based my patch on the implementation of svn:executable auto-
property, which does not recognize when the executable bit is changed
in the working copy. I worked around this in my original patch by
posting a script to "bang" the property flag when the user modifies
the resource file, but I'd prefer that svn recognize these
modifications and flag the property accordingly.

Thanks!

Matt Slot / Bitwise Operator / Ambrosia Software, Inc. -- http://www.AmbrosiaSW.com/

-----

diff -ruN subversion-1.5.1/subversion/include/svn_applefile.h
subversion-appledouble-1.5.1/subversion/include/svn_applefile.h
--- subversion-1.5.1/subversion/include/svn_applefile.h 1969-12-31
19:00:00.000000000 -0500
+++ subversion-appledouble-1.5.1/subversion/include/svn_applefile.h
2008-08-12 00:45:31.000000000 -0400
@@ -0,0 +1,121 @@
+/**
+ * @copyright
+ * ====================================================================
+ * Copyright (c) 2008 CollabNet. All rights reserved.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://subversion.tigris.org/license-1.html.
+ * If newer versions of this license are posted there, you may use a
+ * newer version instead, at your option.
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals. For exact contribution history, see the revision
+ * history and logs, available at http://subversion.tigris.org/.
+ * ====================================================================
+ * @endcopyright
+ *
+ * @file svn_applefile.h
+ * @brief AppleDouble declarations based on RFC 1740, standard MacOS
types
+ */
+
+/*
==================================================================== */
+
+#ifndef SVN_APPLEFILE_H
+#define SVN_APPLEFILE_H
+
+#include <sys/attr.h>
+#include <sys/paths.h>
+#include <sys/stat.h>
+
+#include "apr.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#define APPLEFILE_MAGIC_NUMBER 0x00051607 /* AppleDouble */
+#define APPLEFILE_VERSION_NUMBER 0x00020000
+#define APPLEFILE_HEADER_BYTES 26 /* Without padding */
+
+#define APPLEFILE_ENTRY_DATA_FORK 1
+#define APPLEFILE_ENTRY_RSRC_FORK 2
+#define APPLEFILE_ENTRY_FINDER_INFO 9
+
+/** Portable declaration of MacOS OSType. */
+typedef apr_uint32_t OSType;
+
+/** Portable declaration of MacOS QuickDraw Point. */
+typedef struct Point
+{
+ apr_int16_t h;
+ apr_int16_t v;
+} Point;
+
+/** Portable declaration of MacOS standard Finder flags. */
+typedef struct FInfo
+{
+ OSType fdType;
+ OSType fdCreator;
+ apr_uint16_t fdFlags;
+ Point fdLocation;
+ apr_int16_t fdFldr;
+} FInfo;
+
+/** Portable declaration of MacOS extended Finder flags. */
+typedef struct FXInfo
+{
+ apr_int16_t fdIconID;
+ apr_int16_t fdUnused[3];
+ apr_byte_t fdScript;
+ apr_byte_t fdXFlags;
+ apr_int16_t fdComment;
+ apr_int32_t fdPutAway;
+} FXInfo;
+
+/** Portable declaration of MacOS combined Finder flags. */
+typedef struct FinderInfo
+{
+ FInfo ioFlFndrInfo;
+ FXInfo ioFlXFndrInfo;
+} FinderInfo;
+
+
+/** File header for AppleSingle and AppleDouble format. */
+typedef struct AppleFileHeader
+{
+ apr_uint32_t magicNum;
+ apr_uint32_t versionNum;
+ apr_byte_t filler[16];
+ apr_uint16_t numEntries;
+} AppleFileHeader;
+
+/** Single entry for AppleSingle or AppleDouble format. */
+typedef struct AppleFileEntry
+{
+ apr_uint32_t entryID;
+ apr_uint32_t entryOffset;
+ apr_uint32_t entryLength;
+} AppleFileEntry;
+
+
+/** Format of data returned by getattrlist(ATTR_CMN_FNDRINFO). */
+typedef struct finder_info_attr
+{
+ apr_uint32_t attr_length;
+ FinderInfo finder_info;
+} finder_info_attr;
+
+/** Format of data returned by getattrlist(ATTR_FILE_RSRCLENGTH). */
+typedef struct resource_fork_attr
+{
+ apr_uint32_t attr_length;
+ apr_off_t fork_length;
+} resource_fork_attr;
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* SVN_APPLEFILE_H */
diff -ruN subversion-1.5.1/subversion/include/svn_io.h subversion-
appledouble-1.5.1/subversion/include/svn_io.h
--- subversion-1.5.1/subversion/include/svn_io.h 2008-06-11
01:26:41.000000000 -0400
+++ subversion-appledouble-1.5.1/subversion/include/svn_io.h
2008-08-11 04:20:51.000000000 -0400
@@ -394,6 +394,25 @@
                                         apr_pool_t *pool);

+#if SVN_HAVE_APPLEDOUBLE
+/** Manage HFS metadata by storing it as an AppleDouble encoded
property.
+ *
+ * @a path is the utf8-encoded path to the file. If @a appledouble
+ * is non-empty, then apply the indicated metadata. If empty, remove
+ * any HFS metadata and the resource fork from the file.
+ */
+svn_error_t *svn_io_set_appledouble_data(const char *path,
+ const svn_string_t
*appledouble,
+ svn_boolean_t ignore_enoent,
+ apr_pool_t *pool);
+
+/** Enocde the HFS metadata into an binary property.
+ */
+svn_error_t *svn_io_get_appledouble_data(svn_string_t **appledouble,
+ const char *path,
+ apr_pool_t *pool);
+#endif
+
  /** Read a line from @a file into @a buf, but not exceeding @a
*limit bytes.
   * Does not include newline, instead '\\0' is put there.
   * Length (as in strlen) is returned in @a *limit.
diff -ruN subversion-1.5.1/subversion/include/svn_props.h subversion-
appledouble-1.5.1/subversion/include/svn_props.h
--- subversion-1.5.1/subversion/include/svn_props.h 2008-05-21
17:24:24.000000000 -0400
+++ subversion-appledouble-1.5.1/subversion/include/svn_props.h
2008-08-11 04:25:44.000000000 -0400
@@ -254,6 +254,9 @@
   */
  #define SVN_PROP_EXECUTABLE_VALUE SVN_PROP_BOOLEAN_TRUE

+/** Contains any HFS metadata in AppleDouble format. */
+#define SVN_PROP_APPLEDOUBLE "file:appledouble"
+
  /** Set to TRUE ('*') if we want a file to be set to read-only when
   * not locked. FALSE is indicated by deleting the property. */
  #define SVN_PROP_NEEDS_LOCK SVN_PROP_PREFIX "needs-lock"
diff -ruN subversion-1.5.1/subversion/libsvn_client/add.c subversion-
appledouble-1.5.1/subversion/libsvn_client/add.c
--- subversion-1.5.1/subversion/libsvn_client/add.c 2008-05-21
17:24:24.000000000 -0400
+++ subversion-appledouble-1.5.1/subversion/libsvn_client/add.c
2008-08-11 02:26:49.000000000 -0400
@@ -153,6 +153,9 @@
    svn_config_t *cfg;
    svn_boolean_t use_autoprops;
    auto_props_baton_t autoprops;
+#ifdef SVN_HAVE_APPLEDOUBLE
+ svn_string_t *appledouble;
+#endif

    /* initialisation */
    autoprops.properties = apr_hash_make(pool);
@@ -202,6 +205,14 @@
      }
  #endif

+#ifdef SVN_HAVE_APPLEDOUBLE
+ /* load any appledouble data for the indicated file */
+ SVN_ERR(svn_io_get_appledouble_data(&appledouble, path, pool));
+ if (appledouble)
+ apr_hash_set(autoprops.properties, SVN_PROP_APPLEDOUBLE,
+ strlen (SVN_PROP_APPLEDOUBLE), appledouble);
+#endif
+
    *mimetype = autoprops.mimetype;
    return SVN_NO_ERROR;
  }
diff -ruN subversion-1.5.1/subversion/libsvn_client/export.c
subversion-appledouble-1.5.1/subversion/libsvn_client/export.c
--- subversion-1.5.1/subversion/libsvn_client/export.c 2008-04-07
05:22:45.000000000 -0400
+++ subversion-appledouble-1.5.1/subversion/libsvn_client/export.c
2008-08-11 05:22:52.000000000 -0400
@@ -104,6 +104,9 @@
    apr_hash_t *props;
    const char *base;
    svn_string_t *eol_style, *keywords, *executable, *externals,
*special;
+#ifdef SVN_HAVE_APPLEDOUBLE
+ svn_string_t *appledouble;
+#endif
    const char *eol = NULL;
    svn_boolean_t local_mod = FALSE;
    apr_time_t tm;
@@ -149,6 +152,10 @@
                            APR_HASH_KEY_STRING);
    executable = apr_hash_get(props, SVN_PROP_EXECUTABLE,
                              APR_HASH_KEY_STRING);
+#ifdef SVN_HAVE_APPLEDOUBLE
+ appledouble = apr_hash_get(props, SVN_PROP_APPLEDOUBLE,
+ APR_HASH_KEY_STRING);
+#endif
    externals = apr_hash_get(props, SVN_PROP_EXTERNALS,
                             APR_HASH_KEY_STRING);
    special = apr_hash_get(props, SVN_PROP_SPECIAL,
@@ -202,6 +209,11 @@
      SVN_ERR(svn_io_set_file_executable(to, TRUE,
                                         FALSE, pool));

+#ifdef SVN_HAVE_APPLEDOUBLE
+ if (appledouble)
+ SVN_ERR(svn_io_set_appledouble_data(to, appledouble, FALSE, pool));
+#endif
+
    if (! special)
      SVN_ERR(svn_io_set_file_affected_time(tm, to, pool));

@@ -469,6 +481,9 @@
    const svn_string_t *eol_style_val;
    const svn_string_t *keywords_val;
    const svn_string_t *executable_val;
+#ifdef SVN_HAVE_APPLEDOUBLE
+ const svn_string_t *appledouble_val;
+#endif
    svn_boolean_t special;

    /* Any keyword vals to be substituted */
@@ -665,6 +680,11 @@
    else if (strcmp(name, SVN_PROP_EXECUTABLE) == 0)
      fb->executable_val = svn_string_dup(value, fb->pool);

+#ifdef SVN_HAVE_APPLEDOUBLE
+ else if (strcmp(name, SVN_PROP_APPLEDOUBLE) == 0)
+ fb->appledouble_val = svn_string_dup(value, fb->pool);
+#endif
+
    /* Try to fill out the baton's keywords-structure too. */
    else if (strcmp(name, SVN_PROP_ENTRY_COMMITTED_REV) == 0)
      fb->revision = apr_pstrdup(fb->pool, value->data);
@@ -762,6 +782,12 @@
    if (fb->executable_val)
      SVN_ERR(svn_io_set_file_executable(fb->path, TRUE, FALSE, pool));

+#ifdef SVN_HAVE_APPLEDOUBLE
+ if (fb->appledouble_val)
+ SVN_ERR (svn_io_set_appledouble_data(fb->path, fb->appledouble_val,
+ FALSE, pool));
+#endif
+
    if (fb->date && (! fb->special))
      SVN_ERR(svn_io_set_file_affected_time(fb->date, fb->path, pool));

diff -ruN subversion-1.5.1/subversion/libsvn_subr/io.c subversion-
appledouble-1.5.1/subversion/libsvn_subr/io.c
--- subversion-1.5.1/subversion/libsvn_subr/io.c 2008-05-03
09:30:01.000000000 -0400
+++ subversion-appledouble-1.5.1/subversion/libsvn_subr/io.c
2008-08-12 00:47:54.000000000 -0400
@@ -52,7 +52,8 @@
  #include "svn_utf.h"
  #include "svn_config.h"
  #include "svn_private_config.h"
-
+#include "svn_applefile.h"
+
  /*
    Windows is 'aided' by a number of types of applications that
    follow other applications around and open up files they have
@@ -1476,6 +1477,248 @@
    return SVN_NO_ERROR;
  }

+#ifdef SVN_HAVE_APPLEDOUBLE
+
+svn_error_t *
+svn_io_set_appledouble_data(const char *path,
+ const svn_string_t *appledouble,
+ svn_boolean_t ignore_enoent,
+ apr_pool_t *pool)
+{
+ apr_status_t status;
+ unsigned char *data = NULL;
+ size_t length, offset;
+ size_t bytes_written;
+ struct AppleFileHeader header;
+ struct AppleFileEntry entry;
+ finder_info_attr fi_attr;
+ int finder_info_valid = 0;
+ unsigned char *resource_data = NULL;
+ size_t resource_length = 0;
+ struct attrlist attrs;
+ const char *path_apr;
+ int i, result;
+
+ if ((appledouble != NULL) && (appledouble->len != 0))
+ {
+ data = (unsigned char *) appledouble->data;
+ length = appledouble->len;
+ offset = 0;
+
+ if (length < APPLEFILE_HEADER_BYTES)
+ return svn_error_create(SVN_ERR_INCOMPLETE_DATA, NULL,
+ _("Incomplete AppleDouble encoding"));
+
+ memcpy(&header, data + offset, APPLEFILE_HEADER_BYTES);
+ offset += APPLEFILE_HEADER_BYTES;
+ header.magicNum = ntohl(header.magicNum);
+ header.versionNum = ntohl(header.versionNum);
+ header.numEntries = ntohs(header.numEntries);
+
+ if (header.magicNum != APPLEFILE_MAGIC_NUMBER)
+ return svn_error_create(SVN_ERR_MALFORMED_FILE, NULL,
+ _("Malformed AppleDouble encoding"));
+
+ for(i = 0; i< header.numEntries; i++)
+ {
+ if (offset + sizeof(entry) > length)
+ return svn_error_create(SVN_ERR_INCOMPLETE_DATA, NULL,
+ _("Incomplete AppleDouble encoding"));
+ memcpy(&entry, data + offset, sizeof(entry));
+ offset += sizeof(entry);
+ entry.entryID = ntohl(entry.entryID);
+ entry.entryOffset = ntohl(entry.entryOffset);
+ entry.entryLength = ntohl(entry.entryLength);
+
+ if (entry.entryID == 0)
+ return svn_error_create(SVN_ERR_MALFORMED_FILE, NULL,
+ _("Malformed AppleDouble encoding"));
+ if (entry.entryLength)
+ {
+ if (entry.entryOffset > length)
+ return svn_error_create(SVN_ERR_INCOMPLETE_DATA, NULL,
+ _("Incomplete AppleDouble
encoding"));
+ if (entry.entryOffset + entry.entryLength > length)
+ return svn_error_create(SVN_ERR_INCOMPLETE_DATA, NULL,
+ _("Incomplete AppleDouble
encoding"));
+ if (entry.entryOffset < APPLEFILE_HEADER_BYTES +
+ header.numEntries * sizeof(AppleFileEntry))
+ return svn_error_create(SVN_ERR_MALFORMED_FILE, NULL,
+ _("Malformed AppleDouble encoding"));
+ }
+
+ switch(entry.entryID)
+ {
+ case APPLEFILE_ENTRY_RSRC_FORK:
+ resource_data = data + entry.entryOffset;
+ resource_length = entry.entryLength;
+ break;
+ case APPLEFILE_ENTRY_FINDER_INFO:
+ if (entry.entryLength != sizeof(fi_attr.finder_info))
+ return svn_error_create(SVN_ERR_MALFORMED_FILE, NULL,
+ _("Malformed AppleDouble
encoding"));
+ memcpy(&fi_attr.finder_info, data + entry.entryOffset,
+ sizeof(fi_attr.finder_info));
+ fi_attr.finder_info.ioFlXFndrInfo.fdIconID = htons(0);
+ fi_attr.finder_info.ioFlXFndrInfo.fdComment = htons(0);
+ fi_attr.finder_info.ioFlXFndrInfo.fdPutAway = htonl(0);
+ finder_info_valid = 1;
+ break;
+ default:
+ /* ignore */
+ break;
+ }
+ }
+
+ if (resource_length)
+ {
+ const char *resource_path;
+ apr_file_t *file;
+ apr_size_t bytes_written;
+ svn_error_t *err;
+
+ resource_path = svn_path_join_many(pool, path, "..namedfork",
"rsrc", NULL);
+ if (resource_path == NULL)
+ return svn_error_wrap_apr
+ (apr_get_os_error(), _("Can't create resource path"));
+
+ SVN_ERR(svn_io_file_open(&file, resource_path, APR_READ |
APR_WRITE,
+ APR_OS_DEFAULT, pool));
+ bytes_written = resource_length;
+ err = svn_io_file_write(file, resource_data,
+ &bytes_written, pool);
+ SVN_ERR(svn_io_file_flush_to_disk(file, pool));
+ SVN_ERR(svn_io_file_close(file, pool));
+ if (err && !APR_STATUS_IS_EOF(err->apr_err))
+ return err;
+ }
+
+ /* The FinderInfo struct is populated directly from the HFS volume,
so the
+ fields are already in network byte order. See the getattrlist
manpage. */
+
+ if (finder_info_valid)
+ {
+ SVN_ERR(svn_path_cstring_from_utf8(&path_apr, path, pool));
+
+ memset(&attrs, 0, sizeof(attrs));
+ attrs.bitmapcount = ATTR_BIT_MAP_COUNT;
+ attrs.commonattr = ATTR_CMN_FNDRINFO;
+ fi_attr.attr_length = sizeof(fi_attr.finder_info);
+ result = setattrlist(path_apr, &attrs, &fi_attr.finder_info,
+ sizeof(fi_attr.finder_info), 0);
+ if (result < 0)
+ return svn_error_wrap_apr
+ (apr_get_os_error(), _("Can't set file attributes"));
+ }
+ }
+
+ return SVN_NO_ERROR;
+}
+
+
+
+svn_error_t *
+svn_io_get_appledouble_data(svn_string_t **appledouble,
+ const char *path,
+ apr_pool_t *pool)
+{
+ int result = 0;
+ const char *path_apr;
+ unsigned char *data = NULL;
+ size_t total_header;
+ struct AppleFileHeader header;
+ struct AppleFileEntry entries[2];
+ struct attrlist attrs;
+ finder_info_attr fi_attr;
+ resource_fork_attr rf_attr;
+
+ *appledouble = NULL;
+
+ SVN_ERR(svn_path_cstring_from_utf8(&path_apr, path, pool));
+
+ memset(&attrs, 0, sizeof(attrs));
+ memset(&fi_attr, 0, sizeof(fi_attr));
+ attrs.bitmapcount = ATTR_BIT_MAP_COUNT;
+ attrs.commonattr = ATTR_CMN_FNDRINFO;
+ fi_attr.attr_length = sizeof(fi_attr.finder_info);
+ result = getattrlist(path_apr, &attrs, &fi_attr, sizeof(fi_attr), 0);
+ if (result < 0)
+ return svn_error_wrap_apr
+ (apr_get_os_error(), _("Can't get file attributes"));
+
+ memset(&attrs, 0, sizeof(attrs));
+ attrs.bitmapcount = ATTR_BIT_MAP_COUNT;
+ attrs.fileattr = ATTR_FILE_RSRCLENGTH;
+ result = getattrlist(path_apr, &attrs, &rf_attr, sizeof(rf_attr), 0);
+ if (result < 0)
+ return svn_error_wrap_apr
+ (apr_get_os_error(), _("Can't get file attributes"));
+
+ if (!rf_attr.fork_length &&
+ !fi_attr.finder_info.ioFlFndrInfo.fdType &&
+ !fi_attr.finder_info.ioFlFndrInfo.fdCreator &&
+ !fi_attr.finder_info.ioFlFndrInfo.fdFlags)
+ return SVN_NO_ERROR;
+
+ total_header = APPLEFILE_HEADER_BYTES +
+ sizeof(entries) + sizeof(fi_attr.finder_info);
+ data = (unsigned char *) apr_palloc(pool,
+ total_header + rf_attr.fork_length);
+
+ memset(&header, 0, APPLEFILE_HEADER_BYTES);
+ header.magicNum = htonl(APPLEFILE_MAGIC_NUMBER);
+ header.versionNum = htonl(APPLEFILE_VERSION_NUMBER);
+ header.numEntries = htons(2);
+
+ entries[0].entryID = htonl(APPLEFILE_ENTRY_FINDER_INFO);
+ entries[0].entryOffset = htonl(APPLEFILE_HEADER_BYTES +
sizeof(entries));
+ entries[0].entryLength = htonl(sizeof(FinderInfo));
+ entries[1].entryID = htonl(APPLEFILE_ENTRY_RSRC_FORK);
+ entries[1].entryOffset = htonl(total_header);
+ entries[1].entryLength = htonl(rf_attr.fork_length);
+
+ memcpy(data + 0, &header, APPLEFILE_HEADER_BYTES);
+ memcpy(data + APPLEFILE_HEADER_BYTES, entries, sizeof(entries));
+
+
+ /* The FinderInfo struct is populated directly from the HFS volume,
so the
+ fields are already in network byte order. See the getattrlist
manpage. */
+
+ memcpy(data + APPLEFILE_HEADER_BYTES + sizeof(entries),
+ &fi_attr.finder_info, sizeof(fi_attr.finder_info));
+
+ if (rf_attr.fork_length)
+ {
+ const char *resource_path;
+ apr_file_t *file;
+ apr_size_t bytes_read;
+ svn_error_t *err;
+
+ resource_path = svn_path_join_many(pool, path, "..namedfork",
"rsrc", NULL);
+ if (resource_path == NULL)
+ return svn_error_wrap_apr
+ (apr_get_os_error(), _("Can't create resource path"));
+
+ SVN_ERR(svn_io_file_open(&file, resource_path, APR_READ,
+ APR_OS_DEFAULT, pool));
+ bytes_read = rf_attr.fork_length;
+ err = svn_io_file_read(file, data + total_header, &bytes_read,
pool);
+ SVN_ERR(svn_io_file_close(file, pool));
+ if (err && !APR_STATUS_IS_EOF(err->apr_err))
+ return err;
+ if (bytes_read != rf_attr.fork_length)
+ return svn_error_create(SVN_ERR_INCOMPLETE_DATA, NULL,
+ _("Incomplete AppleDouble encoding"));
+ }
+
+ *appledouble = svn_string_ncreate(data, total_header +
+ rf_attr.fork_length, pool);
+
+ return SVN_NO_ERROR;
+}
+
+#endif
+
  
  /*** File locking. ***/
  /* Clear all outstanding locks on ARG, an open apr_file_t *. */
diff -ruN subversion-1.5.1/subversion/libsvn_wc/adm_crawler.c
subversion-appledouble-1.5.1/subversion/libsvn_wc/adm_crawler.c
--- subversion-1.5.1/subversion/libsvn_wc/adm_crawler.c 2007-10-14
17:11:29.000000000 -0400
+++ subversion-appledouble-1.5.1/subversion/libsvn_wc/adm_crawler.c
2008-08-11 05:22:52.000000000 -0400
@@ -86,6 +86,11 @@
    /* If necessary, tweak the new working file's executable bit. */
    SVN_ERR(svn_wc__maybe_set_executable(NULL, file_path, adm_access,
pool));

+#ifdef SVN_HAVE_APPLEDOUBLE
+ /* If supported on the platform, apply any AppleDouble shadow data */
+ SVN_ERR(svn_wc__maybe_set_appledouble(NULL, file_path, adm_access,
pool));
+#endif
+
    /* Remove any text conflict */
    SVN_ERR(svn_wc_resolved_conflict3(file_path, adm_access, TRUE,
FALSE,
                                      svn_depth_empty,
diff -ruN subversion-1.5.1/subversion/libsvn_wc/log.c subversion-
appledouble-1.5.1/subversion/libsvn_wc/log.c
--- subversion-1.5.1/subversion/libsvn_wc/log.c 2007-12-10
23:13:52.000000000 -0500
+++ subversion-appledouble-1.5.1/subversion/libsvn_wc/log.c 2008-08-11
05:22:52.000000000 -0400
@@ -107,6 +107,9 @@
     executable property is set. */
  #define SVN_WC__LOG_MAYBE_EXECUTABLE "maybe-executable"

+/* Apply the cached AppleDouble data to file SVN_WC__LOG_ATTR_NAME . */
+#define SVN_WC__LOG_MAYBE_APPLEDOUBLE "maybe-appledouble"
+
  /* Set SVN_WC__LOG_ATTR_NAME to have timestamp
SVN_WC__LOG_ATTR_TIMESTAMP. */
  #define SVN_WC__LOG_SET_TIMESTAMP "set-timestamp"

@@ -326,6 +329,11 @@
          SVN_ERR(svn_wc__maybe_set_executable(NULL, full_dest_path,
                                               adm_access, pool));

+#ifdef SVN_HAVE_APPLEDOUBLE
+ SVN_ERR(svn_wc__maybe_set_appledouble(NULL, full_dest_path,
+ adm_access, pool));
+#endif
+
          return SVN_NO_ERROR;
        }
      case svn_wc__xfer_cp_and_detranslate:
@@ -386,6 +394,9 @@
  install_committed_file(svn_boolean_t *overwrote_working,
                         svn_wc_adm_access_t *adm_access,
                         const char *name,
+#ifdef SVN_HAVE_APPLEDOUBLE
+ svn_boolean_t remove_appledouble,
+#endif
                         svn_boolean_t remove_executable,
                         svn_boolean_t remove_read_only,
                         apr_pool_t *pool)
@@ -491,6 +502,28 @@
          *overwrote_working = TRUE;
      }

+#ifdef SVN_HAVE_APPLEDOUBLE
+ if (remove_appledouble)
+ {
+ /* Update the appledouble data for the indicated file */
+ if (same)
+ SVN_ERR(svn_io_set_appledouble_data(filepath,
+ NULL, /* delete */
+ FALSE, pool));
+ *overwrote_working = TRUE; /* entry needs wc-file's timestamp */
+ }
+ else
+ {
+ /* Set the working file's appledouble data if props dictate. */
+ SVN_ERR(svn_wc__maybe_set_appledouble(&did_set, filepath,
+ adm_access, pool));
+ if (did_set)
+ /* okay, so we didn't -overwrite- the working file, but we
changed
+ its timestamp, which is the point of returning this
flag. :-) */
+ *overwrote_working = TRUE;
+ }
+#endif
+
    /* Install the new text base if one is waiting. */
    if (kind == svn_node_file) /* tmp_text_base exists */
      SVN_ERR(svn_wc__sync_text_base(filepath, pool));
@@ -664,6 +697,22 @@
    return SVN_NO_ERROR;
  }

+#ifdef SVN_HAVE_APPLEDOUBLE
+static svn_error_t *
+log_do_file_maybe_appledouble(struct log_runner *loggy,
+ const char *name)
+{
+ const char *full_path
+ = svn_path_join(svn_wc_adm_access_path(loggy->adm_access), name,
+ loggy->pool);
+
+ SVN_ERR(svn_wc__maybe_set_appledouble(NULL, full_path, loggy-
>adm_access,
+ loggy->pool));
+
+ return SVN_NO_ERROR;
+}
+#endif
+
  /* Maybe make file NAME in log's CWD readonly */
  static svn_error_t *
  log_do_file_maybe_readonly(struct log_runner *loggy,
@@ -1063,6 +1112,9 @@
    int is_this_dir = (strcmp(name, SVN_WC_ENTRY_THIS_DIR) == 0);
    const char *rev =
svn_xml_get_attr_value(SVN_WC__LOG_ATTR_REVISION, atts);
    svn_boolean_t wc_root, overwrote_working = FALSE,
remove_executable = FALSE;
+#ifdef SVN_HAVE_APPLEDOUBLE
+ svn_boolean_t remove_appledouble = FALSE;
+#endif
    svn_boolean_t set_read_write = FALSE;
    const char *full_path;
    const char *pdir, *base_name;
@@ -1251,6 +1303,11 @@
                if ((! strcmp(propchange->name, SVN_PROP_EXECUTABLE))
                    && (propchange->value == NULL))
                  remove_executable = TRUE;
+#if SVN_HAVE_APPLEDOUBLE
+ else if ((! strcmp(propchange->name,
SVN_PROP_APPLEDOUBLE))
+ && (propchange->value == NULL))
+ remove_appledouble = TRUE;
+#endif
                else if ((! strcmp(propchange->name,
SVN_PROP_NEEDS_LOCK))
                         && (propchange->value == NULL))
                  set_read_write = TRUE;
@@ -1275,6 +1332,9 @@

        if ((err = install_committed_file
             (&overwrote_working, loggy->adm_access, name,
+#if SVN_HAVE_APPLEDOUBLE
+ remove_appledouble,
+#endif
              remove_executable, set_read_write, pool)))
          return svn_error_createf
            (pick_error_code(loggy), err,
@@ -1574,6 +1634,11 @@
    else if (strcmp(eltname, SVN_WC__LOG_MAYBE_EXECUTABLE) == 0) {
      err = log_do_file_maybe_executable(loggy, name);
    }
+#if SVN_HAVE_APPLEDOUBLE
+ else if (strcmp(eltname, SVN_WC__LOG_MAYBE_APPLEDOUBLE) == 0) {
+ err = log_do_file_maybe_appledouble(loggy, name);
+ }
+#endif
    else if (strcmp(eltname, SVN_WC__LOG_SET_TIMESTAMP) == 0) {
      err = log_do_file_timestamp(loggy, name, atts);
    }
@@ -2297,6 +2362,25 @@
    return SVN_NO_ERROR;
  }

+#if SVN_HAVE_APPLEDOUBLE
+svn_error_t *
+svn_wc__loggy_maybe_set_appledouble(svn_stringbuf_t **log_accum,
+ svn_wc_adm_access_t *adm_access,
+ const char *path,
+ apr_pool_t *pool)
+{
+ svn_xml_make_open_tag(log_accum,
+ pool,
+ svn_xml_self_closing,
+ SVN_WC__LOG_MAYBE_APPLEDOUBLE,
+ SVN_WC__LOG_ATTR_NAME,
+ loggy_path(path, adm_access),
+ NULL);
+
+ return SVN_NO_ERROR;
+}
+#endif
+
  svn_error_t *
  svn_wc__loggy_maybe_set_readonly(svn_stringbuf_t **log_accum,
                                   svn_wc_adm_access_t *adm_access,
diff -ruN subversion-1.5.1/subversion/libsvn_wc/log.h subversion-
appledouble-1.5.1/subversion/libsvn_wc/log.h
--- subversion-1.5.1/subversion/libsvn_wc/log.h 2007-11-06
19:26:32.000000000 -0500
+++ subversion-appledouble-1.5.1/subversion/libsvn_wc/log.h 2008-08-11
05:22:52.000000000 -0400
@@ -199,6 +199,17 @@
                                     const char *path,
                                     apr_pool_t *pool);

+#if SVN_HAVE_APPLEDOUBLE
+/* Extend **LOG_ACCUM with log instructions to set the appledouble
+ properties for the file.
+*/
+svn_error_t *
+svn_wc__loggy_maybe_set_appledouble(svn_stringbuf_t **log_accum,
+ svn_wc_adm_access_t *adm_access,
+ const char *path,
+ apr_pool_t *pool);
+#endif
+
  /* Extend **LOG_ACCUM with log instructions to set permissions of PATH
     to 'readonly' if it has the 'needs-lock' property set and there is
     no lock for the file in the working copy.
diff -ruN subversion-1.5.1/subversion/libsvn_wc/merge.c subversion-
appledouble-1.5.1/subversion/libsvn_wc/merge.c
--- subversion-1.5.1/subversion/libsvn_wc/merge.c 2008-06-19
11:31:34.000000000 -0400
+++ subversion-appledouble-1.5.1/subversion/libsvn_wc/merge.c
2008-08-11 05:22:52.000000000 -0400
@@ -830,6 +830,12 @@
                                                   adm_access,
merge_target,
                                                   pool));

+#if SVN_HAVE_APPLEDOUBLE
+ SVN_ERR(svn_wc__loggy_maybe_set_appledouble(log_accum,
+ adm_access,
merge_target,
+ pool));
+#endif
+
        SVN_ERR(svn_wc__loggy_maybe_set_readonly(log_accum,
                                                  adm_access,
merge_target,
                                                  pool));
diff -ruN subversion-1.5.1/subversion/libsvn_wc/props.c subversion-
appledouble-1.5.1/subversion/libsvn_wc/props.c
--- subversion-1.5.1/subversion/libsvn_wc/props.c 2008-07-14
13:13:27.000000000 -0400
+++ subversion-appledouble-1.5.1/subversion/libsvn_wc/props.c
2008-08-11 05:22:52.000000000 -0400
@@ -2324,6 +2324,9 @@
                                    SVN_PROP_EXTERNALS,
                                    NULL };
    const char *dir_prohibit[] = { SVN_PROP_EXECUTABLE,
+#if SVN_HAVE_APPLEDOUBLE
+ SVN_PROP_APPLEDOUBLE,
+#endif
                                   SVN_PROP_KEYWORDS,
                                   SVN_PROP_EOL_STYLE,
                                   SVN_PROP_MIME_TYPE,
@@ -2512,6 +2515,15 @@
          SVN_ERR(svn_io_set_file_executable(path, TRUE, TRUE, pool));
      }

+#if SVN_HAVE_APPLEDOUBLE
+ if (entry->kind == svn_node_file && strcmp(name,
SVN_PROP_APPLEDOUBLE) == 0)
+ {
+ /* If the file:appledouble property exists, apply the HFS
metadata.
+ If the file:appledouble property was deleted, clear the
metadata. */
+ SVN_ERR(svn_io_set_appledouble_data (path, value, TRUE, pool));
+ }
+#endif
+
    if (entry->kind == svn_node_file && strcmp(name,
SVN_PROP_NEEDS_LOCK) == 0)
      {
        /* If the svn:needs-lock property was set to NULL, set the file
@@ -3431,6 +3443,9 @@
        const svn_prop_t *property = &APR_ARRAY_IDX(properties, i,
svn_prop_t);

        if (strcmp(property->name, SVN_PROP_EXECUTABLE) == 0
+#if SVN_HAVE_APPLEDOUBLE
+ || strcmp(property->name, SVN_PROP_APPLEDOUBLE) == 0
+#endif
            || strcmp(property->name, SVN_PROP_KEYWORDS) == 0
            || strcmp(property->name, SVN_PROP_EOL_STYLE) == 0
            || strcmp(property->name, SVN_PROP_SPECIAL) == 0
diff -ruN subversion-1.5.1/subversion/libsvn_wc/translate.c subversion-
appledouble-1.5.1/subversion/libsvn_wc/translate.c
--- subversion-1.5.1/subversion/libsvn_wc/translate.c 2007-12-27
15:42:46.000000000 -0500
+++ subversion-appledouble-1.5.1/subversion/libsvn_wc/translate.c
2008-08-11 05:22:50.000000000 -0400
@@ -322,6 +322,31 @@
  }

+#if SVN_HAVE_APPLEDOUBLE
+svn_error_t *
+svn_wc__maybe_set_appledouble (svn_boolean_t *did_set,
+ const char *path,
+ svn_wc_adm_access_t *adm_access,
+ apr_pool_t *pool)
+{
+ const svn_string_t *propval;
+ SVN_ERR(svn_wc_prop_get(&propval, SVN_PROP_APPLEDOUBLE, path,
adm_access,
+ pool));
+
+ if (propval != NULL)
+ {
+ SVN_ERR(svn_io_set_appledouble_data(path, propval, FALSE, pool));
+ if (did_set)
+ *did_set = TRUE;
+ }
+ else if (did_set)
+ *did_set = FALSE;
+
+ return SVN_NO_ERROR;
+}
+#endif
+
+
  svn_error_t *
  svn_wc__maybe_set_read_only(svn_boolean_t *did_set,
                              const char *path,
diff -ruN subversion-1.5.1/subversion/libsvn_wc/translate.h subversion-
appledouble-1.5.1/subversion/libsvn_wc/translate.h
--- subversion-1.5.1/subversion/libsvn_wc/translate.h 2006-02-15
16:30:49.000000000 -0500
+++ subversion-appledouble-1.5.1/subversion/libsvn_wc/translate.h
2008-08-11 05:22:45.000000000 -0400
@@ -103,6 +103,18 @@
                               svn_wc_adm_access_t *adm_access,
                               apr_pool_t *pool);

+#if SVN_HAVE_APPLEDOUBLE
+/* If the SVN_PROP_APPLEDOUBLE property is present at all, apply
+ the HFS metadata. If DID_SET is non-null, then set *DID_SET to
+ TRUE if did apply HFS metadata, or to FALSE if not. ADM_ACCESS
+ is an access baton set that contains PATH. */
+svn_error_t *
+svn_wc__maybe_set_appledouble(svn_boolean_t *did_set,
+ const char *path,
+ svn_wc_adm_access_t *adm_access,
+ apr_pool_t *pool);
+#endif
+
  /* If the SVN_PROP_NEEDS_LOCK property is present and there is no
     lock token for the file in the working copy, set PATH to
     read-only. If DID_SET is non-null, then set *DID_SET to TRUE if

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe_at_subversion.tigris.org
For additional commands, e-mail: dev-help_at_subversion.tigris.org
Received on 2008-08-12 08:25:02 CEST

This is an archived mail posted to the Subversion Dev mailing list.

This site is subject to the Apache Privacy Policy and the Apache Public Forum Archive Policy.