/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
5809.3.2 by Aaron Bentley
Support PreviewTree.has_filename.
1
# Copyright (C) 2005-2011 Canonical Ltd
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
2
#
1185.31.12 by John Arbash Meinel
Refactored the export code to make it easier to add new export formats.
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.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
7
#
1185.31.12 by John Arbash Meinel
Refactored the export code to make it easier to add new export formats.
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.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
12
#
1185.31.12 by John Arbash Meinel
Refactored the export code to make it easier to add new export formats.
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
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1185.31.12 by John Arbash Meinel
Refactored the export code to make it easier to add new export formats.
16
5967.6.1 by Martin Pool
pep8 cleanup
17
"""Export trees to tarballs, non-controlled directories, zipfiles, etc.
1185.31.12 by John Arbash Meinel
Refactored the export code to make it easier to add new export formats.
18
"""
19
6379.6.7 by Jelmer Vernooij
Move importing from future until after doc string, otherwise the doc string will disappear.
20
from __future__ import absolute_import
21
6968.2.8 by Jelmer Vernooij
Make export a module.
22
import errno
1185.31.12 by John Arbash Meinel
Refactored the export code to make it easier to add new export formats.
23
import os
6968.2.7 by Jelmer Vernooij
Add breezy.archive.
24
import sys
5718.5.1 by Jelmer Vernooij
per_file_timestamp -> force_mtime.
25
import time
6006.3.6 by Martin Pool
Deprecate export(filtered=True)
26
6968.2.8 by Jelmer Vernooij
Make export a module.
27
from . import (
6968.2.6 by Jelmer Vernooij
Move tar/zip to breezy.archive.
28
    archive,
5436.2.1 by Andrew Bennetts
Add bzrlib.pyutils, which has get_named_object, a wrapper around __import__.
29
    errors,
6968.2.8 by Jelmer Vernooij
Make export a module.
30
    osutils,
5718.5.4 by Jelmer Vernooij
fix timestamp in tgz files.
31
    trace,
5436.2.1 by Andrew Bennetts
Add bzrlib.pyutils, which has get_named_object, a wrapper around __import__.
32
    )
1185.31.12 by John Arbash Meinel
Refactored the export code to make it easier to add new export formats.
33
5967.6.1 by Martin Pool
pep8 cleanup
34
6968.2.9 by Jelmer Vernooij
Simplify export module.
35
def export(tree, dest, format=None, root=None, subdir=None,
36
           per_file_timestamps=False, fileobj=None):
37
    """Export the given Tree to the specific destination.
1185.31.12 by John Arbash Meinel
Refactored the export code to make it easier to add new export formats.
38
39
    :param tree: A Tree (such as RevisionTree) to export
6968.2.9 by Jelmer Vernooij
Simplify export module.
40
    :param dest: The destination where the files,etc should be put
1185.31.12 by John Arbash Meinel
Refactored the export code to make it easier to add new export formats.
41
    :param format: The format (dir, zip, etc), if None, it will check the
6968.2.9 by Jelmer Vernooij
Simplify export module.
42
                   extension on dest, looking for a match
43
    :param root: The root location inside the format.
44
                 It is common practise to have zipfiles and tarballs
45
                 extract into a subdirectory, rather than into the
46
                 current working directory.
47
                 If root is None, the default root will be
48
                 selected as the destination without its
49
                 extension.
3613.2.1 by Robert Collins
Teach export how to export a subdirectory. (Robert Collins)
50
    :param subdir: A starting directory within the tree. None means to export
51
        the entire tree, and anything else should specify the relative path to
52
        a directory to start exporting from.
6968.2.9 by Jelmer Vernooij
Simplify export module.
53
    :param per_file_timestamps: Whether to use the timestamp stored in the
54
        tree rather than now(). This will do a revision lookup
55
        for every file so will be significantly slower.
5952.1.6 by geoffreyfishing at gmail
Created get_export_generator.
56
    :param fileobj: Optional file object to use
1185.31.12 by John Arbash Meinel
Refactored the export code to make it easier to add new export formats.
57
    """
5952.1.6 by geoffreyfishing at gmail
Created get_export_generator.
58
    if format is None and dest is not None:
6968.2.9 by Jelmer Vernooij
Simplify export module.
59
        format = guess_format(dest)
1185.31.12 by John Arbash Meinel
Refactored the export code to make it easier to add new export formats.
60
61
    # Most of the exporters will just have to call
62
    # this function anyway, so why not do it for them
63
    if root is None:
64
        root = get_root_name(dest)
65
5718.5.1 by Jelmer Vernooij
per_file_timestamp -> force_mtime.
66
    if not per_file_timestamps:
7240.8.2 by Jelmer Vernooij
Fix tests.
67
        force_mtime = time.time()
7240.8.1 by Jelmer Vernooij
Use tree timestamp when exporting.
68
        if getattr(tree, '_repository', None):
7240.8.2 by Jelmer Vernooij
Fix tests.
69
            try:
70
                force_mtime = tree._repository.get_revision(
71
                    tree.get_revision_id()).timestamp
72
            except errors.NoSuchRevision:
73
                pass
5718.5.1 by Jelmer Vernooij
per_file_timestamp -> force_mtime.
74
    else:
75
        force_mtime = None
76
5718.5.4 by Jelmer Vernooij
fix timestamp in tgz files.
77
    trace.mutter('export version %r', tree)
78
6968.2.7 by Jelmer Vernooij
Add breezy.archive.
79
    if format == 'dir':
6968.2.9 by Jelmer Vernooij
Simplify export module.
80
        # TODO(jelmer): If the tree is remote (e.g. HPSS, Git Remote),
81
        # then we should stream a tar file and unpack that on the fly.
6968.2.7 by Jelmer Vernooij
Add breezy.archive.
82
        with tree.lock_read():
83
            for unused in dir_exporter_generator(tree, dest, root, subdir,
7143.15.2 by Jelmer Vernooij
Run autopep8.
84
                                                 force_mtime):
6968.2.9 by Jelmer Vernooij
Simplify export module.
85
                pass
6968.2.7 by Jelmer Vernooij
Add breezy.archive.
86
        return
87
6754.8.4 by Jelmer Vernooij
Use new context stuff.
88
    with tree.lock_read():
7143.15.2 by Jelmer Vernooij
Run autopep8.
89
        chunks = tree.archive(format, dest, root=root,
90
                              subdir=subdir, force_mtime=force_mtime)
6968.2.7 by Jelmer Vernooij
Add breezy.archive.
91
        if dest == '-':
92
            for chunk in chunks:
7143.15.2 by Jelmer Vernooij
Run autopep8.
93
                getattr(sys.stdout, 'buffer', sys.stdout).write(chunk)
6968.2.7 by Jelmer Vernooij
Add breezy.archive.
94
        elif fileobj is not None:
95
            for chunk in chunks:
96
                fileobj.write(chunk)
97
        else:
98
            with open(dest, 'wb') as f:
99
                for chunk in chunks:
6973.11.1 by Jelmer Vernooij
Fix export_pot.
100
                    f.write(chunk)
6968.2.9 by Jelmer Vernooij
Simplify export module.
101
102
103
def guess_format(filename, default='dir'):
104
    """Guess the export format based on a file name.
105
106
    :param filename: Filename to guess from
107
    :param default: Default format to fall back to
108
    :return: format name
5952.1.6 by geoffreyfishing at gmail
Created get_export_generator.
109
    """
6968.2.7 by Jelmer Vernooij
Add breezy.archive.
110
    format = archive.format_registry.get_format_from_filename(filename)
111
    if format is None:
6968.2.9 by Jelmer Vernooij
Simplify export module.
112
        format = default
6968.2.7 by Jelmer Vernooij
Add breezy.archive.
113
    return format
114
115
1185.31.12 by John Arbash Meinel
Refactored the export code to make it easier to add new export formats.
116
def get_root_name(dest):
117
    """Get just the root name for an export.
118
119
    """
120
    global _exporter_extensions
5718.5.18 by Jelmer Vernooij
Don't export to '-', but rather to ''.
121
    if dest == '-':
122
        # Exporting to -/foo doesn't make sense so use relative paths.
123
        return ''
1185.31.12 by John Arbash Meinel
Refactored the export code to make it easier to add new export formats.
124
    dest = os.path.basename(dest)
6968.2.7 by Jelmer Vernooij
Add breezy.archive.
125
    for ext in archive.format_registry.extensions:
1185.31.12 by John Arbash Meinel
Refactored the export code to make it easier to add new export formats.
126
        if dest.endswith(ext):
127
            return dest[:-len(ext)]
1185.31.13 by John Arbash Meinel
Updated the test to also test zip exports. Fixed some small bugs exposed by test suite.
128
    return dest
1185.31.12 by John Arbash Meinel
Refactored the export code to make it easier to add new export formats.
129
130
5718.5.8 by Jelmer Vernooij
add skip_special option.
131
def _export_iter_entries(tree, subdir, skip_special=True):
3613.2.2 by Robert Collins
Refactor exporters to remove obvious duplication to a helper function.
132
    """Iter the entries for tree suitable for exporting.
133
134
    :param tree: A tree object.
4988.10.2 by michal
bzr export won't fail on symlink exporting
135
    :param subdir: None or the path of an entry to start exporting from.
5718.5.8 by Jelmer Vernooij
add skip_special option.
136
    :param skip_special: Whether to skip .bzr files.
6331.2.1 by Jelmer Vernooij
Consistently pass tree path when exporting.
137
    :return: iterator over tuples with final path, tree path and inventory
138
        entry for each entry to export
3613.2.2 by Robert Collins
Refactor exporters to remove obvious duplication to a helper function.
139
    """
5809.3.1 by Aaron Bentley
Switch to iter_entries_by_dir.
140
    if subdir == '':
141
        subdir = None
142
    if subdir is not None:
143
        subdir = subdir.rstrip('/')
144
    entries = tree.iter_entries_by_dir()
145
    for path, entry in entries:
6928.1.2 by Jelmer Vernooij
Fix path specification.
146
        if path == '':
147
            continue
148
3613.2.2 by Robert Collins
Refactor exporters to remove obvious duplication to a helper function.
149
        # The .bzr* namespace is reserved for "magic" files like
150
        # .bzrignore and .bzrrules - do not export these
5809.3.1 by Aaron Bentley
Switch to iter_entries_by_dir.
151
        if skip_special and path.startswith(".bzr"):
3613.2.2 by Robert Collins
Refactor exporters to remove obvious duplication to a helper function.
152
            continue
5809.3.1 by Aaron Bentley
Switch to iter_entries_by_dir.
153
        if path == subdir:
154
            if entry.kind == 'directory':
155
                continue
156
            final_path = entry.name
157
        elif subdir is not None:
158
            if path.startswith(subdir + '/'):
159
                final_path = path[len(subdir) + 1:]
160
            else:
4010.2.1 by James Westby
Handle files that are not present in the tree when exporting (#174539)
161
                continue
162
        else:
5809.3.1 by Aaron Bentley
Switch to iter_entries_by_dir.
163
            final_path = path
164
        if not tree.has_filename(path):
165
            continue
5967.6.1 by Martin Pool
pep8 cleanup
166
6331.2.1 by Jelmer Vernooij
Consistently pass tree path when exporting.
167
        yield final_path, path, entry
6968.2.8 by Jelmer Vernooij
Make export a module.
168
169
170
def dir_exporter_generator(tree, dest, root, subdir=None,
171
                           force_mtime=None, fileobj=None):
172
    """Return a generator that exports this tree to a new directory.
173
174
    `dest` should either not exist or should be empty. If it does not exist it
175
    will be created holding the contents of this tree.
176
177
    :note: If the export fails, the destination directory will be
178
           left in an incompletely exported state: export is not transactional.
179
    """
180
    try:
181
        os.mkdir(dest)
182
    except OSError as e:
183
        if e.errno == errno.EEXIST:
184
            # check if directory empty
185
            if os.listdir(dest) != []:
186
                raise errors.BzrError(
187
                    "Can't export tree to non-empty directory.")
188
        else:
189
            raise
190
    # Iterate everything, building up the files we will want to export, and
191
    # creating the directories and symlinks that we need.
192
    # This tracks (file_id, (destination_path, executable))
193
    # This matches the api that tree.iter_files_bytes() wants
194
    # Note in the case of revision trees, this does trigger a double inventory
195
    # lookup, hopefully it isn't too expensive.
196
    to_fetch = []
197
    for dp, tp, ie in _export_iter_entries(tree, subdir):
6973.3.4 by Jelmer Vernooij
Don't assume entries returned by trees have a 'file_id' attribute.
198
        file_id = getattr(ie, 'file_id', None)
6968.2.8 by Jelmer Vernooij
Make export a module.
199
        fullpath = osutils.pathjoin(dest, dp)
200
        if ie.kind == "file":
6973.3.4 by Jelmer Vernooij
Don't assume entries returned by trees have a 'file_id' attribute.
201
            to_fetch.append((tp, (dp, tp, file_id)))
6968.2.8 by Jelmer Vernooij
Make export a module.
202
        elif ie.kind in ("directory", "tree-reference"):
203
            os.mkdir(fullpath)
204
        elif ie.kind == "symlink":
205
            try:
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
206
                symlink_target = tree.get_symlink_target(tp)
6968.2.8 by Jelmer Vernooij
Make export a module.
207
                os.symlink(symlink_target, fullpath)
208
            except OSError as e:
209
                raise errors.BzrError(
210
                    "Failed to create symlink %r -> %r, error: %s"
211
                    % (fullpath, symlink_target, e))
212
        else:
213
            raise errors.BzrError("don't know how to export {%s} of kind %r" %
7143.15.2 by Jelmer Vernooij
Run autopep8.
214
                                  (tp, ie.kind))
6968.2.8 by Jelmer Vernooij
Make export a module.
215
216
        yield
217
    # The data returned here can be in any order, but we've already created all
218
    # the directories
219
    flags = os.O_CREAT | os.O_TRUNC | os.O_WRONLY | getattr(os, 'O_BINARY', 0)
220
    for (relpath, treepath, file_id), chunks in tree.iter_files_bytes(to_fetch):
221
        fullpath = osutils.pathjoin(dest, relpath)
222
        # We set the mode and let the umask sort out the file info
223
        mode = 0o666
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
224
        if tree.is_executable(treepath):
6968.2.8 by Jelmer Vernooij
Make export a module.
225
            mode = 0o777
226
        with os.fdopen(os.open(fullpath, flags, mode), 'wb') as out:
227
            out.writelines(chunks)
228
        if force_mtime is not None:
229
            mtime = force_mtime
230
        else:
7141.7.1 by Jelmer Vernooij
Get rid of file_ids in most of Tree.
231
            mtime = tree.get_file_mtime(treepath)
6968.2.8 by Jelmer Vernooij
Make export a module.
232
        os.utime(fullpath, (mtime, mtime))
233
234
        yield