Hi All
Here is the auto-prop patch again.
The only thing which is missing are the test cases. Because i don't know
python it's probably better if someone else adds the tests. Ofcourse i'd
help as much as possible.
Thanks
Martin
========= log message ==========
Automatic properties for 'svn add' and 'svn import' added.
They are defined in the config file and can be enabled/disabled in the
config and on the commandline. The config has 2 enable flags, one for add
and one for import.
* subversion/include/svn_config.h
(SVN_CONFIG_OPTION_ENABLE_AUTO_PROPS_*, SVN_CONFIG_SECTION_AUTO_PROPS)
New defines.
* subversion/libsvn_subr/config_file.c
(svn_config_ensure) Config entries added.
* subversion/libsvn_client/client.h
(svn_client__add_auto_props) Prototype added.
* subversion/libsvn_client/commit.c
(import_file) Call to svn_client__add_auto_props added, detection of
mimetype and executable modified.
* subversion/libsvn_client/add.c
(auto_props_baton_t) New struct, local usage only.
(auto_props_enumerator) New function, used by svn_client__add_auto_props.
(svn_client__add_auto_props) New function, adds automatic properties.
(add_dir_recursive) Call to svn_client__add_auto_props added.
(svn_client__add) Call to svn_client__add_auto_props added.
* subversion/clients/cmdline/cl.h
(svn_cl__longopt_t) Added svn_cl__enable_autoprops_opt and
svn_cl__disable_autoprops_opt.
(svn_cl__opt_state_t) Added enable_autoprops and disable_autoprops.
* subversion/clients/cmdline/main.c
(svn_cl__options, svn_cl__cmd_table, main) Added svn_cl__enable_autoprops_opt
and svn_cl__disable_autoprops_opt, set them in the config in main().
========= patch ==========
Index: subversion/include/svn_config.h
===================================================================
--- subversion/include/svn_config.h (revision 6732)
+++ subversion/include/svn_config.h (working copy)
@@ -82,7 +82,10 @@
#define SVN_CONFIG_OPTION_GLOBAL_IGNORES "global-ignores"
#define SVN_CONFIG_OPTION_LOG_ENCODING "log-encoding"
#define SVN_CONFIG_OPTION_TEMPLATE_ROOT "template-root"
+#define SVN_CONFIG_OPTION_ENABLE_AUTO_PROPS_ADD "enable-auto-props-add"
+#define SVN_CONFIG_OPTION_ENABLE_AUTO_PROPS_IMP "enable-auto-props-imp"
#define SVN_CONFIG_SECTION_TUNNELS "tunnels"
+#define SVN_CONFIG_SECTION_AUTO_PROPS "auto-props"
/*** Configuration Default Values ***/
Index: subversion/libsvn_subr/config_file.c
===================================================================
--- subversion/libsvn_subr/config_file.c (revision 6732)
+++ subversion/libsvn_subr/config_file.c (working copy)
@@ -956,7 +956,30 @@
"# global-ignores = " SVN_CONFIG_DEFAULT_GLOBAL_IGNORES "\n"
"### Set log-encoding to the default encoding for log messages\n"
"# log-encoding = latin1\n"
+ "### Enable automatic properties for 'svn add' (true | false).\n"
+ "### Automatic properties are defined in the section 'auto-props'.\n"
+ "# enable-auto-props-add = true\n"
+ "### Enable automatic properties for 'svn import' (true | false).\n"
+ "# enable-auto-props-imp = true\n"
"\n"
+ "### Section for configuring automatic properties.\n"
+ "# [auto-props]\n"
+ "### Default properties.\n"
+ "# * = svn:mimetype=application/octet-stream\n"
+ "### Suffix match entries.\n"
+ "# *.c = svn:eol-style=native\n"
+ "# *.cpp = svn:eol-style=native\n"
+ "# *.h = svn:eol-style=native\n"
+ "# *.dsp = svn:eol-style=CRLF\n"
+ "# *.dsw = svn:eol-style=CRLF\n"
+ "# *.sh = svn:eol-style=native;svn:executable\n"
+ "# *.txt = svn:eol-style=native\n"
+ "# *.png = svn:mimetype=image/png\n"
+ "# *.jpg = svn:mimetype=image/jpeg\n"
+ "### Exact match entries.\n"
+ "# Makefile = svn:eol-style=native\n"
+ "\n"
+ "\n"
"### See http://subversion.tigris.org/issues/show_bug.cgi?id=668\n"
"### for what else will soon be customized in this file.\n";
Index: subversion/libsvn_client/client.h
===================================================================
--- subversion/libsvn_client/client.h (revision 6732)
+++ subversion/libsvn_client/client.h (working copy)
@@ -233,6 +233,41 @@
/*** Add/delete ***/
+/* Method which automatically adds properties.
+
+ path, ctx and pool must always be valid. When adding adm_access must
+ be valid and editor must be NULL, when importing editor, file_baton,
+ mimetype and executable must be valid.
+
+ First the function checks that auto-props is enabled for add or import.
+ Then i enumerates the 'auto-props' section and tries to find a match.
+ There are 3 types of match: "*" is the default entry and has lowest
+ priority, "*XXX" is a suffix match and the longer the match the higher
+ it's priority, names not beginning with '*' are exact matches and have
+ the highest priority. When a name matches the value of the option.
+
+ The format of the value is [propname[=value][;name[=val]]...]
+
+ @param path a filename
+ @param ctx the client context
+ @param pool apr memory pool
+ @param adm_access whatever ???, used when adding
+ @param editor editor, used when importing
+ @param file_baton file baton for editor, used when importing
+ @param mimetype pointer for returning mimetype, used when importing
+ @param executable pointer for returning executable, used when importing
+ @return an svn_error_t or SVN_NO_ERROR when everything went OK
+*/
+svn_error_t *
+svn_client__add_auto_props (const char *path,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *pool,
+ svn_wc_adm_access_t *adm_access,
+ const svn_delta_editor_t *editor,
+ void *file_baton,
+ const char **mimetype,
+ int *executable);
+
/* The main logic of the public svn_client_add; the only difference
is that this function uses an existing access baton.
(svn_client_add just generates an access baton and calls this func.) */
Index: subversion/libsvn_client/commit.c
===================================================================
--- subversion/libsvn_client/commit.c (revision 6732)
+++ subversion/libsvn_client/commit.c (working copy)
@@ -105,8 +105,8 @@
apr_pool_t *pool)
{
void *file_baton;
- const char *mimetype;
- svn_boolean_t executable;
+ const char *mimetype = NULL;
+ svn_boolean_t executable = FALSE;
unsigned char digest[MD5_DIGESTSIZE];
const char *text_checksum;
@@ -114,21 +114,27 @@
SVN_ERR (editor->add_file (edit_path, dir_baton, NULL, SVN_INVALID_REVNUM,
pool, &file_baton));
+ /* add automatic properties */
+ SVN_ERR (svn_client__add_auto_props (path, ctx, pool, NULL, editor,
+ file_baton, &mimetype, &executable));
+
/* If the file has a discernable mimetype, add that as a property to
the file. */
- SVN_ERR (svn_io_detect_mimetype (&mimetype, path, pool));
+ if (!mimetype)
+ SVN_ERR (svn_io_detect_mimetype (&mimetype, path, pool));
if (mimetype)
SVN_ERR (editor->change_file_prop (file_baton, SVN_PROP_MIME_TYPE,
svn_string_create (mimetype, pool),
pool));
/* If the file is executable, add that as a property to the file. */
- SVN_ERR (svn_io_is_file_executable (&executable, path, pool));
+ if (!executable)
+ SVN_ERR (svn_io_is_file_executable (&executable, path, pool));
if (executable)
SVN_ERR (editor->change_file_prop (file_baton, SVN_PROP_EXECUTABLE,
svn_string_create ("", pool),
pool));
-
+
if (ctx->notify_func)
(*ctx->notify_func) (ctx->notify_baton,
path,
Index: subversion/libsvn_client/add.c
===================================================================
--- subversion/libsvn_client/add.c (revision 6732)
+++ subversion/libsvn_client/add.c (working copy)
@@ -30,12 +30,165 @@
#include "svn_error.h"
#include "svn_path.h"
#include "svn_io.h"
+#include "svn_config.h"
#include "client.h"
/*** Code. ***/
+/* baton for the auto_props_enumerator function */
+typedef struct {
+ char *filename;
+ int name_len;
+ char *props;
+ int match_len;
+ apr_pool_t *pool;
+} auto_props_baton_t;
+
+/* enumerate through auto-props entries and store value if name matches */
+static svn_boolean_t
+auto_props_enumerator (const char *name,
+ const char *value,
+ void *baton)
+{
+ auto_props_baton_t *autoprops = (auto_props_baton_t*)baton;
+ int len;
+
+ if (!name)
+ return TRUE;
+ if (!baton)
+ return FALSE;
+ if (!value)
+ value = "";
+ if (!strcmp (name, "*") )
+ {
+ /* default properties */
+ if (autoprops->match_len == -1)
+ {
+ autoprops->props = apr_pstrdup(autoprops->pool, value);
+ autoprops->match_len = 0;
+ }
+ return TRUE;
+ }
+ if (name[0] == '*')
+ {
+ /* properties for a suffix match */
+ len = strlen (name+1);
+ if (autoprops->match_len >= len)
+ return TRUE;
+ if (len > autoprops->name_len)
+ return TRUE;
+ if (!strcmp (name+1, autoprops->filename+autoprops->name_len-len))
+ {
+ autoprops->props = apr_pstrdup(autoprops->pool, value);
+ autoprops->match_len = len;
+ }
+ return TRUE;
+ }
+ if (!strcmp(name, autoprops->filename))
+ {
+ /* properties for an exact match */
+ autoprops->props = apr_pstrdup(autoprops->pool, value);
+ /* found an exact match so stop enumerating */
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/* adds automatic properties, for a description look into client.h */
+svn_error_t *
+svn_client__add_auto_props (const char *path,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *pool,
+ svn_wc_adm_access_t *adm_access,
+ const svn_delta_editor_t *editor,
+ void *file_baton,
+ const char **mimetype,
+ int *executable)
+{
+ svn_config_t *cfg = NULL;
+ auto_props_baton_t autoprops;
+ char *property;
+ char *last_token;
+ char *value;
+ const char *cfgvalue = 0;
+ svn_error_t *err;
+
+ /* check that we have config */
+ if (!ctx->config)
+ return SVN_NO_ERROR;
+ cfg = apr_hash_get (ctx->config, SVN_CONFIG_CATEGORY_CONFIG,
+ APR_HASH_KEY_STRING);
+ if (!cfg)
+ return SVN_NO_ERROR;
+
+ /* check that auto props is enabled */
+ if (editor)
+ svn_config_get (cfg, &cfgvalue, SVN_CONFIG_SECTION_MISCELLANY,
+ SVN_CONFIG_OPTION_ENABLE_AUTO_PROPS_IMP, "false");
+ else
+ svn_config_get (cfg, &cfgvalue, SVN_CONFIG_SECTION_MISCELLANY,
+ SVN_CONFIG_OPTION_ENABLE_AUTO_PROPS_ADD, "false");
+ if (!cfgvalue || strcmp(cfgvalue, "true"))
+ return SVN_NO_ERROR;
+
+ /* search for auto props */
+ autoprops.filename = svn_path_basename (path, pool);
+ autoprops.name_len = strlen (autoprops.filename);
+ autoprops.props = NULL;
+ autoprops.match_len = -1;
+ autoprops.pool = pool;
+ svn_config_enumerate (cfg, SVN_CONFIG_SECTION_AUTO_PROPS,
+ auto_props_enumerator, &autoprops);
+
+ /* did we find auto props ? */
+ if (!autoprops.props)
+ return SVN_NO_ERROR;
+ if (strlen (autoprops.props) == 0)
+ return SVN_NO_ERROR;
+
+ /* add properties */
+ last_token = NULL;
+ property = apr_strtok (autoprops.props, ";", &last_token);
+ while (property)
+ {
+ svn_string_t valstr;
+ value = strchr (property, '=');
+ if (value)
+ {
+ *value = 0;
+ value++;
+ apr_collapse_spaces (value, value);
+ }
+ else
+ value = "";
+ apr_collapse_spaces (property, property);
+ valstr.data = value;
+ valstr.len = strlen (value);
+ if (strlen (property))
+ {
+ if (editor)
+ {
+ /* SVN_PROP_MIME_TYPE and SVN_PROP_EXECUTABLE
+ * are returned to the caller */
+ if (!strcmp(property, SVN_PROP_MIME_TYPE))
+ *mimetype = apr_pstrdup (pool, value);
+ else if (!strcmp (property, SVN_PROP_EXECUTABLE))
+ *executable = TRUE;
+ else
+ err = editor->change_file_prop (file_baton, property,
+ &valstr, pool);
+ }
+ else
+ err = svn_wc_prop_set (property, &valstr, path, adm_access, pool);
+ }
+ if (err)
+ return err;
+ property = apr_strtok (NULL, ";", &last_token);
+ }
+}
+
static svn_error_t *
add_dir_recursive (const char *dirname,
svn_wc_adm_access_t *adm_access,
@@ -97,9 +250,13 @@
SVN_ERR (add_dir_recursive (fullpath, dir_access, ctx, subpool));
else if (this_entry.filetype == APR_REG)
- SVN_ERR (svn_wc_add (fullpath, dir_access, NULL, SVN_INVALID_REVNUM,
- ctx->cancel_func, ctx->cancel_baton,
- ctx->notify_func, ctx->notify_baton, subpool));
+ {
+ SVN_ERR (svn_wc_add (fullpath, dir_access, NULL, SVN_INVALID_REVNUM,
+ ctx->cancel_func, ctx->cancel_baton,
+ ctx->notify_func, ctx->notify_baton, subpool));
+ SVN_ERR (svn_client__add_auto_props (fullpath, ctx, subpool,
+ adm_access, NULL, NULL, NULL, NULL));
+ }
/* Clean out the per-iteration pool. */
svn_pool_clear (subpool);
@@ -145,9 +302,14 @@
if ((kind == svn_node_dir) && recursive)
err = add_dir_recursive (path, adm_access, ctx, pool);
else
- err = svn_wc_add (path, adm_access, NULL, SVN_INVALID_REVNUM,
- ctx->cancel_func, ctx->cancel_baton,
- ctx->notify_func, ctx->notify_baton, pool);
+ {
+ err = svn_wc_add (path, adm_access, NULL, SVN_INVALID_REVNUM,
+ ctx->cancel_func, ctx->cancel_baton,
+ ctx->notify_func, ctx->notify_baton, pool);
+ if (!err)
+ err = svn_client__add_auto_props (path, ctx, pool, adm_access,
+ NULL, NULL, NULL, NULL);
+ }
return err;
}
Index: subversion/clients/cmdline/cl.h
===================================================================
--- subversion/clients/cmdline/cl.h (revision 6732)
+++ subversion/clients/cmdline/cl.h (working copy)
@@ -67,7 +67,9 @@
svn_cl__notice_ancestry_opt,
svn_cl__editor_cmd_opt,
svn_cl__old_cmd_opt,
- svn_cl__new_cmd_opt
+ svn_cl__new_cmd_opt,
+ svn_cl__enable_autoprops_opt,
+ svn_cl__disable_autoprops_opt
} svn_cl__longopt_t;
@@ -119,6 +121,8 @@
const char *old_target; /* diff target */
const char *new_target; /* diff target */
svn_boolean_t relocate; /* rewrite urls (svn switch) */
+ svn_boolean_t enable_autoprops; /* automatic properties (svn add|import) */
+ svn_boolean_t disable_autoprops; /* automatic properties (svn add|import) */
} svn_cl__opt_state_t;
Index: subversion/clients/cmdline/main.c
===================================================================
--- subversion/clients/cmdline/main.c (revision 6732)
+++ subversion/clients/cmdline/main.c (working copy)
@@ -121,6 +121,10 @@
"operate on a revision property (use with -r)"},
{"relocate", svn_cl__relocate_opt, 0,
"relocate via url-rewriting"},
+ {"auto-props", svn_cl__enable_autoprops_opt, 0,
+ "enable automatic properties"},
+ {"no-auto-props", svn_cl__disable_autoprops_opt, 0,
+ "disable automatic properties"},
{0, 0, 0, 0}
};
@@ -147,7 +151,8 @@
"Put files and directories under revision control, scheduling\n"
"them for addition to repository. They will be added in next commit.\n"
"usage: add PATH...\n",
- {svn_cl__targets_opt, 'N', 'q'} },
+ {svn_cl__targets_opt, 'N', 'q', svn_cl__enable_autoprops_opt,
+ svn_cl__disable_autoprops_opt} },
{ "cat", svn_cl__cat, {0},
"Output the content of specified files or URLs.\n"
@@ -255,7 +260,8 @@
" If PATH is omitted '.' is assumed. Parent directories are created\n"
" as necessary in the repository.\n",
{'m', 'F', 'q', 'N', SVN_CL__AUTH_OPTIONS, svn_cl__force_log_opt,
- svn_cl__editor_cmd_opt, svn_cl__encoding_opt} },
+ svn_cl__editor_cmd_opt, svn_cl__encoding_opt,
+ svn_cl__enable_autoprops_opt, svn_cl__disable_autoprops_opt} },
{ "info", svn_cl__info, {0},
"Display info about a resource.\n"
@@ -809,6 +815,30 @@
case svn_cl__new_cmd_opt:
opt_state.new_target = apr_pstrdup (pool, opt_arg);
break;
+ case svn_cl__enable_autoprops_opt:
+ if (opt_state.disable_autoprops)
+ {
+ err = svn_error_create (SVN_ERR_CL_MUTUALLY_EXCLUSIVE_ARGS, NULL,
+ "--auto-props and --no-autoprops are "
+ "mutually exclusive.");
+ svn_handle_error (err, stderr, FALSE);
+ svn_pool_destroy (pool);
+ return EXIT_FAILURE;
+ }
+ opt_state.enable_autoprops = TRUE;
+ break;
+ case svn_cl__disable_autoprops_opt:
+ if (opt_state.enable_autoprops)
+ {
+ err = svn_error_create (SVN_ERR_CL_MUTUALLY_EXCLUSIVE_ARGS, NULL,
+ "--auto-props and --no-autoprops are "
+ "mutually exclusive.");
+ svn_handle_error (err, stderr, FALSE);
+ svn_pool_destroy (pool);
+ return EXIT_FAILURE;
+ }
+ opt_state.disable_autoprops = TRUE;
+ break;
default:
/* Hmmm. Perhaps this would be a good place to squirrel away
opts that commands like svn diff might need. Hmmm indeed. */
@@ -964,6 +994,23 @@
svn_config_set (cfg, SVN_CONFIG_SECTION_HELPERS,
SVN_CONFIG_OPTION_DIFF3_CMD, opt_state.merge_cmd);
+ /* Update auto-props-enable option for add/import commands */
+ if (subcommand->cmd_func == svn_cl__add
+ || subcommand->cmd_func == svn_cl__import)
+ {
+ char *cfgopt = (subcommand->cmd_func == svn_cl__add)
+ ? SVN_CONFIG_OPTION_ENABLE_AUTO_PROPS_ADD
+ : SVN_CONFIG_OPTION_ENABLE_AUTO_PROPS_IMP;
+ if (opt_state.enable_autoprops)
+ {
+ svn_config_set (cfg, SVN_CONFIG_SECTION_MISCELLANY, cfgopt, "true");
+ }
+ if (opt_state.disable_autoprops)
+ {
+ svn_config_set (cfg, SVN_CONFIG_SECTION_MISCELLANY, cfgopt, "false");
+ }
+ }
+
/* Set the log message callback function. Note that individual
subcommands will populate the ctx.log_msg_baton */
ctx.log_msg_func = svn_cl__get_log_message;
========================
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Wed Aug 20 02:07:32 2003