You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@subversion.apache.org by Josh Pieper <jj...@pobox.com> on 2004/06/28 13:03:18 UTC
Proposal: Support for versioning symlinks and other special files.
I've begun work on implementing versioning of symlinks and other
special device files in Subversion. It follows the approach suggested
by Nuutti Kotivuori in Issue #677 of using the EOL/keyword translation
framework to "translate" all the special files into a textual version
that can be stored in the text-base and in the repository. The
translation is controlled by a new Subversion namespace property,
"svn:special".
This approach should allow Windows and other platforms without support
for the special devices to still view, modify, and create them,
although the files will not have the special meaning that they do on
UNIX like platforms. I am not proposing any use of symlinks as a way
to replace svn:externals, instead the destination of the symlink is
just treated like the versioned contents of a file. I think this gets
95% of the cases when you actually want to version a symlink.
I'm mainly looking for feedback on the general approach in this
message, but I have attached a patch that implements some of this
behavior. It is not complete and several items remain to be finished.
First, only symlinks are supported, however support for character
devices, block devices, sockets, and FIFOs would mostly be similar to
that for symlinks. Second, I haven't actually tried to implement
support for non-UNIX like systems yet. Finally, I believe a new type
of entry in the WC entries file is necessary, perhaps "special" or
something similar. It would allow the WC code to determine when a
normal file has been replaced with a special file or vice versa.
Changes between different types of special files can be handled using
the normal translation framework.
One other question about the patch. In it, I change the behavior of
svn_io_check_path to return svn_node_file for any special file,
instead of svn_node_unknown. This is still in line with the docstring
for the function, but is a behavior change. Is this acceptable within
the 1.x line of development, or should it get a new API routine while
deprecating the old?
-Josh
========================================================
Issue #677: Allow special files such as symlinks to be added to
working copies on systems that support them. The special files are
stored in the repository as normal files with the svn:special property
set and the information necessary to recreate the special file are
stored in the contents of the normal file. Most of the hard work is
done using the existing EOL/keyword translation support.
* subversion/include/svn_subst.h
(SVN_SUBST__SPECIAL_LINK_STR,
SVN_SUBST__SPECIAL_CHR_STR,
SVN_SUBST__SPECIAL_BLK_STR,
SVN_SUBST__SPECIAL_FIFO_STR,
SVN_SUBST__SPECIAL_SOCK_STR): New defines that allow the correct
special device to be created given a repository file'ified version
of it.
(svn_subst_copy_and_translate): Deprecated.
(svn_subst_copy_and_translate2): New routine which duplicates the
functionality of svn_subst_copy_and_translate and also allows
translation of special files. All callers changed to use the new
API.
* subversion/include/svn_props.h
(SVN_PROP_SPECIAL, SVN_PROP_SPECIAL_VALUE): New property that sets a
file as being a "special" file.
* subversion/include/svn_types.h
(svn_node_kind_t): Include all the possible types that APR supports
as possible node kinds.
* subversion/include/svn_io.h
(svn_io_check_special_path): New.
(svn_io_create_unique_link): New.
(svn_io_read_link): New.
* subversion/libsvn_wc/merge.c
(svn_wc_merge): Use the new svn_subst_copy_and_translate2.
* subversion/libsvn_wc/translate.h
(svn_wc__get_special): New.
* subversion/libsvn_wc/adm_crawler.c
(restore_file): Use the new svn_subst_copy_and_translate2.
* subversion/libsvn_wc/log.c
(file_xfer_under_path, install_committed_file): Use the new
svn_subst_copy_and_translate2.
* subversion/libsvn_wc/adm_ops.c
(revert_admin_things): Use the new svn_subst_copy_and_translate2.
* subversion/libsvn_wc/translate.c
(svn_wc_translated_file): Use the new svn_subst_copy_and_translate2.
(svn_wc__get_special): New, determines if the svn:special property
is set on a path.
* subversion/libsvn_subr/subst.c
(create_special_file): New, given a repository normal version of a
special file, create the actual special file using whatever
platform-dependent methods are necessary.
(detranslate_special_file): New, given an actual special file,
create a repository normal version of it.
(svn_subst_copy_and_translate): Impelemented in terms of
svn_subst_copy_and_translate2.
(svn_subst_copy_and_translate2): New, similar to
svn_subst_copy_and_translate except for the addition of the
special option, which controls whether a file should be translated
as if it were a special file.
* subversion/libsvn_subr/io.c
(io_check_path): Add a new option that determines whether special
file types will be collapsed into svn_node_file or whether they
will be returned as their actual types.
(svn_io_check_path, svn_io_check_resolved_path): Use the new
io_check_path. Note that this changes their behavior slightly
since special files used to return svn_node_unknown and will now
return svn_node_file.
(svn_io_check_special_path): New, similar to svn_io_check_path,
except that any special files are returned as their actual type,
not svn_node_file.
(svn_io_create_unique_link): New, creates a symlink that has a
unique name.
(svn_io_read_link): New, reads the destination path from a symlink.
* subversion/libsvn_client/add.c
(add_file): Check to see if the svn:special property should be set
when adding a new file.
(add_dir_recursive): Add all files types that aren't unknown, rather
than just regular files.
Index: subversion/include/svn_subst.h
===================================================================
--- subversion/include/svn_subst.h (revision 10080)
+++ subversion/include/svn_subst.h (working copy)
@@ -32,6 +32,17 @@
extern "C" {
#endif /* __cplusplus */
+/**
+ * The textual elements of a detranslated special file. One of these
+ * strings must appear as the first element of any special file as it
+ * exists in the repository or the text base.
+ */
+#define SVN_SUBST__SPECIAL_LINK_STR "link"
+#define SVN_SUBST__SPECIAL_CHR_STR "chr"
+#define SVN_SUBST__SPECIAL_BLK_STR "blk"
+#define SVN_SUBST__SPECIAL_FIFO_STR "fifo"
+#define SVN_SUBST__SPECIAL_SOCK_STR "sock"
+
/* Eol conversion and keyword expansion. */
/** Valid states for 'svn:eol-style' property.
@@ -163,9 +174,29 @@
svn_boolean_t expand);
-/** Convenience routine: a variant of @c svn_subst_translate_stream which
- * operates on files. (See previous docstring for details.)
+/**
+ * @deprecated Provided for backward compatibility with the 1.0.0 API.
*
+ * Similar to svn_subst_copy_and_translate2 except that @a special is
+ * always set to @c FALSE.
+ */
+svn_error_t *
+svn_subst_copy_and_translate (const char *src,
+ const char *dst,
+ const char *eol_str,
+ svn_boolean_t repair,
+ const svn_subst_keywords_t *keywords,
+ svn_boolean_t expand,
+ apr_pool_t *pool);
+
+/**
+ * @since New in 1.1.
+ *
+ * Convenience routine: a variant of @c svn_subst_translate_stream
+ * which operates on files. (See previous docstring for details.) In
+ * addition, it will create/detranslate a special file if @a special
+ * is @c TRUE.
+ *
* Copy the contents of file-path @a src to file-path @a dst atomically,
* either creating @a dst (or overwriting @a dst if it exists), possibly
* performing line ending and keyword translations.
@@ -177,13 +208,14 @@
* copy.
*/
svn_error_t *
-svn_subst_copy_and_translate (const char *src,
- const char *dst,
- const char *eol_str,
- svn_boolean_t repair,
- const svn_subst_keywords_t *keywords,
- svn_boolean_t expand,
- apr_pool_t *pool);
+svn_subst_copy_and_translate2 (const char *src,
+ const char *dst,
+ const char *eol_str,
+ svn_boolean_t repair,
+ const svn_subst_keywords_t *keywords,
+ svn_boolean_t expand,
+ svn_boolean_t special,
+ apr_pool_t *pool);
/** Convenience routine: a variant of @c svn_subst_translate_stream which
* operates on cstrings. (See previous docstring for details.)
Index: subversion/include/svn_props.h
===================================================================
--- subversion/include/svn_props.h (revision 10080)
+++ subversion/include/svn_props.h (working copy)
@@ -182,6 +182,12 @@
/** The value to force the executable property to when set */
#define SVN_PROP_EXECUTABLE_VALUE "*"
+/** Set if the file should be treated as a special file. */
+#define SVN_PROP_SPECIAL SVN_PROP_PREFIX "special"
+
+/** The value to force the special property to when set. */
+#define SVN_PROP_SPECIAL_VALUE "*"
+
/** Describes external items to check out into this directory.
*
* The format is a series of lines, such as:
Index: subversion/include/svn_types.h
===================================================================
--- subversion/include/svn_types.h (revision 10080)
+++ subversion/include/svn_types.h (working copy)
@@ -85,6 +85,21 @@
/* directory */
svn_node_dir,
+ /* a character device */
+ svn_node_chr,
+
+ /* a block device */
+ svn_node_blk,
+
+ /* a FIFO pipe */
+ svn_node_pipe,
+
+ /* a symbolic link */
+ svn_node_link,
+
+ /* a socket */
+ svn_node_sock,
+
/* something's here, but we don't know what */
svn_node_unknown
Index: subversion/include/svn_io.h
===================================================================
--- subversion/include/svn_io.h (revision 10080)
+++ subversion/include/svn_io.h (working copy)
@@ -59,6 +59,16 @@
svn_node_kind_t *kind,
apr_pool_t *pool);
+/**
+ * @since New in 1.1.
+ *
+ * Like svn_io_check_path(), but return the actual node type for any
+ * special files.
+ */
+svn_error_t *svn_io_check_special_path (const char *path,
+ svn_node_kind_t *kind,
+ apr_pool_t *pool);
+
/** Like svn_io_check_path(), but resolve symlinks. This returns the
same varieties of @a kind as svn_io_check_path(). */
svn_error_t *svn_io_check_resolved_path (const char *path,
@@ -119,7 +129,30 @@
svn_boolean_t delete_on_close,
apr_pool_t *pool);
+/**
+ * @since New in 1.1.
+ *
+ * Like svn_io_open_unique_file, except that instead of creating a
+ * file, a symlink is generated that references the path @a dest.
+ */
+svn_error_t *svn_io_create_unique_link (const char **unique_name_p,
+ const char *path,
+ const char *dest,
+ const char *suffix,
+ apr_pool_t *pool);
+
+/**
+ * @since New in 1.1.
+ *
+ * Set @a dest to the path that the symlink at @a path references.
+ * Allocate the string from @a pool.
+ */
+svn_error_t *svn_io_read_link (svn_string_t **dest,
+ const char *path,
+ apr_pool_t *pool);
+
+
/** Set @a dir to a directory path (allocated in @a pool) deemed
* usable for the creation of temporary files and subdirectories.
*/
Index: subversion/libsvn_wc/merge.c
===================================================================
--- subversion/libsvn_wc/merge.c (revision 10080)
+++ subversion/libsvn_wc/merge.c (working copy)
@@ -52,7 +52,7 @@
svn_subst_keywords_t *keywords;
const char *eol;
const svn_wc_entry_t *entry;
- svn_boolean_t contains_conflicts;
+ svn_boolean_t contains_conflicts, special;
svn_path_split (merge_target, &mt_pt, &mt_bn, pool);
@@ -234,14 +234,18 @@
NULL, pool));
SVN_ERR (svn_wc__get_eol_style (NULL, &eol, merge_target, adm_access,
pool));
- SVN_ERR (svn_subst_copy_and_translate (left,
- left_copy,
- eol, eol ? TRUE : FALSE,
- keywords, TRUE, pool));
- SVN_ERR (svn_subst_copy_and_translate (right,
- right_copy,
- eol, eol ? TRUE : FALSE,
- keywords, TRUE, pool));
+ SVN_ERR (svn_wc__get_special (&special, merge_target, adm_access,
+ pool));
+ SVN_ERR (svn_subst_copy_and_translate2 (left,
+ left_copy,
+ eol, eol ? TRUE : FALSE,
+ keywords, TRUE, special,
+ pool));
+ SVN_ERR (svn_subst_copy_and_translate2 (right,
+ right_copy,
+ eol, eol ? TRUE : FALSE,
+ keywords, TRUE, special,
+ pool));
/* Back up MERGE_TARGET verbatim (it's already in expanded form.) */
SVN_ERR (svn_io_copy_file (merge_target,
@@ -289,9 +293,12 @@
NULL, pool));
SVN_ERR (svn_wc__get_eol_style (NULL, &eol, merge_target, adm_access,
pool));
- SVN_ERR (svn_subst_copy_and_translate (result_target, merge_target,
- eol, eol ? TRUE : FALSE,
- keywords, TRUE, pool));
+ SVN_ERR (svn_wc__get_special (&special, merge_target, adm_access,
+ pool));
+ SVN_ERR (svn_subst_copy_and_translate2 (result_target, merge_target,
+ eol, eol ? TRUE : FALSE,
+ keywords, TRUE, special,
+ pool));
}
/* Don't forget to clean up tmp_target, result_target, tmp_left,
Index: subversion/libsvn_wc/translate.h
===================================================================
--- subversion/libsvn_wc/translate.h (revision 10080)
+++ subversion/libsvn_wc/translate.h (working copy)
@@ -88,6 +88,15 @@
apr_pool_t *pool);
+/* Determine if the svn:special flag is set on PATH. If so, set
+ SPECIAL to TRUE, if not, set it to FALSE. ADM_ACCESS must be an
+ access baton for PATH. Perform any temporary allocations in
+ POOL. */
+svn_error_t *svn_wc__get_special (svn_boolean_t *special,
+ const char *path,
+ svn_wc_adm_access_t *adm_access,
+ apr_pool_t *pool);
+
/* If the SVN_PROP_EXECUTABLE property is present at all, then set
PATH executable. If DID_SET is non-null, then set *DID_SET to
TRUE if did set PATH executable, or to FALSE if not. ADM_ACCESS
Index: subversion/libsvn_wc/adm_crawler.c
===================================================================
--- subversion/libsvn_wc/adm_crawler.c (revision 10080)
+++ subversion/libsvn_wc/adm_crawler.c (working copy)
@@ -69,6 +69,7 @@
apr_time_t tstamp;
const char *bname;
apr_uint32_t modify_flags = 0;
+ svn_boolean_t special;
text_base_path = svn_wc__text_base_path (file_path, FALSE, pool);
tmp_text_base_path = svn_wc__text_base_path (file_path, TRUE, pool);
@@ -80,17 +81,20 @@
SVN_ERR (svn_wc__get_eol_style (NULL, &eol, file_path, adm_access, pool));
SVN_ERR (svn_wc__get_keywords (&keywords,
file_path, adm_access, NULL, pool));
+ SVN_ERR (svn_wc__get_special (&special, file_path, adm_access, pool));
+
/* When copying the tmp-text-base out to the working copy, make
sure to do any eol translations or keyword substitutions,
as dictated by the property values. If these properties
are turned off, then this is just a normal copy. */
- SVN_ERR (svn_subst_copy_and_translate (tmp_text_base_path,
- file_path,
- eol, FALSE, /* don't repair */
- keywords,
- TRUE, /* expand keywords */
- pool));
+ SVN_ERR (svn_subst_copy_and_translate2 (tmp_text_base_path,
+ file_path,
+ eol, FALSE, /* don't repair */
+ keywords,
+ TRUE, /* expand keywords */
+ special,
+ pool));
SVN_ERR (svn_io_remove_file (tmp_text_base_path, pool));
Index: subversion/libsvn_wc/log.c
===================================================================
--- subversion/libsvn_wc/log.c (revision 10080)
+++ subversion/libsvn_wc/log.c (working copy)
@@ -115,20 +115,24 @@
{
svn_subst_keywords_t *keywords;
const char *eol_str;
+ svn_boolean_t special;
/* Note that this action takes properties from dest, not source. */
SVN_ERR (svn_wc__get_keywords (&keywords, full_dest_path, adm_access,
NULL, pool));
SVN_ERR (svn_wc__get_eol_style (NULL, &eol_str, full_dest_path,
adm_access, pool));
+ SVN_ERR (svn_wc__get_special (&special, full_dest_path, adm_access,
+ pool));
- SVN_ERR (svn_subst_copy_and_translate (full_from_path,
- full_dest_path,
- eol_str,
- TRUE,
- keywords,
- TRUE,
- pool));
+ SVN_ERR (svn_subst_copy_and_translate2 (full_from_path,
+ full_dest_path,
+ eol_str,
+ TRUE,
+ keywords,
+ TRUE,
+ special,
+ pool));
/* After copying, set the file executable if props dictate. */
return svn_wc__maybe_set_executable (NULL, full_dest_path, adm_access,
@@ -139,23 +143,27 @@
{
svn_subst_keywords_t *keywords;
const char *eol_str;
+ svn_boolean_t special;
/* Note that this action takes properties from source, not dest. */
SVN_ERR (svn_wc__get_keywords (&keywords, full_from_path, adm_access,
NULL, pool));
SVN_ERR (svn_wc__get_eol_style (NULL, &eol_str, full_from_path,
adm_access, pool));
+ SVN_ERR (svn_wc__get_special (&special, full_from_path, adm_access,
+ pool));
/* If any specific eol style was indicated, then detranslate
back to repository normal form ("\n"), repairingly. But if
no style indicated, don't touch line endings at all. */
- return svn_subst_copy_and_translate (full_from_path,
- full_dest_path,
- (eol_str ? "\n" : NULL),
- (eol_str ? TRUE : FALSE),
- keywords,
- FALSE, /* contract keywords */
- pool);
+ return svn_subst_copy_and_translate2 (full_from_path,
+ full_dest_path,
+ (eol_str ? "\n" : NULL),
+ (eol_str ? TRUE : FALSE),
+ keywords,
+ FALSE, /* contract keywords */
+ special,
+ pool);
}
case svn_wc__xfer_mv:
@@ -212,6 +220,7 @@
svn_boolean_t same, did_set;
const char *tmp_wfile, *pdir, *bname;
const char *eol_str;
+ svn_boolean_t special;
/* start off assuming that the working file isn't touched. */
*overwrote_working = FALSE;
@@ -238,6 +247,7 @@
/* start off getting the latest translation prop values. */
SVN_ERR (svn_wc__get_eol_style (NULL, &eol_str, filepath, adm_access, pool));
SVN_ERR (svn_wc__get_keywords (&keywords, filepath, adm_access, NULL, pool));
+ SVN_ERR (svn_wc__get_special (&special, filepath, adm_access, pool));
svn_path_split (filepath, &pdir, &bname, pool);
tmp_wfile = svn_wc__adm_path (pdir, TRUE, pool, bname, NULL);
@@ -252,23 +262,32 @@
SVN_ERR (svn_io_check_path (tmp_text_base, &kind, pool));
if (kind == svn_node_file)
- SVN_ERR (svn_subst_copy_and_translate (tmp_text_base,
- tmp_wfile,
- eol_str,
- FALSE, /* don't repair eol */
- keywords,
- TRUE, /* expand keywords */
- pool));
+ SVN_ERR (svn_subst_copy_and_translate2 (tmp_text_base,
+ tmp_wfile,
+ eol_str,
+ FALSE, /* don't repair eol */
+ keywords,
+ TRUE, /* expand keywords */
+ special,
+ pool));
else
- SVN_ERR (svn_subst_copy_and_translate (filepath,
- tmp_wfile,
- eol_str,
- FALSE, /* don't repair eol */
- keywords,
- TRUE, /* expand keywords */
- pool));
+ SVN_ERR (svn_subst_copy_and_translate2 (filepath,
+ tmp_wfile,
+ eol_str,
+ FALSE, /* don't repair eol */
+ keywords,
+ TRUE, /* expand keywords */
+ special,
+ pool));
- SVN_ERR (svn_io_files_contents_same_p (&same, tmp_wfile, filepath, pool));
+ if (! special)
+ {
+ SVN_ERR (svn_io_files_contents_same_p (&same, tmp_wfile, filepath, pool));
+ }
+ else
+ {
+ same = TRUE;
+ }
if (! same)
{
Index: subversion/libsvn_wc/adm_ops.c
===================================================================
--- subversion/libsvn_wc/adm_ops.c (revision 10080)
+++ subversion/libsvn_wc/adm_ops.c (working copy)
@@ -1245,23 +1245,26 @@
file. */
svn_subst_keywords_t *keywords;
const char *eol;
+ svn_boolean_t special;
SVN_ERR (svn_wc__get_eol_style (NULL, &eol, fullpath, adm_access,
pool));
SVN_ERR (svn_wc__get_keywords (&keywords, fullpath, adm_access, NULL,
pool));
+ SVN_ERR (svn_wc__get_special (&special, fullpath, adm_access, pool));
/* When copying the text-base out to the working copy, make
sure to do any eol translations or keyword substitutions,
as dictated by the property values. If these properties
are turned off, then this is just a normal copy. */
- if ((err = svn_subst_copy_and_translate (base_thing,
- fullpath,
- eol,
- FALSE, /* don't repair */
- keywords,
- TRUE, /* expand keywords */
- pool)))
+ if ((err = svn_subst_copy_and_translate2 (base_thing,
+ fullpath,
+ eol,
+ FALSE, /* don't repair */
+ keywords,
+ TRUE, /* expand keywords */
+ special,
+ pool)))
return svn_error_quick_wrap
(err, apr_psprintf (pool, _("Error restoring text for '%s'"),
fullpath));
Index: subversion/libsvn_wc/translate.c
===================================================================
--- subversion/libsvn_wc/translate.c (revision 10080)
+++ subversion/libsvn_wc/translate.c (working copy)
@@ -57,11 +57,13 @@
svn_subst_eol_style_t style;
const char *eol;
svn_subst_keywords_t *keywords;
+ svn_boolean_t special;
SVN_ERR (svn_wc__get_eol_style (&style, &eol, vfile, adm_access, pool));
SVN_ERR (svn_wc__get_keywords (&keywords, vfile, adm_access, NULL, pool));
+ SVN_ERR (svn_wc__get_special (&special, vfile, adm_access, pool));
- if ((style == svn_subst_eol_style_none) && (! keywords))
+ if ((style == svn_subst_eol_style_none) && (! keywords) && (! special))
{
/* Translation would be a no-op, so return the original file. */
*xlated_p = vfile;
@@ -91,33 +93,36 @@
if (style == svn_subst_eol_style_fixed)
{
- SVN_ERR (svn_subst_copy_and_translate (vfile,
- tmp_vfile,
- eol,
- TRUE,
- keywords,
- FALSE,
- pool));
+ SVN_ERR (svn_subst_copy_and_translate2 (vfile,
+ tmp_vfile,
+ eol,
+ TRUE,
+ keywords,
+ FALSE,
+ special,
+ pool));
}
else if (style == svn_subst_eol_style_native)
{
- SVN_ERR (svn_subst_copy_and_translate (vfile,
- tmp_vfile,
- SVN_WC__DEFAULT_EOL_MARKER,
- force_repair,
- keywords,
- FALSE,
- pool));
+ SVN_ERR (svn_subst_copy_and_translate2 (vfile,
+ tmp_vfile,
+ SVN_WC__DEFAULT_EOL_MARKER,
+ force_repair,
+ keywords,
+ FALSE,
+ special,
+ pool));
}
else if (style == svn_subst_eol_style_none)
{
- SVN_ERR (svn_subst_copy_and_translate (vfile,
- tmp_vfile,
- NULL,
- force_repair,
- keywords,
- FALSE,
- pool));
+ SVN_ERR (svn_subst_copy_and_translate2 (vfile,
+ tmp_vfile,
+ NULL,
+ force_repair,
+ keywords,
+ FALSE,
+ special,
+ pool));
}
else
{
@@ -220,6 +225,24 @@
svn_error_t *
+svn_wc__get_special (svn_boolean_t *special,
+ const char *path,
+ svn_wc_adm_access_t *adm_access,
+ apr_pool_t *pool)
+{
+ const svn_string_t *propval;
+
+ /* Get the property value. */
+ SVN_ERR (svn_wc_prop_get (&propval, SVN_PROP_SPECIAL, path, adm_access,
+ pool));
+
+ *special = propval ? TRUE : FALSE;
+
+ return SVN_NO_ERROR;
+}
+
+
+svn_error_t *
svn_wc__maybe_set_executable (svn_boolean_t *did_set,
const char *path,
svn_wc_adm_access_t *adm_access,
Index: subversion/libsvn_subr/subst.c
===================================================================
--- subversion/libsvn_subr/subst.c (revision 10080)
+++ subversion/libsvn_subr/subst.c (working copy)
@@ -779,9 +779,171 @@
return err;
}
+/* Given a file containing a repository representation of a special
+ file in SRC, create the appropriate special file at location DST.
+ Perform all allocations in POOL. */
+static svn_error_t *
+create_special_file (const char *src,
+ const char *dst,
+ apr_pool_t *pool)
+{
+ svn_stringbuf_t *contents;
+ char *identifier, *remainder;
+ const char *dst_tmp;
+ int i;
+ /* Read in the detranslated file. */
+ SVN_ERR (svn_stringbuf_from_file (&contents, src, pool));
+ /* Separate off the identifier. The first space character delimits
+ the identifier, after which any remaining characters are specific
+ to the actual special device being created. */
+ identifier = contents->data;
+ for (remainder = identifier; *remainder; remainder++)
+ {
+ if (*remainder == ' ')
+ {
+ *remainder = '\0';
+ remainder++;
+ break;
+ }
+ }
+
+ if (! strcmp (identifier, SVN_SUBST__SPECIAL_LINK_STR))
+ {
+ /* For symlinks, the type specific data is just a filesystem
+ path that the symlink should reference. */
+ SVN_ERR (svn_io_create_unique_link (&dst_tmp, dst, remainder,
+ ".tmp", pool));
+ }
+ /*
+ else if (! strcmp (identifier, SVN_SUBST__SPECIAL_CHR_STR) ||
+ ! strcmp (identifier, SVN_SUBST__SPECIAL_BLK_STR))
+ {
+ char *major_str, *minor_str;
+ int major, minor;
+ apr_filetype_t type;
+
+ major_str = apr_strtok (remainder, " ", &minor_str);
+
+ if ((! major_str) || (! minor_str))
+ abort();
+
+ major = atoi (major_str);
+ minor = atoi (minor_str);
+
+ type = (! strcmp (identifier, SVN_SUBST__SPECIAL_CHR_STR)) ? APR_CHR
+ : APR_BLK;
+
+ SVN_ERR (svn_io_create_unique_device (&dst_tmp, dst, type,
+ major, minor,
+ ".tmp", pool));
+ }
+ else if (! strcmp (identifier, SVN_SUBST__SPECIAL_FIFO_STR))
+ {
+ SVN_ERR (svn_io_create_unique_fifo (&dst_tmp, dst, ".tmp", pool));
+ }
+ else if (! strcmp (identifier, SVN_SUBST__SPECIAL_SOCK_STR))
+ {
+ SVN_ERR (svn_io_create_unique_socket (&dst_tmp, dst, ".tmp", pool));
+ }
+ */
+ else
+ {
+ /* We should return a valid error here. */
+ abort ();
+ }
+
+ /* Do the atomic rename from our temporary location. */
+ SVN_ERR (svn_io_file_rename (dst_tmp, dst, pool));
+
+ return SVN_NO_ERROR;
+}
+
+
+/* Given a special file at SRC, generate a textual representation of
+ it in a normal file at DST. Perform all allocations in POOL. */
+static svn_error_t *
+detranslate_special_file (const char *src,
+ const char *dst,
+ apr_pool_t *pool)
+{
+ svn_node_kind_t kind;
+ const char *dst_tmp;
+ svn_string_t *buf;
+ apr_file_t *s, *d;
+ svn_stream_t *src_stream, *dst_stream;
+
+ /* First determine what type of special file we are
+ detranslating. */
+ SVN_ERR (svn_io_check_special_path (src, &kind, pool));
+
+ /* Open a temporary destination that we will eventually atomically
+ rename into place. */
+ SVN_ERR (svn_io_open_unique_file (&d, &dst_tmp, dst,
+ ".tmp", FALSE, pool));
+
+ dst_stream = svn_stream_from_aprfile (d, pool);
+
+ switch (kind) {
+ case svn_node_file:
+ /* Nothing special to do here, just copy the original file's
+ contents. */
+ SVN_ERR (svn_io_file_open (&s, src, APR_READ | APR_BUFFERED,
+ APR_OS_DEFAULT, pool));
+ src_stream = svn_stream_from_aprfile (d, pool);
+
+ SVN_ERR (svn_stream_copy (src_stream, dst_stream, pool));
+ break;
+ case svn_node_link:
+ /* Determine the destination of the link. */
+ SVN_ERR (svn_io_read_link (&buf, src, pool));
+
+ SVN_ERR (svn_stream_printf (dst_stream, pool, "link %s",
+ buf->data));
+ break;
+ default:
+ abort ();
+ }
+
+ SVN_ERR (svn_io_file_close (d, pool));
+
+ /* Do the atomic rename from our temporary location. */
+ SVN_ERR (svn_io_file_rename (dst_tmp, dst, pool));
+
+ return SVN_NO_ERROR;
+}
+
+
svn_error_t *
+svn_subst_copy_and_translate2 (const char *src,
+ const char *dst,
+ const char *eol_str,
+ svn_boolean_t repair,
+ const svn_subst_keywords_t *keywords,
+ svn_boolean_t expand,
+ svn_boolean_t special,
+ apr_pool_t *pool)
+{
+ /* Handle the case when we are handling normal files. */
+ if (! special)
+ {
+ return svn_subst_copy_and_translate (src, dst, eol_str, repair, keywords,
+ expand, pool);
+ }
+
+ /* If this is a 'special' file, we may need to create it or
+ detranslate it. */
+ if (expand)
+ SVN_ERR (create_special_file (src, dst, pool));
+ else
+ SVN_ERR (detranslate_special_file (src, dst, pool));
+
+ return SVN_NO_ERROR;
+}
+
+
+svn_error_t *
svn_subst_translate_string (svn_string_t **new_value,
const svn_string_t *value,
const char *encoding,
Index: subversion/libsvn_subr/io.c
===================================================================
--- subversion/libsvn_subr/io.c (revision 10080)
+++ subversion/libsvn_subr/io.c (working copy)
@@ -90,6 +90,7 @@
static svn_error_t *
io_check_path (const char *path,
svn_boolean_t resolve_symlinks,
+ svn_boolean_t expand_special,
svn_node_kind_t *kind,
apr_pool_t *pool)
{
@@ -120,10 +121,8 @@
*kind = svn_node_file;
else if (finfo.filetype == APR_DIR)
*kind = svn_node_dir;
-#if 0
- else if (finfo.filetype == APR_LINK)
- *kind = svn_node_symlink; /* we support symlinks someday, but not yet */
-#endif /* 0 */
+ else if (finfo.filetype == APR_LNK)
+ *kind = expand_special ? svn_node_link : svn_node_file;
else
*kind = svn_node_unknown;
@@ -136,7 +135,7 @@
svn_node_kind_t *kind,
apr_pool_t *pool)
{
- return io_check_path (path, TRUE, kind, pool);
+ return io_check_path (path, TRUE, FALSE, kind, pool);
}
svn_error_t *
@@ -144,9 +143,16 @@
svn_node_kind_t *kind,
apr_pool_t *pool)
{
- return io_check_path (path, FALSE, kind, pool);
+ return io_check_path (path, FALSE, FALSE, kind, pool);
}
+svn_error_t *
+svn_io_check_special_path (const char *path,
+ svn_node_kind_t *kind,
+ apr_pool_t *pool)
+{
+ return io_check_path (path, FALSE, TRUE, kind, pool);
+}
svn_error_t *
svn_io_open_unique_file (apr_file_t **f,
@@ -234,6 +240,114 @@
"Unable to make name for '%s'", path);
}
+svn_error_t *
+svn_io_create_unique_link (const char **unique_name_p,
+ const char *path,
+ const char *dest,
+ const char *suffix,
+ apr_pool_t *pool)
+{
+ unsigned int i;
+ const char *unique_name;
+ const char *unique_name_apr;
+ int rv;
+
+ for (i = 1; i <= 99999; i++)
+ {
+ apr_status_t apr_err;
+
+ /* Special case the first attempt -- if we can avoid having a
+ generated numeric portion at all, that's best. So first we
+ try with just the suffix; then future tries add a number
+ before the suffix. (A do-while loop could avoid the repeated
+ conditional, but it's not worth the clarity loss.)
+
+ If the first attempt fails, the first number will be "2".
+ This is good, since "1" would misleadingly imply that
+ the second attempt was actually the first... and if someone's
+ got conflicts on their conflicts, we probably don't want to
+ add to their confusion :-). */
+ if (i == 1)
+ unique_name = apr_psprintf (pool, "%s%s", path, suffix);
+ else
+ unique_name = apr_psprintf (pool, "%s.%u%s", path, i, suffix);
+
+ /* Hmmm. Ideally, we would append to a native-encoding buf
+ before starting iteration, then convert back to UTF-8 for
+ return. But I suppose that would make the appending code
+ sensitive to i18n in a way it shouldn't be... Oh well. */
+ SVN_ERR (svn_path_cstring_from_utf8 (&unique_name_apr, unique_name,
+ pool));
+
+#ifdef WIN32
+
+ rv = 0;
+#else
+ do {
+ rv = symlink (dest, unique_name_apr);
+ } while (rv == -1 && APR_STATUS_IS_EINTR (apr_get_os_error ()));
+#endif
+
+ apr_err = apr_get_os_error();
+
+ if (APR_STATUS_IS_EEXIST (apr_err))
+ continue;
+ else if (rv == -1 && apr_err)
+ {
+ /* On Win32, CreateFile failswith an "Access Denied" error
+ code, rather than "File Already Exists", if the colliding
+ name belongs to a directory. */
+ if (APR_STATUS_IS_EACCES (apr_err))
+ {
+ apr_finfo_t finfo;
+ apr_status_t apr_err_2 = apr_stat (&finfo, unique_name_apr,
+ APR_FINFO_TYPE, pool);
+
+ if (APR_STATUS_IS_SUCCESS (apr_err_2)
+ && (finfo.filetype == APR_DIR))
+ continue;
+
+ /* Else ignore apr_err_2; better to fall through and
+ return the original error. */
+ }
+
+ *unique_name_p = NULL;
+ return svn_error_wrap_apr (apr_err, "Can't open '%s'", unique_name);
+ }
+ else
+ {
+ *unique_name_p = unique_name;
+ return SVN_NO_ERROR;
+ }
+ }
+
+ *unique_name_p = NULL;
+ return svn_error_createf (SVN_ERR_IO_UNIQUE_NAMES_EXHAUSTED,
+ NULL,
+ "Unable to make name for '%s'", path);
+}
+
+svn_error_t *
+svn_io_read_link (svn_string_t **dest,
+ const char *path,
+ apr_pool_t *pool)
+{
+ char buf[1024];
+ int rv;
+
+ do {
+ rv = readlink (path, buf, sizeof(buf));
+ } while (rv == -1 && APR_STATUS_IS_EINTR (apr_get_os_error ()));
+
+ if (rv == -1)
+ return svn_error_wrap_apr
+ (apr_get_os_error (), "Can't read contents of link.");
+
+ *dest = svn_string_ncreate (buf, rv, pool);
+
+ return SVN_NO_ERROR;
+}
+
#if 1 /* TODO: Remove this code when APR 0.9.6 is released. */
#include "apr_env.h"
Index: subversion/libsvn_client/add.c
===================================================================
--- subversion/libsvn_client/add.c (revision 10080)
+++ subversion/libsvn_client/add.c (working copy)
@@ -205,27 +205,46 @@
apr_hash_t* properties;
apr_hash_index_t *hi;
const char *mimetype;
+ svn_node_kind_t kind;
/* add the file */
SVN_ERR (svn_wc_add (path, adm_access, NULL, SVN_INVALID_REVNUM,
ctx->cancel_func, ctx->cancel_baton,
NULL, NULL, pool));
- /* get automatic properties */
- SVN_ERR (svn_client__get_auto_props (&properties, &mimetype, path, ctx,
- pool));
- if (properties)
+
+ /* Check to see if this is a special file. */
+ SVN_ERR (svn_io_check_special_path (path, &kind, pool));
+
+ if ((kind != svn_node_dir)
+ && (kind != svn_node_file)
+ && (kind != svn_node_unknown))
{
- /* loop through the hashtable and add the properties */
- for (hi = apr_hash_first (pool, properties);
- hi != NULL; hi = apr_hash_next (hi))
+ /* This must be a special file. */
+ SVN_ERR (svn_wc_prop_set (SVN_PROP_SPECIAL,
+ svn_string_create (SVN_PROP_SPECIAL_VALUE, pool),
+ path, adm_access, pool));
+ mimetype = NULL;
+ }
+ else
+ {
+ /* get automatic properties */
+ SVN_ERR (svn_client__get_auto_props (&properties, &mimetype, path, ctx,
+ pool));
+ if (properties)
{
- const void *pname;
- void *pval;
-
- apr_hash_this (hi, &pname, NULL, &pval);
- SVN_ERR (svn_wc_prop_set (pname, pval, path, adm_access, pool));
+ /* loop through the hashtable and add the properties */
+ for (hi = apr_hash_first (pool, properties);
+ hi != NULL; hi = apr_hash_next (hi))
+ {
+ const void *pname;
+ void *pval;
+
+ apr_hash_this (hi, &pname, NULL, &pval);
+ SVN_ERR (svn_wc_prop_set (pname, pval, path, adm_access, pool));
+ }
}
}
+
/* Report the addition to the caller. */
if (ctx->notify_func != NULL)
(*ctx->notify_func) (ctx->notify_baton, path, svn_wc_notify_add,
@@ -304,7 +323,7 @@
SVN_ERR (add_dir_recursive (fullpath, dir_access, force,
ctx, subpool));
}
- else if (this_entry.filetype == APR_REG)
+ else if (this_entry.filetype != APR_UNKFILE)
{
err = add_file (fullpath, ctx, dir_access, subpool);
if (err && err->apr_err == SVN_ERR_ENTRY_EXISTS && force)
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Re: Proposal: Support for versioning symlinks and other special
files.
Posted by Greg Hudson <gh...@MIT.EDU>.
On Wed, 2004-06-30 at 08:17, Josh Pieper wrote:
> Hmmmm, after some more investigation, it appears storing the
> svn_node_special types in the repository may be challenging for any
> svn before 2.0. The reason being the editor interface has no way to
> specify the type of a node. It is obvious that the calling signatures
> of the editor interface functions cannot be changed in a 1.x line, but
> can new functions be added?
An interesting question. If a caller uses get_default_editor(), then
it's safe to add new functions, just as we can add new fields to the
libsvn_client context structure. But I don't think we document that
requirement anywhere.
We could of course have a new editor type and an old editor type, and
rev all the functions which accept an editor.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Re: Proposal: Support for versioning symlinks and other special files.
Posted by Josh Pieper <jj...@pobox.com>.
Branko ??ibej wrote:
> Josh Pieper wrote:
> >After considering the feedback, I think a workable solution would be
> >to introduce just one new type, svn_node_special, and have it be
> >stored in the repository that way as well doing away with the
> >svn:special property. The server could translate this to a
> >svn_node_file for 1.0 clients. Then, the only system specific logic
> >would not be exported directly in any API, since it would consist of
> >just the stuff necessary to create and read the special files.
> >
> >
> Seems reasonable. It would also be nice if the change to
> svn_subst_copy_and_translate were a bit more generic. That is, instead
> of adding another boolean flag, you could pass in the node type, or
> maybe combine the various bools into a bit mask. Both would leave room
> for future extensions.
Hmmmm, after some more investigation, it appears storing the
svn_node_special types in the repository may be challenging for any
svn before 2.0. The reason being the editor interface has no way to
specify the type of a node. It is obvious that the calling signatures
of the editor interface functions cannot be changed in a 1.x line, but
can new functions be added?
-Josh
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Re: Proposal: Support for versioning symlinks and other special files.
Posted by Branko Čibej <br...@xbc.nu>.
Josh Pieper wrote:
>Branko ??ibej wrote:
>
>
>>1.0 clients must be able to talk to 1.1 servers, and unless the server
>>can know in advance not to send the new node kind values to a client
>>that doesn't understand them, you can't add new node types. I suppose
>>the server should be able to figure it out, though -- I think we have a
>>mechanism for this in both ra_dav and ra_svn.
>>
>>
>At what point in the connection process does the server know that it
>is talking to an old client and what is the API mechanism for
>determining this?
>
>
I'm not very familiar with the RA layers; I think ra_dav can set a
property on the custom reports to determine if the client understands
extended options, and ra_svn has capabilities.
>>If that's the case, then using a new node kind is much cleaner. However,
>>I object to adding /five/ new node kinds where one will do quite nicely.
>>In general, I find the patch adds way too much system-specific logic
>>into the API (not talking about system-specific code in the
>>implementation, of course). The API should be as neutral as possible.
>>There are "special" file types on systems other than Unix, and the same
>>logic should handle them all.
>>
>>
>
>Ok, I believe only three API changes were introduced:
>
> 1. Adding the 'special' flag to svn_subst_copy_and_translate
>
> 2. Adding the svn:special property.
>
> 3. Increasing the number of svn_node_kind_t's.
>
>I assume you are talking about 3, in which case I agree.
>
>
Yup.
>After considering the feedback, I think a workable solution would be
>to introduce just one new type, svn_node_special, and have it be
>stored in the repository that way as well doing away with the
>svn:special property. The server could translate this to a
>svn_node_file for 1.0 clients. Then, the only system specific logic
>would not be exported directly in any API, since it would consist of
>just the stuff necessary to create and read the special files.
>
>
Seems reasonable. It would also be nice if the change to
svn_subst_copy_and_translate were a bit more generic. That is, instead
of adding another boolean flag, you could pass in the node type, or
maybe combine the various bools into a bit mask. Both would leave room
for future extensions.
>If I implement character/block devices, they will be disabled by
>default, needing a config option to enable them as per ghudson's
>suggestion.
>
>
+1
-- Brane
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Re: Proposal: Support for versioning symlinks and other special files.
Posted by Branko Čibej <br...@xbc.nu>.
kfogel@collab.net wrote:
>Josh Pieper <jj...@pobox.com> writes:
>
>
>>After considering the feedback, I think a workable solution would be
>>to introduce just one new type, svn_node_special, and have it be
>>stored in the repository that way as well doing away with the
>>svn:special property. The server could translate this to a
>>svn_node_file for 1.0 clients. Then, the only system specific logic
>>would not be exported directly in any API, since it would consist of
>>just the stuff necessary to create and read the special files.
>>
>>
>
>Well, why not just introduce 'svn_node_symlink', since that's the
>goal?
>
>
Because that's not really the goal. The goal is to have a type of file
node whose contents get interpreted as a sort of file-creation command.
So if the file contents are, e.g., "symlink ../..", you'd get that in
the text base, but an actual symbolic link in the working copy itself.
You only need one new node kind for all of those.
The problem is, of course, that our WC infrastructure is woefully
inadequate for that sort of thing, so any work in that direction will
necessarily be a horrible hack.
-- Brane
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Re: Proposal: Support for versioning symlinks and other special files.
Posted by kf...@collab.net.
Josh Pieper <jj...@pobox.com> writes:
> The reason for having a separate node class would be that not every
> platform can support all of the non-file and non-directory types.
> Also, there are lots of different platform dependent file types. Do
> we want to go through the work of adding a new repository type for
> each and every one?
So the main thing is: *every* platform supports at least files and
directories. For any other types, all bets are off, hence those types
are "special".
Is that the gist of it?
Oh, plus what Brane said in his reply:
> Because that's not really the goal. The goal is to have a type of
> file node whose contents get interpreted as a sort of file-creation
> command. So if the file contents are, e.g., "symlink ../..", you'd
> get that in the text base, but an actual symbolic link in the
> working copy itself. You only need one new node kind for all of
> those.
Okay. I can buy that.
> I have a new proposal that avoids some of these problems. It is
> certainly very simple to implement and may be slightly easier to
> accept than my first one.
>
> 1. Change nothing in the repository/server.
>
> 2. Use just the svn:special property to indicate that a file is
> platform dependent. (do not have a new WC entry type)
>
> 3. Teach svn_subst_copy_and_translate to translate the new files.
>
> 4. Have a new svn_io_check_special_path return svn_node_special for
> any platform dependent file, and use svn_io_stat to figure out what
> type it actually is. svn_io_check_path will just return
> svn_node_file for anything that isn't a directory.
>
> My original idea that a new type of entry would be needed in the WC
> was unwarranted. (Testing for the svn:special property is sufficient
> in all cases.)
>
> This approach is very simple, does not require any APIs to be modified
> in order to support additional platform dependent types, and
> the only platform dependent APIs it introduces are those necessary to
> create and read the special files. The patch is actually pretty
> small, with most of the changes just in changing all callers of
> svn_subst_copy_and_translate.
I think what's going on here is I'm slowly making my peace with the
fact that if we're going to get this feature compatibly, it will be
via a horrible hack :-).
So, this is a horrible hack too, but maybe it's right way to go. At
least it's small.
> About Brane's suggestion to fix the interface to
> svn_subst_copy_and_translate at the same time: While I agree the
> interface is ugly, fixing it is a parallel effort that can be done at
> any time, regardless of this work on handling special files. I may
> even clean it up myself, but would rather not intermingle that work
> with this and thus will look at it later.
Sounds sane.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Re: Proposal: Support for versioning symlinks and other special files.
Posted by Josh Pieper <jj...@pobox.com>.
kfogel@collab.net wrote:
> Josh Pieper <jj...@pobox.com> writes:
> > After considering the feedback, I think a workable solution would be
> > to introduce just one new type, svn_node_special, and have it be
> > stored in the repository that way as well doing away with the
> > svn:special property. The server could translate this to a
> > svn_node_file for 1.0 clients. Then, the only system specific logic
> > would not be exported directly in any API, since it would consist of
> > just the stuff necessary to create and read the special files.
>
> Well, why not just introduce 'svn_node_symlink', since that's the
> goal?
>
> For example, we don't have an 'svn_node_normal' kind. Instead we have
> 'svn_node_file' and 'svn_node_directory'. Although both are "normal",
> that's a category, not an equivalence class. Likewise, the only thing
> "special" node kinds have in common is that they are special. But
> knowing that something is special is not enough information to tell us
> what to actually *do* with such an beast; for that, we need to know
> its actual kind.
>
> In other words, there's no point diving node kinds into special and
> non-special. Let's just, you know, have a node kind for each node
> kind :-). Right now we have two, the most common node kinds in the
> world: files and directories. Tomorrow, maybe we'll have three:
> files, directories, and symlinks.
The reason for having a separate node class would be that not every
platform can support all of the non-file and non-directory types.
Also, there are lots of different platform dependent file types. Do
we want to go through the work of adding a new repository type for
each and every one?
I hacked around a bit seeing what it would take to add _any_ new type
of node into the client/repository. In short, it is a lot of code
churn. There are many cases where it is assumed that a node is either
a file or directory, and many other places where we would need to add
things like 'if (kind == svn_node_file || kind == svn_node_symlink ||
...)' since all the special files are most often treated identically
to normal files. In addition, we would need new interfaces for things
like the update editor and possibly the reporter.
I have a new proposal that avoids some of these problems. It is
certainly very simple to implement and may be slightly easier to
accept than my first one.
1. Change nothing in the repository/server.
2. Use just the svn:special property to indicate that a file is
platform dependent. (do not have a new WC entry type)
3. Teach svn_subst_copy_and_translate to translate the new files.
4. Have a new svn_io_check_special_path return svn_node_special for
any platform dependent file, and use svn_io_stat to figure out what
type it actually is. svn_io_check_path will just return
svn_node_file for anything that isn't a directory.
My original idea that a new type of entry would be needed in the WC
was unwarranted. (Testing for the svn:special property is sufficient
in all cases.)
This approach is very simple, does not require any APIs to be modified
in order to support additional platform dependent types, and
the only platform dependent APIs it introduces are those necessary to
create and read the special files. The patch is actually pretty
small, with most of the changes just in changing all callers of
svn_subst_copy_and_translate.
About Brane's suggestion to fix the interface to
svn_subst_copy_and_translate at the same time: While I agree the
interface is ugly, fixing it is a parallel effort that can be done at
any time, regardless of this work on handling special files. I may
even clean it up myself, but would rather not intermingle that work
with this and thus will look at it later.
-Josh
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Re: Proposal: Support for versioning symlinks and other special files.
Posted by kf...@collab.net.
Josh Pieper <jj...@pobox.com> writes:
> After considering the feedback, I think a workable solution would be
> to introduce just one new type, svn_node_special, and have it be
> stored in the repository that way as well doing away with the
> svn:special property. The server could translate this to a
> svn_node_file for 1.0 clients. Then, the only system specific logic
> would not be exported directly in any API, since it would consist of
> just the stuff necessary to create and read the special files.
Well, why not just introduce 'svn_node_symlink', since that's the
goal?
For example, we don't have an 'svn_node_normal' kind. Instead we have
'svn_node_file' and 'svn_node_directory'. Although both are "normal",
that's a category, not an equivalence class. Likewise, the only thing
"special" node kinds have in common is that they are special. But
knowing that something is special is not enough information to tell us
what to actually *do* with such an beast; for that, we need to know
its actual kind.
In other words, there's no point diving node kinds into special and
non-special. Let's just, you know, have a node kind for each node
kind :-). Right now we have two, the most common node kinds in the
world: files and directories. Tomorrow, maybe we'll have three:
files, directories, and symlinks.
Of course, every engineer always claims that they're arguing for
simplicity, directness, and elegance. So when I claim that I'm
arguing here for simplicity, directness, and elegance, please
understand that it's only because I'm on the side of goodness, truth,
and beauty.
-Karl
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Re: Proposal: Support for versioning symlinks and other special files.
Posted by Josh Pieper <jj...@pobox.com>.
Branko ??ibej wrote:
> 1.0 clients must be able to talk to 1.1 servers, and unless the server
> can know in advance not to send the new node kind values to a client
> that doesn't understand them, you can't add new node types. I suppose
> the server should be able to figure it out, though -- I think we have a
> mechanism for this in both ra_dav and ra_svn.
At what point in the connection process does the server know that it
is talking to an old client and what is the API mechanism for
determining this?
> If that's the case, then using a new node kind is much cleaner. However,
> I object to adding /five/ new node kinds where one will do quite nicely.
> In general, I find the patch adds way too much system-specific logic
> into the API (not talking about system-specific code in the
> implementation, of course). The API should be as neutral as possible.
> There are "special" file types on systems other than Unix, and the same
> logic should handle them all.
Ok, I believe only three API changes were introduced:
1. Adding the 'special' flag to svn_subst_copy_and_translate
2. Adding the svn:special property.
3. Increasing the number of svn_node_kind_t's.
I assume you are talking about 3, in which case I agree.
After considering the feedback, I think a workable solution would be
to introduce just one new type, svn_node_special, and have it be
stored in the repository that way as well doing away with the
svn:special property. The server could translate this to a
svn_node_file for 1.0 clients. Then, the only system specific logic
would not be exported directly in any API, since it would consist of
just the stuff necessary to create and read the special files.
If I implement character/block devices, they will be disabled by
default, needing a config option to enable them as per ghudson's
suggestion.
-Josh
--
It's easy to solve the halting problem with a shotgun. :-)
-- Larry Wall in <19...@wall.org>
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Re: Proposal: Support for versioning symlinks and other special files.
Posted by Branko Čibej <br...@xbc.nu>.
Josh Pieper wrote:
>kfogel@collab.net wrote:
>
>
>>Josh Pieper <jj...@pobox.com> writes:
>>
>>
>>>support for non-UNIX like systems yet. Finally, I believe a new type
>>>of entry in the WC entries file is necessary, perhaps "special" or
>>>something similar. It would allow the WC code to determine when a
>>>normal file has been replaced with a special file or vice versa.
>>>Changes between different types of special files can be handled using
>>>the normal translation framework.
>>>
>>>
>>If we're having a new type of entry in the WC entries file anyway, do
>>we also want to have a new "svn:" property? If there are two
>>indicators of the same thing, then they can get out of sync; it seem
>>like asking for trouble, maybe?
>>
>>
>
>Except that you need some way in the repository to indicate it as
>well. We could introduce a new node kind into the repository, but I
>figured just doing it in the WC would be less invasive and would
>introduce one less incompatibility between 1.1 and 1.0. I'm open to
>debate though. Would it be better to add a new node type to the
>repository and use it there and in the WC, or to have a svn: property
>along with a new WC entry type and no changes to the repository?
>
>
1.0 clients must be able to talk to 1.1 servers, and unless the server
can know in advance not to send the new node kind values to a client
that doesn't understand them, you can't add new node types. I suppose
the server should be able to figure it out, though -- I think we have a
mechanism for this in both ra_dav and ra_svn.
If that's the case, then using a new node kind is much cleaner. However,
I object to adding /five/ new node kinds where one will do quite nicely.
In general, I find the patch adds way too much system-specific logic
into the API (not talking about system-specific code in the
implementation, of course). The API should be as neutral as possible.
There are "special" file types on systems other than Unix, and the same
logic should handle them all.
-- Brane
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Re: Proposal: Support for versioning symlinks and other special files.
Posted by Josh Pieper <jj...@pobox.com>.
kfogel@collab.net wrote:
> Josh Pieper <jj...@pobox.com> writes:
> > support for non-UNIX like systems yet. Finally, I believe a new type
> > of entry in the WC entries file is necessary, perhaps "special" or
> > something similar. It would allow the WC code to determine when a
> > normal file has been replaced with a special file or vice versa.
> > Changes between different types of special files can be handled using
> > the normal translation framework.
>
> If we're having a new type of entry in the WC entries file anyway, do
> we also want to have a new "svn:" property? If there are two
> indicators of the same thing, then they can get out of sync; it seem
> like asking for trouble, maybe?
Except that you need some way in the repository to indicate it as
well. We could introduce a new node kind into the repository, but I
figured just doing it in the WC would be less invasive and would
introduce one less incompatibility between 1.1 and 1.0. I'm open to
debate though. Would it be better to add a new node type to the
repository and use it there and in the WC, or to have a svn: property
along with a new WC entry type and no changes to the repository?
-Josh
--
It seems to make an auto driver mad if he misses you.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Re: Proposal: Support for versioning symlinks and other special files.
Posted by kf...@collab.net.
Josh Pieper <jj...@pobox.com> writes:
> support for non-UNIX like systems yet. Finally, I believe a new type
> of entry in the WC entries file is necessary, perhaps "special" or
> something similar. It would allow the WC code to determine when a
> normal file has been replaced with a special file or vice versa.
> Changes between different types of special files can be handled using
> the normal translation framework.
If we're having a new type of entry in the WC entries file anyway, do
we also want to have a new "svn:" property? If there are two
indicators of the same thing, then they can get out of sync; it seem
like asking for trouble, maybe?
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Re: Proposal: Support for versioning symlinks and otherspecial files.
Posted by kf...@collab.net.
Greg Hudson <gh...@MIT.EDU> writes:
> On Mon, 2004-06-28 at 21:19, Steve Williams wrote:
> > > The idea here is to protect the user from the server, not to protect the
> > > operating system from the user.
> >
> > Protect the user from themselves? Now that would be a selling point. :)
>
> I'm not sure how I'm failing to get through here. The server operator
> is not the user of the client.
I think he might have been kidding (by taking the original
misunderstanding and running with it, without actually endorsing the
misunderstanding himself).
-K
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Re: Proposal: Support for versioning symlinks and
otherspecial files.
Posted by Greg Hudson <gh...@MIT.EDU>.
On Mon, 2004-06-28 at 21:19, Steve Williams wrote:
> > The idea here is to protect the user from the server, not to protect the
> > operating system from the user.
>
> Protect the user from themselves? Now that would be a selling point. :)
I'm not sure how I'm failing to get through here. The server operator
is not the user of the client.
If I type "svn co http://svn.collab.net/repos/svn/trunk", I expect it to
put some files on disk. I don't expect the server operators to be able
to instruct my client to run arbitrary commands or to be able to create
device special files in my working area. It would be a violation of
reasonable security expectations for Subversion to give the server too
much power by default.
(It so happens that what I'm checking out is a piece of software, which
I'm likely to try to compile and run, so the Collabnet people could have
just stuck their malicious code in the Makefile or whatever. But
Subversion is not only used to version source code, and people don't run
every piece of code they check out.)
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Re: Proposal: Support for versioning symlinks and otherspecial files.
Posted by Steve Williams <st...@kromestudios.com>.
> The idea here is to protect the user from the server, not to protect the
> operating system from the user.
Protect the user from themselves? Now that would be a selling point. :)
Sly
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Re: Proposal: Support for versioning symlinks and other
special files.
Posted by Greg Hudson <gh...@MIT.EDU>.
On Mon, 2004-06-28 at 20:37, Bruce Elrick wrote:
> Wouldn't standard OS permissions on the client take care of this? The client process runs with no greater priveledges than the
> user running them, correct (the svn executable isn't setuid or setgid)? If the user can run the mknod command, how is letting svn
> do the same any different?
The idea here is to protect the user from the server, not to protect the
operating system from the user.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Re: Proposal: Support for versioning symlinks and other special files.
Posted by Bruce Elrick <br...@elrick.ca>.
Greg Hudson wrote:
> On Mon, 2004-06-28 at 09:03, Josh Pieper wrote:
>
>>First, only symlinks are supported, however support for character
>>devices, block devices, sockets, and FIFOs would mostly be similar to
>>that for symlinks.
>
>
> I'm concerned about the security implications of allowing the server to
> instruct the client to create device files. So I'd say we should leave
> that out in the absence of (1) a clear demand, and (2) enough
> infrastructure so that the user has to explicitly turn on special device
> support in client-side configuration before it works.
>
Wouldn't standard OS permissions on the client take care of this? The client process runs with no greater priveledges than the
user running them, correct (the svn executable isn't setuid or setgid)? If the user can run the mknod command, how is letting svn
do the same any different?
If the sysadmin wants to remove the ability of users to create device special files, they should be mounting user-writable
filesystems with the nodev option. If they want to allow very specific access, then they would be making the mknod command not
runnable by root and allowing sudo access with specific arguments or creating a wrapper. And then they'd have to not allow the
user to compile programs, because they'll write their own programs that call the mknod system call. But even if you don't provide
your users compilers, are you also preventing them from uploading a compiler executable?
By all means don't add this functionality because of lack of demand, but I'm not sure security is a valid objection.
Cheers!
Bruce
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Re: Proposal: Support for versioning symlinks and other special
files.
Posted by Greg Hudson <gh...@MIT.EDU>.
On Mon, 2004-06-28 at 09:03, Josh Pieper wrote:
> First, only symlinks are supported, however support for character
> devices, block devices, sockets, and FIFOs would mostly be similar to
> that for symlinks.
I'm concerned about the security implications of allowing the server to
instruct the client to create device files. So I'd say we should leave
that out in the absence of (1) a clear demand, and (2) enough
infrastructure so that the user has to explicitly turn on special device
support in client-side configuration before it works.
> One other question about the patch. In it, I change the behavior of
> svn_io_check_path to return svn_node_file for any special file,
> instead of svn_node_unknown. This is still in line with the docstring
> for the function, but is a behavior change. Is this acceptable within
> the 1.x line of development, or should it get a new API routine while
> deprecating the old?
That should be fine for 1.x. For any behavior change which doesn't
affect the function signature, the rule is that we try to guess whether
the change is likely to cause problems. This change is highly unlikely
to cause any problems.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org