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

[PATCH] auto-props

From: Martin Furter <mf_at_rola.ch>
Date: 2003-08-20 02:05:37 CEST

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

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.