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

[PATCH and TEST] Re: svn add horkage (and exposing libsvn_wc's ignore functionality)

From: <epg_at_pretzelnet.org>
Date: 2003-01-25 02:38:56 CET

Karl Fogel kfogel@newton.ch.collab.net writes:

 Also, if you have time to add a regression test, that would be great.
 Should be pretty short simple, for this.

Let me know when you guys are done battling out where this
functionality should live. I will then post an updated patch.
In the meantime, here is the patch again, this time with the log
message again, and now with a regression test. It's only my
second test--the other was a test for issue 1084 earlier
today--so both of these probably merit a more careful review.

Log message and patch:

A recursive svn add was scheduling items matching the user's ignore
list for addition. Export svn_wc's ignores functionality and use that
in svn_client to correct this.

* subversion/include/svn_config.h:

  Add prototypes and documentation for svn_config_get_default_ignores
  and svn_config_is_ignored.

* subversion/libsvn_wc/status.c:

  (get_default_ignores): Moved to svn_config_get_default_ignores in
  libsvn_subr/config.c.

  (add_unversioned_items): Use svn_config_is_ignored.

  (get_dir_status): Use svn_config_is_ignored.

* subversion/libsvn_subr/config.c:

  (svn_config_get_default_ignores): New function, basically identical
  to the old get_default_ignores in libsvn_wc/status.c.

  (svn_config_is_ignored): New function, basically copied from the check
  in add_unversioned_items.

* subversion/libsvn_client/add.c:

  (add_dir_recursive): Use svn_config_is_ignored to avoid adding items
  matching the user's ignore list.

* subversion/tests/clients/cmdline/basic_tests.py:

  (basic_add_ignores): Regression test for this bug.

Index: subversion/include/svn_config.h
===================================================================
--- subversion/include/svn_config.h (revision 4559)
+++ subversion/include/svn_config.h (working copy)
@@ -207,6 +207,20 @@
 svn_error_t *svn_config_ensure (apr_pool_t *pool);
 
 
+/** Get the run-time configured list of ignore patterns, and store
+ * them in @a patterns. Allocate @a patterns and its contents in @a
+ * pool.
+ */
+svn_error_t *svn_config_get_default_ignores (apr_array_header_t **patterns,
+ apr_pool_t *pool);
+
+/** Determine whether a @a path matches the run-time configured list
+ * of ignore patterns, specified by the array @a ignores.
+ */
+svn_boolean_t svn_config_is_ignored (const char *path,
+ apr_array_header_t *ignores);
+
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
Index: subversion/libsvn_wc/status.c
===================================================================
--- subversion/libsvn_wc/status.c (revision 4559)
+++ subversion/libsvn_wc/status.c (working copy)
@@ -23,7 +23,6 @@
 #include apr_file_io.h
 #include apr_hash.h
 #include apr_time.h
-#include apr_fnmatch.h
 #include svn_pools.h
 #include svn_types.h
 #include svn_string.h
@@ -36,28 +35,6 @@
 #include props.h
 
 
-/* Get the run-time configured list of ignore patterns, and store them
- in *PATTERNS. Allocate *PATTERNS and its contents in POOL. */
-static svn_error_t *
-get_default_ignores (apr_array_header_t **patterns,
- apr_pool_t *pool)
-{
- struct svn_config_t *cfg;
- const char *val;
-
- /* Check the Subversion run-time configuration for global ignores.
- If no configuration value exists, we fall back to our defaults. */
- SVN_ERR (svn_config_read_config (cfg, pool));
- svn_config_get (cfg, val, miscellany, global-ignores,
- *.o *.lo *.la #*# .*.rej *.rej .*~ *~ .#*);
- *patterns = apr_array_make (pool, 16, sizeof (const char *));
-
- /* Split the patterns on whitespace, and stuff them into *PATTERNS. */
- svn_cstring_split_append (*patterns, val, \n\r\t\v , FALSE, pool);
- return SVN_NO_ERROR;
-}
-
-
 /* Helper routine: add to *PATTERNS patterns from the value of
    the SVN_PROP_IGNORE property set on DIRPATH. If there is no such
    property, or the property contains no patterns, do nothing.
@@ -433,7 +410,6 @@
       apr_ssize_t klen;
       void *val;
       const char *keystring;
- int i;
       int ignore_me;
       const char *printable_path;
       svn_node_kind_t *path_kind;
@@ -450,22 +426,8 @@
       if (! strcmp (keystring, SVN_WC_ADM_DIR_NAME))
         continue;
 
- ignore_me = 0;
+ ignore_me = svn_config_is_ignored (keystring, patterns);
 
- /* See if any of the ignore patterns we have matches our
- keystring. */
- for (i = 0; patterns (i patterns-nelts); i++)
- {
- const char *pat = (((const char **) (patterns)-elts))[i];
-
- /* Try to match current_entry_name to pat. */
- if (APR_SUCCESS == apr_fnmatch (pat, keystring, FNM_PERIOD))
- {
- ignore_me = 1;
- break;
- }
- }
-
       /* If we aren't ignoring it, add a status structure for this
          dirent. */
       if (no_ignore || ! ignore_me)
@@ -557,7 +519,7 @@
   SVN_ERR (svn_wc_entries_read (entries, adm_access, FALSE, pool));
 
   /* Read the default ignores from the config files. */
- SVN_ERR (get_default_ignores (ignores, pool));
+ SVN_ERR (svn_config_get_default_ignores (ignores, pool));
 
   /* Add the unversioned items to the status output. */
   SVN_ERR (add_unversioned_items (path, adm_access, entries, statushash,
Index: subversion/libsvn_subr/config.c
===================================================================
--- subversion/libsvn_subr/config.c (revision 4559)
+++ subversion/libsvn_subr/config.c (working copy)
@@ -22,6 +22,7 @@
 #define APR_WANT_MEMFUNC
 #include apr_want.h
 
+#include apr_fnmatch.h
 #include apr_lib.h
 #include apr_user.h
 #include svn_error.h
@@ -533,4 +534,40 @@
   gb.pool = pool;
   svn_config_enumerate (cfg, master_section, search_groups, );
   return gb.match;
+}
+
+svn_error_t *
+svn_config_get_default_ignores (apr_array_header_t **patterns,
+ apr_pool_t *pool)
+{
+ struct svn_config_t *cfg;
+ const char *val;
+
+ /* Check the Subversion run-time configuration for global ignores.
+ If no configuration value exists, we fall back to our defaults. */
+ SVN_ERR (svn_config_read_config (cfg, pool));
+ svn_config_get (cfg, val, miscellany, global-ignores,
+ *.o *.lo *.la #*# .*.rej *.rej .*~ *~ .#*);
+ *patterns = apr_array_make (pool, 16, sizeof (const char *));
+
+ /* Split the patterns on whitespace, and stuff them into *PATTERNS. */
+ svn_cstring_split_append (*patterns, val, \n\r\t\v , FALSE, pool);
+ return SVN_NO_ERROR;
+}
+
+svn_boolean_t
+svn_config_is_ignored (const char *path,
+ apr_array_header_t *ignores)
+{
+ int i;
+
+ for (i = 0; ignores (i ignores-nelts); i++)
+ {
+ const char *pat = (((const char **) (ignores)-elts))[i];
+
+ if (APR_SUCCESS == apr_fnmatch (pat, path, FNM_PERIOD))
+ return TRUE;
+ }
+
+ return FALSE;
 }
Index: subversion/libsvn_client/add.c
===================================================================
--- subversion/libsvn_client/add.c (revision 4559)
+++ subversion/libsvn_client/add.c (working copy)
@@ -25,6 +25,7 @@
 #include string.h
 #include svn_wc.h
 #include svn_client.h
+#include svn_config.h
 #include svn_string.h
 #include svn_pools.h
 #include svn_error.h
@@ -49,6 +50,7 @@
   apr_pool_t *subpool;
   apr_int32_t flags = APR_FINFO_TYPE | APR_FINFO_NAME;
   svn_wc_adm_access_t *dir_access;
+ apr_array_header_t *ignores;
 
   /* Add this directory to revision control. */
   SVN_ERR (svn_wc_add (dirname, adm_access,
@@ -57,6 +59,8 @@
 
   SVN_ERR (svn_wc_adm_retrieve (dir_access, adm_access, dirname, pool));
 
+ SVN_ERR (svn_config_get_default_ignores (ignores, pool));
+
   /* Create a subpool for iterative memory control. */
   subpool = svn_pool_create (pool);
 
@@ -77,6 +81,9 @@
       if (this_entry.name[0] == '.'
            (this_entry.name[1] == '\0'
               || (this_entry.name[1] == '.' this_entry.name[2] == '\0')))
+ continue;
+
+ if (svn_config_is_ignored (this_entry.name, ignores))
         continue;
 
       /* Construct the full path of the entry. */
Index: subversion/tests/clients/cmdline/basic_tests.py
===================================================================
--- subversion/tests/clients/cmdline/basic_tests.py (revision 4559)
+++ subversion/tests/clients/cmdline/basic_tests.py (working copy)
@@ -1481,6 +1481,48 @@
                                         os.path.join(wc_dir, 'A', 'D', 'G'))
   if errput: return 1
 
+
+#----------------------------------------------------------------------
+def basic_add_ignores(sbox):
+ 'ignored files in the added directory should not be added'
+
+ # The bug was that
+ #
+ # $ svn add dir
+ #
+ # where dir contains some items that match the ignore list and some
+ # do not would add all items, ignored or not.
+ #
+ # This bug was fixed in revision XXX, by testing each item with the
+ # new svn_config_is_ignored function.
+
+ if sbox.build():
+ return 1
+
+ wc_dir = sbox.wc_dir
+
+ dir_path = os.path.join(wc_dir, 'dir')
+ foo_c_path = os.path.join(dir_path, 'foo.c')
+ foo_o_path = os.path.join(dir_path, 'foo.o')
+
+ os.mkdir(dir_path, 0755)
+ open(foo_c_path, 'w')
+ open(foo_o_path, 'w')
+
+ (output, errput) = svntest.main.run_svn (None, 'add', dir_path)
+
+ if not output:
+ return 1
+
+ for line in output:
+ # If we see foo.o in the add output, fail the test.
+ if re.match(r'^A\s+.*foo.o$', line):
+ return 1
+
+ # Else never matched the unwanted output, so the test passed.
+ return 0
+
+
 #----------------------------------------------------------------------
 
 ########################################################################
@@ -1507,6 +1549,7 @@
               Skip(basic_import_executable, (os.name != 'posix')),
               nonexistent_repository,
               basic_auth_cache,
+ basic_add_ignores,
               ### todo: more tests needed:
               ### test svn rm http://some_url
               ### not sure this file is the right place, though.

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Sat Oct 14 02:16:27 2006

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