Rev 3618: (robertc) Teach export to export subdirectories as well as entire in file:///home/pqm/archives/thelove/bzr/%2Btrunk/

Canonical.com Patch Queue Manager pqm at pqm.ubuntu.com
Mon Aug 11 04:39:35 BST 2008


At file:///home/pqm/archives/thelove/bzr/%2Btrunk/

------------------------------------------------------------
revno: 3618
revision-id: pqm at pqm.ubuntu.com-20080811033925-rwcu69eiq0zg0buv
parent: pqm at pqm.ubuntu.com-20080809215057-4tnxs63ngab9gm8a
parent: robertc at robertcollins.net-20080808065948-io0c6pfo305ss5vj
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Mon 2008-08-11 04:39:25 +0100
message:
  (robertc) Teach export to export subdirectories as well as entire
  	branches. (Robert Collins)
modified:
  NEWS                           NEWS-20050323055033-4e00b5db738777ff
  bzrlib/__init__.py             __init__.py-20050309040759-33e65acf91bbcd5d
  bzrlib/builtins.py             builtins.py-20050830033751-fc01482b9ca23183
  bzrlib/export/__init__.py      __init__.py-20051114235828-1ba62cb4062304e6
  bzrlib/export/dir_exporter.py  dir_exporter.py-20051114235828-b51397f56bc7b117
  bzrlib/export/tar_exporter.py  tar_exporter.py-20051114235828-1f6349a2f090a5d0
  bzrlib/export/zip_exporter.py  zip_exporter.py-20051114235828-8f57f954fba6497e
  bzrlib/tests/blackbox/test_export.py test_export.py-20051229024010-e6c26658e460fb1c
    ------------------------------------------------------------
    revno: 3613.2.2
    revision-id: robertc at robertcollins.net-20080808065948-io0c6pfo305ss5vj
    parent: robertc at robertcollins.net-20080808052558-b3xkprmd19buq12s
    committer: Robert Collins <robertc at robertcollins.net>
    branch nick: export
    timestamp: Fri 2008-08-08 16:59:48 +1000
    message:
      Refactor exporters to remove obvious duplication to a helper function.
    modified:
      bzrlib/export/__init__.py      __init__.py-20051114235828-1ba62cb4062304e6
      bzrlib/export/dir_exporter.py  dir_exporter.py-20051114235828-b51397f56bc7b117
      bzrlib/export/tar_exporter.py  tar_exporter.py-20051114235828-1f6349a2f090a5d0
      bzrlib/export/zip_exporter.py  zip_exporter.py-20051114235828-8f57f954fba6497e
    ------------------------------------------------------------
    revno: 3613.2.1
    revision-id: robertc at robertcollins.net-20080808052558-b3xkprmd19buq12s
    parent: pqm at pqm.ubuntu.com-20080807005717-qxnuq9je71bt9tcs
    committer: Robert Collins <robertc at robertcollins.net>
    branch nick: export
    timestamp: Fri 2008-08-08 15:25:58 +1000
    message:
      Teach export how to export a subdirectory. (Robert Collins)
    modified:
      NEWS                           NEWS-20050323055033-4e00b5db738777ff
      bzrlib/__init__.py             __init__.py-20050309040759-33e65acf91bbcd5d
      bzrlib/builtins.py             builtins.py-20050830033751-fc01482b9ca23183
      bzrlib/export/__init__.py      __init__.py-20051114235828-1ba62cb4062304e6
      bzrlib/export/dir_exporter.py  dir_exporter.py-20051114235828-b51397f56bc7b117
      bzrlib/export/tar_exporter.py  tar_exporter.py-20051114235828-1f6349a2f090a5d0
      bzrlib/export/zip_exporter.py  zip_exporter.py-20051114235828-8f57f954fba6497e
      bzrlib/tests/blackbox/test_export.py test_export.py-20051229024010-e6c26658e460fb1c
=== modified file 'NEWS'
--- a/NEWS	2008-08-08 06:17:19 +0000
+++ b/NEWS	2008-08-11 03:39:25 +0000
@@ -11,6 +11,9 @@
 
   IMPROVEMENTS:
 
+    * ``bzr export`` can now export a subdirectory of a project.
+      (Robert Collins)
+
   BUG FIXES:
 
     * ``bzr upgrade`` on remote branches accessed via bzr:// and
@@ -31,6 +34,8 @@
 
   API CHANGES:
 
+    * Exporters now take 4 parameters. (Robert Collins)
+
   INTERNALS:
 
 

=== modified file 'bzrlib/__init__.py'
--- a/bzrlib/__init__.py	2008-08-06 08:23:43 +0000
+++ b/bzrlib/__init__.py	2008-08-08 05:25:58 +0000
@@ -44,8 +44,8 @@
 version_info = (1, 7, 0, 'dev', 0)
 
 
-# API compatibility version: bzrlib is currently API compatible with 1.6.
-api_minimum_version = (1, 6, 0)
+# API compatibility version: bzrlib is currently API compatible with 1.7.
+api_minimum_version = (1, 7, 0)
 
 def _format_version_tuple(version_info):
     """Turn a version number 3-tuple or 5-tuple into a short string.

=== modified file 'bzrlib/builtins.py'
--- a/bzrlib/builtins.py	2008-08-08 05:44:44 +0000
+++ b/bzrlib/builtins.py	2008-08-11 03:39:25 +0000
@@ -2018,7 +2018,7 @@
          zip                          .zip
       =================       =========================
     """
-    takes_args = ['dest', 'branch?']
+    takes_args = ['dest', 'branch_or_subdir?']
     takes_options = [
         Option('format',
                help="Type of file to export to.",
@@ -2028,14 +2028,16 @@
                type=str,
                help="Name of the root directory inside the exported file."),
         ]
-    def run(self, dest, branch=None, revision=None, format=None, root=None):
+    def run(self, dest, branch_or_subdir=None, revision=None, format=None,
+        root=None):
         from bzrlib.export import export
 
-        if branch is None:
+        if branch_or_subdir is None:
             tree = WorkingTree.open_containing(u'.')[0]
             b = tree.branch
+            subdir = None
         else:
-            b = Branch.open(branch)
+            b, subdir = Branch.open_containing(branch_or_subdir)
             
         if revision is None:
             # should be tree.last_revision  FIXME
@@ -2046,7 +2048,7 @@
             rev_id = revision[0].as_revision_id(b)
         t = b.repository.revision_tree(rev_id)
         try:
-            export(t, dest, format, root)
+            export(t, dest, format, root, subdir)
         except errors.NoSuchExportFormat, e:
             raise errors.BzrCommandError('Unsupported export format: %s' % e.format)
 

=== modified file 'bzrlib/export/__init__.py'
--- a/bzrlib/export/__init__.py	2007-10-28 17:30:25 +0000
+++ b/bzrlib/export/__init__.py	2008-08-08 06:59:48 +0000
@@ -55,14 +55,14 @@
 
     When requesting a specific type of export, load the respective path.
     """
-    def _loader(tree, dest, root):
+    def _loader(tree, dest, root, subdir):
         mod = __import__(module, globals(), locals(), [funcname])
         func = getattr(mod, funcname)
-        return func(tree, dest, root)
+        return func(tree, dest, root, subdir)
     register_exporter(scheme, extensions, _loader)
 
 
-def export(tree, dest, format=None, root=None):
+def export(tree, dest, format=None, root=None, subdir=None):
     """Export the given Tree to the specific destination.
 
     :param tree: A Tree (such as RevisionTree) to export
@@ -76,6 +76,9 @@
                  If root is None, the default root will be
                  selected as the destination without its
                  extension.
+    :param subdir: A starting directory within the tree. None means to export
+        the entire tree, and anything else should specify the relative path to
+        a directory to start exporting from.
     """
     global _exporters, _exporter_extensions
 
@@ -94,7 +97,7 @@
         raise errors.NoSuchExportFormat(format)
     tree.lock_read()
     try:
-        return _exporters[format](tree, dest, root)
+        return _exporters[format](tree, dest, root, subdir)
     finally:
         tree.unlock()
 
@@ -129,6 +132,28 @@
     return dest
 
 
+def _export_iter_entries(tree, subdir):
+    """Iter the entries for tree suitable for exporting.
+
+    :param tree: A tree object.
+    :param subdir: None or the path of a directory to start exporting from.
+    """
+    inv = tree.inventory
+    if subdir is None:
+        subdir_id = None
+    else:
+        subdir_id = inv.path2id(subdir)
+    entries = inv.iter_entries(subdir_id)
+    if subdir is None:
+        entries.next() # skip root
+    for entry in entries:
+        # The .bzr* namespace is reserved for "magic" files like
+        # .bzrignore and .bzrrules - do not export these
+        if entry[0].startswith(".bzr"):
+            continue
+        yield entry
+
+
 register_lazy_exporter(None, [], 'bzrlib.export.dir_exporter', 'dir_exporter')
 register_lazy_exporter('dir', [], 'bzrlib.export.dir_exporter', 'dir_exporter')
 register_lazy_exporter('tar', ['.tar'], 'bzrlib.export.tar_exporter', 'tar_exporter')

=== modified file 'bzrlib/export/dir_exporter.py'
--- a/bzrlib/export/dir_exporter.py	2008-07-30 00:26:38 +0000
+++ b/bzrlib/export/dir_exporter.py	2008-08-08 06:59:48 +0000
@@ -21,10 +21,11 @@
 import os
 
 from bzrlib import errors, osutils
+from bzrlib.export import _export_iter_entries
 from bzrlib.trace import mutter
 
 
-def dir_exporter(tree, dest, root):
+def dir_exporter(tree, dest, root, subdir):
     """Export this tree to a new directory.
 
     `dest` should not exist, and will be created holding the
@@ -36,17 +37,9 @@
     :note: If the export fails, the destination directory will be
            left in a half-assed state.
     """
+    mutter('export version %r', tree)
     os.mkdir(dest)
-    mutter('export version %r', tree)
-    inv = tree.inventory
-    entries = inv.iter_entries()
-    entries.next() # skip root
-    for dp, ie in entries:
-        # The .bzr* namespace is reserved for "magic" files like
-        # .bzrignore and .bzrrules - do not export these
-        if dp.startswith(".bzr"):
-            continue
-        
+    for dp, ie in _export_iter_entries(tree, subdir):
         fullpath = osutils.pathjoin(dest, dp)
         if ie.kind == "file":
             fileobj = tree.get_file(ie.file_id)

=== modified file 'bzrlib/export/tar_exporter.py'
--- a/bzrlib/export/tar_exporter.py	2008-07-30 00:26:38 +0000
+++ b/bzrlib/export/tar_exporter.py	2008-08-08 06:59:48 +0000
@@ -23,15 +23,17 @@
 import time
 
 from bzrlib import errors, export, osutils
+from bzrlib.export import _export_iter_entries
 from bzrlib.trace import mutter
 
 
-def tar_exporter(tree, dest, root, compression=None):
+def tar_exporter(tree, dest, root, subdir, compression=None):
     """Export this tree to a new tar file.
 
     `dest` will be created holding the contents of this tree; if it
     already exists, it will be clobbered, like with "tar -c".
     """
+    mutter('export version %r', tree)
     now = time.time()
     compression = str(compression or '')
     if dest == '-':
@@ -42,16 +44,7 @@
         if root is None:
             root = export.get_root_name(dest)
         ball = tarfile.open(dest, 'w:' + compression)
-    mutter('export version %r', tree)
-    inv = tree.inventory
-    entries = inv.iter_entries()
-    entries.next() # skip root
-    for dp, ie in entries:
-        # The .bzr* namespace is reserved for "magic" files like
-        # .bzrignore and .bzrrules - do not export these
-        if dp.startswith(".bzr"):
-            continue
-
+    for dp, ie in _export_iter_entries(tree, subdir):
         filename = osutils.pathjoin(root, dp).encode('utf8')
         item = tarfile.TarInfo(filename)
         item.mtime = now
@@ -82,9 +75,9 @@
     ball.close()
 
 
-def tgz_exporter(tree, dest, root):
-    tar_exporter(tree, dest, root, compression='gz')
-
-
-def tbz_exporter(tree, dest, root):
-    tar_exporter(tree, dest, root, compression='bz2')
+def tgz_exporter(tree, dest, root, subdir):
+    tar_exporter(tree, dest, root, subdir, compression='gz')
+
+
+def tbz_exporter(tree, dest, root, subdir):
+    tar_exporter(tree, dest, root, subdir, compression='bz2')

=== modified file 'bzrlib/export/zip_exporter.py'
--- a/bzrlib/export/zip_exporter.py	2008-07-25 01:12:16 +0000
+++ b/bzrlib/export/zip_exporter.py	2008-08-08 06:59:48 +0000
@@ -19,11 +19,13 @@
 
 import os
 import stat
+import time
 import zipfile
 
 from bzrlib import (
     osutils,
     )
+from bzrlib.export import _export_iter_entries
 from bzrlib.trace import mutter
 
 
@@ -35,31 +37,21 @@
 _DIR_ATTR = stat.S_IFDIR | ZIP_DIRECTORY_BIT
 
 
-def zip_exporter(tree, dest, root):
+def zip_exporter(tree, dest, root, subdir):
     """ Export this tree to a new zip file.
 
     `dest` will be created holding the contents of this tree; if it
     already exists, it will be overwritten".
     """
-    import time
+    mutter('export version %r', tree)
 
     now = time.localtime()[:6]
-    mutter('export version %r', tree)
 
     compression = zipfile.ZIP_DEFLATED
     zipf = zipfile.ZipFile(dest, "w", compression)
 
-    inv = tree.inventory
-
     try:
-        entries = inv.iter_entries()
-        entries.next() # skip root
-        for dp, ie in entries:
-            # The .bzr* namespace is reserved for "magic" files like
-            # .bzrignore and .bzrrules - do not export these
-            if dp.startswith(".bzr"):
-                continue
-
+        for dp, ie in _export_iter_entries(tree, subdir):
             file_id = ie.file_id
             mutter("  export {%s} kind %s to %s", file_id, ie.kind, dest)
 

=== modified file 'bzrlib/tests/blackbox/test_export.py'
--- a/bzrlib/tests/blackbox/test_export.py	2008-07-30 00:22:33 +0000
+++ b/bzrlib/tests/blackbox/test_export.py	2008-08-08 05:25:58 +0000
@@ -174,6 +174,7 @@
         self.assertEqual(['a'], files)
 
     def example_branch(self):
+        """Create a branch a 'branch' containing hello and goodbye."""
         tree = self.make_branch_and_tree('branch')
         self.build_tree_contents([('branch/hello', 'foo')])
         tree.add('hello')
@@ -277,3 +278,11 @@
         self.run_bzr('export first -r 1 branch')
         self.assertEqual(['hello'], sorted(os.listdir('first')))
         self.check_file_contents('first/hello', 'foo')
+
+    def test_export_partial_tree(self):
+        tree = self.example_branch()
+        self.build_tree(['branch/subdir/', 'branch/subdir/foo.txt'])
+        tree.smart_add(['branch'])
+        tree.commit('more setup')
+        out, err = self.run_bzr('export exported branch/subdir')
+        self.assertEqual(['foo.txt'], os.listdir('exported'))




More information about the bazaar-commits mailing list