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

[rfc/patch] Fix issue 734, import should 'mkdir -p'

From: David Kimdon <dwhedon_at_debian.org>
Date: 2003-05-02 06:11:40 CEST

Hi,

Here's a fix that I'd like another set of eyes on. It passes 'make
check', of course. I'm not entirely sure that I'm doing the right
thing closing the directory batons while I'm doing the mkdir's. I'm
keeping just the last one, and the root baton open and closing the
intermediate batons.

Thanks,

-David

Fix issue #735: Create directories on import.

   * subversion/libsvn_client/commit.c (import) : Call mkdir on
     components of 'new_entry' prior to performing the actual import.

   * subversion/tests/clients/cmdline/basic_tests.py (basic_import) : Change
     existing test case to use a path to the third argument to import and
     verify that the new directories are created properly.

   * doc/book/book/ch03.xml : Change text and import example to show how
     subversion can create subdirectories on import.

   * doc/book/book/ch08.xml : Remove warning that the leading elements of
     the third argument to import must exist. Subversion will now create
     these directories.

Index: subversion/libsvn_client/commit.c
===================================================================
--- subversion/libsvn_client/commit.c (revision 5780)
+++ subversion/libsvn_client/commit.c (working copy)
@@ -341,6 +341,7 @@
   void *root_baton;
   svn_node_kind_t kind;
   apr_array_header_t *ignores;
+ void *new_dir_baton = NULL;
 
   /* Get a root dir baton. We pass an invalid revnum to open_root
      to mean "base this on the youngest revision". Should we have an
@@ -351,6 +352,42 @@
   /* Import a file or a directory tree. */
   SVN_ERR (svn_io_check_path (path, &kind, pool));
 
+ if (new_entry) {
+ apr_array_header_t *temp, *dirs;
+ const char **element;
+ const char *new_path = "";
+
+ temp = svn_path_decompose(new_entry, pool);
+ dirs = apr_array_make (pool, 1, sizeof(const char *));
+
+ /* If we are importing a file then new_entry's basename is
+ * the desired filename in the repository. We don't create
+ * a directory with that name. Discard the component. */
+ if (kind == svn_node_file) {
+ apr_array_pop(temp);
+ }
+
+ /* We can only pop paths off the array, and they won't come
+ * off in the order we want to create directories. Create
+ * another array that we can access in the desired order. */
+ while ((element = (const char **) apr_array_pop(temp))) {
+ *((const char **) apr_array_push(dirs)) = *element;
+ }
+
+ while ((element = (const char **) apr_array_pop(dirs))) {
+
+ if (new_dir_baton)
+ SVN_ERR (editor->close_directory (new_dir_baton, pool));
+
+ new_path = svn_path_join(new_path, *element, pool);
+
+ SVN_ERR (editor->add_directory (new_path, root_baton,
+ NULL, SVN_INVALID_REVNUM,
+ pool, &new_dir_baton));
+ }
+ }
+
+
   /* Note that there is no need to check whether PATH's basename is
      the same name that we reserve for our admistritave
      subdirectories. It would be strange, but not illegal to import
@@ -368,20 +405,13 @@
                 (SVN_ERR_NODE_UNKNOWN_KIND, NULL,
                  "new entry name required when importing a file");
 
- SVN_ERR (import_file (editor, root_baton,
+ SVN_ERR (import_file (editor,
+ new_dir_baton ? new_dir_baton : root_baton,
                                 path, new_entry, ctx, pool));
         }
     }
   else if (kind == svn_node_dir)
     {
- void *new_dir_baton = NULL;
-
- /* Grab a new baton, making two we'll have to close. */
- if (new_entry)
- SVN_ERR (editor->add_directory (new_entry, root_baton,
- NULL, SVN_INVALID_REVNUM,
- pool, &new_dir_baton));
-
 #if 0 /* Temporarily blocked out for consideration, see below. */
       /* If we activate this notification, then
        *
@@ -419,9 +449,6 @@
                            path, new_entry ? new_entry : "",
                            nonrecursive, excludes, ctx, pool));
 
- /* Close one baton or two. */
- if (new_dir_baton)
- SVN_ERR (editor->close_directory (new_dir_baton, pool));
     }
   else if (kind == svn_node_none)
     {
@@ -431,6 +458,8 @@
     }
 
   /* Close up the show; it's time to go home. */
+ if (new_dir_baton)
+ SVN_ERR (editor->close_directory (new_dir_baton, pool));
   SVN_ERR (editor->close_directory (root_baton, pool));
   SVN_ERR (editor->close_edit (edit_baton, pool));
 
Index: subversion/tests/clients/cmdline/basic_tests.py
===================================================================
--- subversion/tests/clients/cmdline/basic_tests.py (revision 5780)
+++ subversion/tests/clients/cmdline/basic_tests.py (working copy)
@@ -1148,7 +1148,7 @@
     'Cannot change node kind', None, [], 'import',
     '--username', svntest.main.wc_author,
     '--password', svntest.main.wc_passwd,
- '-m', 'Log message for new import', url, new_path, 'new_file')
+ '-m', 'Log message for new import', url, new_path, 'dir1/dir2/new_file')
 
   lastline = string.strip(output.pop())
   cm = re.compile ("(Committed|Imported) revision [0-9]+.")
@@ -1163,19 +1163,23 @@
   # Create expected disk tree for the update (disregarding props)
   expected_disk = svntest.main.greek_state.copy()
   expected_disk.add({
- 'new_file' : Item('some text'),
+ os.path.join('dir1', 'dir2', 'new_file') : Item('some text'),
     })
 
   # Create expected status tree for the update (disregarding props).
   # Newly imported file should be at revision 2.
   expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
   expected_status.add({
- 'new_file' : Item(status=' ', wc_rev=2, repos_rev=2),
+ 'dir1' : Item(status=' ', wc_rev=2, repos_rev=2),
+ 'dir1/dir2' : Item(status=' ', wc_rev=2, repos_rev=2),
+ 'dir1/dir2/new_file' : Item(status=' ', wc_rev=2, repos_rev=2),
     })
 
   # Create expected output tree for the update.
   expected_output = svntest.wc.State(wc_dir, {
- 'new_file' : Item(status='A '),
+ 'dir1' : Item(status='A '),
+ 'dir1/dir2' : Item(status='A '),
+ 'dir1/dir2/new_file' : Item(status='A '),
   })
 
   # do update and check three ways
Index: doc/book/book/ch03.xml
===================================================================
--- doc/book/book/ch03.xml (revision 5780)
+++ doc/book/book/ch03.xml (working copy)
@@ -1996,11 +1996,11 @@
 
       <para>If you give <command>svn import</command> a third
         argument, it will use the argument as the name of a new
- subdirectory to create within the URL.</para>
+ path to create within the URL.</para>
 
       <screen>
 $ svnadmin create /usr/local/svn/newrepos
-$ svn import file:///usr/local/svn/newrepos mytree fooproject
+$ svn import file:///usr/local/svn/newrepos mytree fooproject/trunk
 Adding mytree/foo.c
 Adding mytree/bar.c
 Adding mytree/subdir
@@ -2012,10 +2012,10 @@
       <para>The repository would now look like this:</para>
 
       <screen>
-/fooproject/foo.c
-/fooproject/bar.c
-/fooproject/subdir
-/fooproject/subdir/quux.h
+/fooproject/trunk/foo.c
+/fooproject/trunk/bar.c
+/fooproject/trunk/subdir
+/fooproject/trunk/subdir/quux.h
       </screen>
 
     </sect2>
Index: doc/book/book/ch08.xml
===================================================================
--- doc/book/book/ch08.xml (revision 5780)
+++ doc/book/book/ch08.xml (working copy)
@@ -1366,10 +1366,7 @@
             </screen>
 
             <para>This imports the local directory 'myproj' into
- 'trunk/vendors' in your repository. The directory
- 'trunk/vendors' must exist before you import into
- it&mdash;<command>svn import</command> will not
- recursively create directories for you:</para>
+ 'trunk/vendors' in your repository:</para>
 
             <screen>
 $ svn import -m "New import" http://svn.red-bean.com/repos/test myproj trunk/vendors/myproj

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Fri May 2 06:14:14 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.