On 06.02.2011 11:43, Bert Huijben wrote:
Note that this patch is not really what you want: It doesn't handle UTF-8,
nor long path names (which apr's version would do for us). We need to
support both when we don't want to introduce a regression.
In 1.7 we usually only have one .svn directory per workingcopy so there
won't be any performance difference on our operations.
Attached is a patch that would address the issue. I implemented it in
make_dir when the 'hidden' attribute is set: I just set the 'no index'
attribute as well.
Stefan
--
___
oo // \\ "De Chelonian Mobile"
(_,\/ \_/ \ TortoiseSVN
\ \_/_\_/> The coolest Interface to (Sub)Version Control
/_/ \_\ http://tortoisesvn.net
[[[
Set the 'don't index' attribute on Windows on .svn the folders to prevent
its content from being indexed by the Windows search service.
* subversion/libsvn_subr/io.c
(svn_utf8_to_unicode_path): new function, copy of utf8_to_unicode_path in
the apr library since it's not exported.
(apr_win_file_attrs_set): new function to set Windows file attributes.
(dir_make): when setting the 'hidden' attribute also set the 'no index'
attribute.
]]]
Index: subversion/libsvn_subr/io.c
===================================================================
--- subversion/libsvn_subr/io.c (Revision 1066924)
+++ subversion/libsvn_subr/io.c (Arbeitskopie)
@@ -47,6 +47,10 @@
#include <apr_portable.h>
#include <apr_md5.h>
+#ifdef WIN32
+#include <arch/win32/apr_arch_file_io.h>
+#endif
+
#include "svn_types.h"
#include "svn_dirent_uri.h"
#include "svn_path.h"
@@ -1539,7 +1543,132 @@
}
#endif /* !WIN32 && !__OS2__ */
+#ifdef WIN32
+#if APR_HAS_UNICODE_FS
+/* copy of the apr function utf8_to_unicode_path since apr doesn't export this
one */
+apr_status_t svn_utf8_to_unicode_path(apr_wchar_t* retstr, apr_size_t retlen,
+ const char* srcstr)
+{
+ /* TODO: The computations could preconvert the string to determine
+ * the true size of the retstr, but that's a memory over speed
+ * tradeoff that isn't appropriate this early in development.
+ *
+ * Allocate the maximum string length based on leading 4
+ * characters of \\?\ (allowing nearly unlimited path lengths)
+ * plus the trailing null, then transform /'s into \\'s since
+ * the \\?\ form doesn't allow '/' path seperators.
+ *
+ * Note that the \\?\ form only works for local drive paths, and
+ * \\?\UNC\ is needed UNC paths.
+ */
+ apr_size_t srcremains = strlen(srcstr) + 1;
+ apr_wchar_t *t = retstr;
+ apr_status_t rv;
+ /* This is correct, we don't twist the filename if it is will
+ * definately be shorter than 248 characters. It merits some
+ * performance testing to see if this has any effect, but there
+ * seem to be applications that get confused by the resulting
+ * Unicode \\?\ style file names, especially if they use argv[0]
+ * or call the Win32 API functions such as GetModuleName, etc.
+ * Not every application is prepared to handle such names.
+ *
+ * Note also this is shorter than MAX_PATH, as directory paths
+ * are actually limited to 248 characters.
+ *
+ * Note that a utf-8 name can never result in more wide chars
+ * than the original number of utf-8 narrow chars.
+ */
+ if (srcremains > 248) {
+ if (srcstr[1] == ':' && (srcstr[2] == '/' || srcstr[2] == '\\')) {
+ wcscpy (retstr, L"\\\\?\\");
+ retlen -= 4;
+ t += 4;
+ }
+ else if ((srcstr[0] == '/' || srcstr[0] == '\\')
+ && (srcstr[1] == '/' || srcstr[1] == '\\')
+ && (srcstr[2] != '?')) {
+ /* Skip the slashes */
+ srcstr += 2;
+ srcremains -= 2;
+ wcscpy (retstr, L"\\\\?\\UNC\\");
+ retlen -= 8;
+ t += 8;
+ }
+ }
+
+ if (rv = apr_conv_utf8_to_ucs2(srcstr, &srcremains, t, &retlen)) {
+ return (rv == APR_INCOMPLETE) ? APR_EINVAL : rv;
+ }
+ if (srcremains) {
+ return APR_ENAMETOOLONG;
+ }
+ for (; *t; ++t)
+ if (*t == L'/')
+ *t = L'\\';
+ return APR_SUCCESS;
+}
+#endif
+
+apr_status_t apr_win_file_attrs_set(const char *fname,
+ DWORD attributes,
+ DWORD attr_mask,
+ apr_pool_t *pool)
+{
+ /* this is an implementation of apr_file_attrs_set() but one
+ that uses the proper Windows attributes instead of the apr
+ attributes. This way, we can apply any Windows file and
+ folder attributes even if apr doesn't implement them */
+ DWORD flags;
+ apr_status_t rv;
+#if APR_HAS_UNICODE_FS
+ apr_wchar_t wfname[APR_PATH_MAX];
+#endif
+
+#if APR_HAS_UNICODE_FS
+ IF_WIN_OS_IS_UNICODE
+ {
+ if (rv = svn_utf8_to_unicode_path(wfname,
+ sizeof(wfname) / sizeof(wfname[0]),
+ fname))
+ return rv;
+ flags = GetFileAttributesW(wfname);
+ }
+#endif
+#if APR_HAS_ANSI_FS
+ ELSE_WIN_OS_IS_ANSI
+ {
+ flags = GetFileAttributesA(fname);
+ }
+#endif
+
+ if (flags == 0xFFFFFFFF)
+ return apr_get_os_error();
+
+ flags |= (attributes & attr_mask);
+ flags &= ~attr_mask;
+
+#if APR_HAS_UNICODE_FS
+ IF_WIN_OS_IS_UNICODE
+ {
+ rv = SetFileAttributesW(wfname, flags);
+ }
+#endif
+#if APR_HAS_ANSI_FS
+ ELSE_WIN_OS_IS_ANSI
+ {
+ rv = SetFileAttributesA(fname, flags);
+ }
+#endif
+
+ if (rv == 0)
+ return apr_get_os_error();
+
+ return APR_SUCCESS;
+}
+
+#endif
+
svn_error_t *
svn_io_set_file_read_write_carefully(const char *path,
svn_boolean_t enable_write,
@@ -3197,10 +3326,22 @@
#ifdef APR_FILE_ATTR_HIDDEN
if (hidden)
{
+#ifndef WIN32
status = apr_file_attrs_set(path_apr,
APR_FILE_ATTR_HIDDEN,
APR_FILE_ATTR_HIDDEN,
pool);
+#else
+ /* on Windows, use our wrapper so we can also set the
+ FILE_ATTRIBUTE_NOT_CONTENT_INDEXED attribute */
+ status = apr_win_file_attrs_set(path_apr,
+ FILE_ATTRIBUTE_HIDDEN |
+ FILE_ATTRIBUTE_NOT_CONTENT_INDEXED,
+ FILE_ATTRIBUTE_HIDDEN |
+ FILE_ATTRIBUTE_NOT_CONTENT_INDEXED,
+ pool);
+
+#endif
if (status)
return svn_error_wrap_apr(status, _("Can't hide directory '%s'"),
svn_dirent_local_style(path, pool));