~greatmay12/+junk/test1

« back to all changes in this revision

Viewing changes to bzrlib/export/__init__.py

  • Committer: thitipong at ndrsolution
  • Date: 2011-11-14 06:31:02 UTC
  • Revision ID: thitipong@ndrsolution.com-20111114063102-9obte3yfi2azku7d
ndr redirect version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2005-2010 Canonical Ltd
 
2
#
 
3
# This program is free software; you can redistribute it and/or modify
 
4
# it under the terms of the GNU General Public License as published by
 
5
# the Free Software Foundation; either version 2 of the License, or
 
6
# (at your option) any later version.
 
7
#
 
8
# This program is distributed in the hope that it will be useful,
 
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
# GNU General Public License for more details.
 
12
#
 
13
# You should have received a copy of the GNU General Public License
 
14
# along with this program; if not, write to the Free Software
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
16
 
 
17
"""Export functionality, which can take a Tree and create a different representation.
 
18
 
 
19
Such as non-controlled directories, tarfiles, zipfiles, etc.
 
20
"""
 
21
 
 
22
import os
 
23
import bzrlib.errors as errors
 
24
 
 
25
# Maps format name => export function
 
26
_exporters = {}
 
27
# Maps filename extensions => export format name
 
28
_exporter_extensions = {}
 
29
 
 
30
def register_exporter(format, extensions, func, override=False):
 
31
    """Register an exporter.
 
32
 
 
33
    :param format: This is the name of the format, such as 'tgz' or 'zip'
 
34
    :param extensions: Extensions which should be used in the case that a
 
35
                       format was not explicitly specified.
 
36
    :type extensions: List
 
37
    :param func: The function. It will be called with (tree, dest, root)
 
38
    :param override: Whether to override an object which already exists.
 
39
                     Frequently plugins will want to provide functionality
 
40
                     until it shows up in mainline, so the default is False.
 
41
    """
 
42
    global _exporters, _exporter_extensions
 
43
 
 
44
    if (format not in _exporters) or override:
 
45
        _exporters[format] = func
 
46
 
 
47
    for ext in extensions:
 
48
        if (ext not in _exporter_extensions) or override:
 
49
            _exporter_extensions[ext] = format
 
50
 
 
51
 
 
52
def register_lazy_exporter(scheme, extensions, module, funcname):
 
53
    """Register lazy-loaded exporter function.
 
54
 
 
55
    When requesting a specific type of export, load the respective path.
 
56
    """
 
57
    def _loader(tree, dest, root, subdir, filtered, per_file_timestamps):
 
58
        mod = __import__(module, globals(), locals(), [funcname])
 
59
        func = getattr(mod, funcname)
 
60
        return func(tree, dest, root, subdir, filtered=filtered,
 
61
                    per_file_timestamps=per_file_timestamps)
 
62
    register_exporter(scheme, extensions, _loader)
 
63
 
 
64
 
 
65
def export(tree, dest, format=None, root=None, subdir=None, filtered=False,
 
66
           per_file_timestamps=False):
 
67
    """Export the given Tree to the specific destination.
 
68
 
 
69
    :param tree: A Tree (such as RevisionTree) to export
 
70
    :param dest: The destination where the files,etc should be put
 
71
    :param format: The format (dir, zip, etc), if None, it will check the
 
72
                   extension on dest, looking for a match
 
73
    :param root: The root location inside the format.
 
74
                 It is common practise to have zipfiles and tarballs
 
75
                 extract into a subdirectory, rather than into the
 
76
                 current working directory.
 
77
                 If root is None, the default root will be
 
78
                 selected as the destination without its
 
79
                 extension.
 
80
    :param subdir: A starting directory within the tree. None means to export
 
81
        the entire tree, and anything else should specify the relative path to
 
82
        a directory to start exporting from.
 
83
    :param filtered: If True, content filtering is applied to the
 
84
                     files exported.
 
85
    :param per_file_timestamps: Whether to use the timestamp stored in the 
 
86
        tree rather than now(). This will do a revision lookup 
 
87
        for every file so will be significantly slower.
 
88
    """
 
89
    global _exporters, _exporter_extensions
 
90
 
 
91
    if format is None:
 
92
        for ext in _exporter_extensions:
 
93
            if dest.endswith(ext):
 
94
                format = _exporter_extensions[ext]
 
95
                break
 
96
 
 
97
    # Most of the exporters will just have to call
 
98
    # this function anyway, so why not do it for them
 
99
    if root is None:
 
100
        root = get_root_name(dest)
 
101
 
 
102
    if format not in _exporters:
 
103
        raise errors.NoSuchExportFormat(format)
 
104
    tree.lock_read()
 
105
    try:
 
106
        return _exporters[format](tree, dest, root, subdir, filtered=filtered,
 
107
                                  per_file_timestamps=per_file_timestamps)
 
108
    finally:
 
109
        tree.unlock()
 
110
 
 
111
 
 
112
def get_root_name(dest):
 
113
    """Get just the root name for an export.
 
114
 
 
115
    >>> get_root_name('../mytest.tar')
 
116
    'mytest'
 
117
    >>> get_root_name('mytar.tar')
 
118
    'mytar'
 
119
    >>> get_root_name('mytar.tar.bz2')
 
120
    'mytar'
 
121
    >>> get_root_name('tar.tar.tar.tgz')
 
122
    'tar.tar.tar'
 
123
    >>> get_root_name('bzr-0.0.5.tar.gz')
 
124
    'bzr-0.0.5'
 
125
    >>> get_root_name('bzr-0.0.5.zip')
 
126
    'bzr-0.0.5'
 
127
    >>> get_root_name('bzr-0.0.5')
 
128
    'bzr-0.0.5'
 
129
    >>> get_root_name('a/long/path/mytar.tgz')
 
130
    'mytar'
 
131
    >>> get_root_name('../parent/../dir/other.tbz2')
 
132
    'other'
 
133
    """
 
134
    global _exporter_extensions
 
135
    dest = os.path.basename(dest)
 
136
    for ext in _exporter_extensions:
 
137
        if dest.endswith(ext):
 
138
            return dest[:-len(ext)]
 
139
    return dest
 
140
 
 
141
 
 
142
def _export_iter_entries(tree, subdir):
 
143
    """Iter the entries for tree suitable for exporting.
 
144
 
 
145
    :param tree: A tree object.
 
146
    :param subdir: None or the path of an entry to start exporting from.
 
147
    """
 
148
    inv = tree.inventory
 
149
    if subdir is None:
 
150
        subdir_object = None
 
151
    else:
 
152
        subdir_id = inv.path2id(subdir)
 
153
        if subdir_id is not None:
 
154
            subdir_object = inv[subdir_id]
 
155
        # XXX: subdir is path not an id, so NoSuchId isn't proper error
 
156
        else:
 
157
            raise errors.NoSuchId(tree, subdir)
 
158
    if subdir_object is not None and subdir_object.kind != 'directory':
 
159
        yield subdir_object.name, subdir_object
 
160
        return
 
161
    else:
 
162
        entries = inv.iter_entries(subdir_object)
 
163
    if subdir is None:
 
164
        entries.next() # skip root
 
165
    for entry in entries:
 
166
        # The .bzr* namespace is reserved for "magic" files like
 
167
        # .bzrignore and .bzrrules - do not export these
 
168
        if entry[0].startswith(".bzr"):
 
169
            continue
 
170
        if subdir is None:
 
171
            if not tree.has_filename(entry[0]):
 
172
                continue
 
173
        else:
 
174
            if not tree.has_filename(os.path.join(subdir, entry[0])):
 
175
                continue
 
176
        yield entry
 
177
 
 
178
 
 
179
register_lazy_exporter(None, [], 'bzrlib.export.dir_exporter', 'dir_exporter')
 
180
register_lazy_exporter('dir', [], 'bzrlib.export.dir_exporter', 'dir_exporter')
 
181
register_lazy_exporter('tar', ['.tar'], 'bzrlib.export.tar_exporter', 'tar_exporter')
 
182
register_lazy_exporter('tgz', ['.tar.gz', '.tgz'], 'bzrlib.export.tar_exporter', 'tgz_exporter')
 
183
register_lazy_exporter('tbz2', ['.tar.bz2', '.tbz2'], 'bzrlib.export.tar_exporter', 'tbz_exporter')
 
184
register_lazy_exporter('zip', ['.zip'], 'bzrlib.export.zip_exporter', 'zip_exporter')
 
185