/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
70 by mbp at sourcefrog
Prepare for smart recursive add.
1
# Copyright (C) 2005 Canonical Ltd
1685.1.80 by Wouter van Heyst
more code cleanup
2
#
70 by mbp at sourcefrog
Prepare for smart recursive add.
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.
1685.1.80 by Wouter van Heyst
more code cleanup
7
#
70 by mbp at sourcefrog
Prepare for smart recursive add.
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.
1685.1.80 by Wouter van Heyst
more code cleanup
12
#
70 by mbp at sourcefrog
Prepare for smart recursive add.
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
1185.85.12 by John Arbash Meinel
Refactoring AddAction to allow redirecting to an encoding file.
17
import sys
1185.1.53 by Robert Collins
raise a specific error on unsupported branches so that they can be distinguished from generic errors
18
from os.path import dirname
19
20
import bzrlib.errors as errors
1399.1.1 by Robert Collins
move checks for versionability of file kinds into InventoryEntry
21
from bzrlib.inventory import InventoryEntry
1128 by Martin Pool
- smart_add routine now doesn't print filenames directly, but rather
22
from bzrlib.trace import mutter, note, warning
1092.1.27 by Robert Collins
two bugfixes to smart_add - do not add paths from nested trees to the parent tree, and do not mutate the user supplied file list
23
from bzrlib.errors import NotBranchError
1508.1.10 by Robert Collins
bzrlib.add.smart_add_branch is now smart_add_tree. (Robert Collins)
24
import bzrlib.osutils
25
from bzrlib.workingtree import WorkingTree
70 by mbp at sourcefrog
Prepare for smart recursive add.
26
1685.1.80 by Wouter van Heyst
more code cleanup
27
686 by Martin Pool
- glob expand add arguments on win32
28
def glob_expand_for_win32(file_list):
1185.23.2 by Aaron Bentley
win32 glob expansion fix from Belchenko
29
    if not file_list:
30
        return
686 by Martin Pool
- glob expand add arguments on win32
31
    import glob
32
    expanded_file_list = []
33
    for possible_glob in file_list:
34
        glob_files = glob.glob(possible_glob)
35
       
36
        if glob_files == []:
37
            # special case to let the normal code path handle
38
            # files that do not exists
39
            expanded_file_list.append(possible_glob)
40
        else:
41
            expanded_file_list += glob_files
42
    return expanded_file_list
43
1128 by Martin Pool
- smart_add routine now doesn't print filenames directly, but rather
44
1092.1.29 by Robert Collins
break smart_add into smart_add and smart_add_branch which will accept a branch parameter
45
def _prepare_file_list(file_list):
46
    """Prepare a file list for use by smart_add_*."""
47
    if sys.platform == 'win32':
48
        file_list = glob_expand_for_win32(file_list)
49
    if not file_list:
1185.33.66 by Martin Pool
[patch] use unicode literals for all hardcoded paths (Alexander Belchenko)
50
        file_list = [u'.']
1092.1.29 by Robert Collins
break smart_add into smart_add and smart_add_branch which will accept a branch parameter
51
    file_list = list(file_list)
52
    return file_list
53
1159 by Martin Pool
- clean up parameters to smart_add and smart_add_branch
54
1185.85.12 by John Arbash Meinel
Refactoring AddAction to allow redirecting to an encoding file.
55
class AddAction(object):
56
    """A class which defines what action to take when adding a file."""
57
58
    def __init__(self, to_file=None, should_add=None, should_print=None):
59
        self._to_file = to_file
60
        if to_file is None:
61
            self._to_file = sys.stdout
1685.1.69 by Wouter van Heyst
merge bzr.dev 1740
62
        self.should_add = False
1185.85.12 by John Arbash Meinel
Refactoring AddAction to allow redirecting to an encoding file.
63
        if should_add is not None:
64
            self.should_add = should_add
1685.1.69 by Wouter van Heyst
merge bzr.dev 1740
65
        self.should_print = False
1185.85.12 by John Arbash Meinel
Refactoring AddAction to allow redirecting to an encoding file.
66
        if should_print is not None:
67
            self.should_print = should_print
68
1685.1.69 by Wouter van Heyst
merge bzr.dev 1740
69
    def __call__(self, inv, parent_ie, path, kind):
1185.85.12 by John Arbash Meinel
Refactoring AddAction to allow redirecting to an encoding file.
70
        """Add path to inventory.
71
72
        The default action does nothing.
73
74
        :param inv: The inventory we are working with.
75
        :param path: The path being added
76
        :param kind: The kind of the object being added.
77
        """
78
        if self.should_add:
1685.1.69 by Wouter van Heyst
merge bzr.dev 1740
79
            self._add_to_inv(inv, parent_ie, path, kind)
1185.85.12 by John Arbash Meinel
Refactoring AddAction to allow redirecting to an encoding file.
80
        if self.should_print:
1685.1.69 by Wouter van Heyst
merge bzr.dev 1740
81
            self._print(inv, parent_ie, path, kind)
1185.85.12 by John Arbash Meinel
Refactoring AddAction to allow redirecting to an encoding file.
82
1685.1.69 by Wouter van Heyst
merge bzr.dev 1740
83
    def _print(self, inv, parent_ie, path, kind):
84
        """Print a line to self._to_file for each file that would be added."""
1185.85.12 by John Arbash Meinel
Refactoring AddAction to allow redirecting to an encoding file.
85
        self._to_file.write('added ')
86
        self._to_file.write(bzrlib.osutils.quotefn(path))
87
        self._to_file.write('\n')
88
1685.1.69 by Wouter van Heyst
merge bzr.dev 1740
89
    def _add_to_inv(self, inv, parent_ie, path, kind):
90
        """Add each file to the given inventory. Produce no output."""
91
        if parent_ie is not None:
92
            entry = bzrlib.inventory.make_entry(
93
                kind, bzrlib.osutils.basename(path),  parent_ie.file_id)
94
            inv.add(entry)
95
        else:
96
            entry = inv.add_path(path, kind=kind)
97
        # mutter("added %r kind %r file_id={%s}", path, kind, entry.file_id)
1185.85.12 by John Arbash Meinel
Refactoring AddAction to allow redirecting to an encoding file.
98
99
100
# TODO: jam 20050105 These could be used for compatibility
101
#       however, they bind against the current stdout, not the
102
#       one which exists at the time they are called, so they
103
#       don't work for the test suite.
104
# deprecated
105
add_action_null = AddAction()
106
add_action_add = AddAction(should_add=True)
107
add_action_print = AddAction(should_print=True)
108
add_action_add_and_print = AddAction(should_add=True, should_print=True)
109
110
111
def smart_add(file_list, recurse=True, action=None):
598 by Martin Pool
doc
112
    """Add files to version, optionally recursing into directories.
70 by mbp at sourcefrog
Prepare for smart recursive add.
113
114
    This is designed more towards DWIM for humans than API simplicity.
115
    For the specific behaviour see the help for cmd_add().
1159 by Martin Pool
- clean up parameters to smart_add and smart_add_branch
116
117
    Returns the number of files added.
70 by mbp at sourcefrog
Prepare for smart recursive add.
118
    """
1092.1.29 by Robert Collins
break smart_add into smart_add and smart_add_branch which will accept a branch parameter
119
    file_list = _prepare_file_list(file_list)
1508.1.10 by Robert Collins
bzrlib.add.smart_add_branch is now smart_add_tree. (Robert Collins)
120
    tree = WorkingTree.open_containing(file_list[0])[0]
1185.85.12 by John Arbash Meinel
Refactoring AddAction to allow redirecting to an encoding file.
121
    return smart_add_tree(tree, file_list, recurse, action=action)
122
123
124
def smart_add_tree(tree, file_list, recurse=True, action=None):
1092.1.29 by Robert Collins
break smart_add into smart_add and smart_add_branch which will accept a branch parameter
125
    """Add files to version, optionally recursing into directories.
126
127
    This is designed more towards DWIM for humans than API simplicity.
128
    For the specific behaviour see the help for cmd_add().
1128 by Martin Pool
- smart_add routine now doesn't print filenames directly, but rather
129
1508.1.11 by Robert Collins
Documentation.
130
    This calls reporter with each (path, kind, file_id) of added files.
1159 by Martin Pool
- clean up parameters to smart_add and smart_add_branch
131
132
    Returns the number of files added.
1092.1.29 by Robert Collins
break smart_add into smart_add and smart_add_branch which will accept a branch parameter
133
    """
1185.56.2 by Michael Ellerman
Raise NoSuchFile when someone tries to add a non-existant file.
134
    import os, errno
599 by Martin Pool
- better error reporting from smart_add
135
    from bzrlib.errors import BadFileKindError, ForbiddenFileError
1159 by Martin Pool
- clean up parameters to smart_add and smart_add_branch
136
    assert isinstance(recurse, bool)
1185.85.12 by John Arbash Meinel
Refactoring AddAction to allow redirecting to an encoding file.
137
    if action is None:
138
        action = AddAction(should_add=True)
1713.1.9 by Robert Collins
Paired performance tuning of bzr add. (Robert Collins, Martin Pool).
139
    
1713.1.14 by Robert Collins
Review feedback.
140
    prepared_list = _prepare_file_list(file_list)
141
    mutter("smart add of %r, originally %r", prepared_list, file_list)
1497 by Robert Collins
Move Branch.read_working_inventory to WorkingTree.
142
    inv = tree.read_working_inventory()
1185.46.8 by Aaron Bentley
bzr add reports ignored patterns.
143
    added = []
144
    ignored = {}
1713.1.14 by Robert Collins
Review feedback.
145
    user_files = set()
146
    files_to_add = []
86 by mbp at sourcefrog
first cut at recursive add
147
1713.1.11 by Robert Collins
refactor smart_add to pass around the parent inventory entry and use that, resulting in another 100bzrlib/inventory.py performance improvement, and making inventory writing the dominating factory in add. (Robert Collins)
148
    # validate user file paths and convert all paths to tree 
149
    # relative : its cheaper to make a tree relative path an abspath
150
    # than to convert an abspath to tree relative.
1713.1.14 by Robert Collins
Review feedback.
151
    for filepath in prepared_list:
1713.1.9 by Robert Collins
Paired performance tuning of bzr add. (Robert Collins, Martin Pool).
152
        rf = tree.relpath(filepath)
1713.1.14 by Robert Collins
Review feedback.
153
        user_files.add(rf)
154
        files_to_add.append((rf, None))
1713.1.9 by Robert Collins
Paired performance tuning of bzr add. (Robert Collins, Martin Pool).
155
        # validate user parameters. Our recursive code avoids adding new files
156
        # that need such validation 
1713.1.11 by Robert Collins
refactor smart_add to pass around the parent inventory entry and use that, resulting in another 100bzrlib/inventory.py performance improvement, and making inventory writing the dominating factory in add. (Robert Collins)
157
        if tree.is_control_filename(rf):
1713.1.9 by Robert Collins
Paired performance tuning of bzr add. (Robert Collins, Martin Pool).
158
            raise ForbiddenFileError('cannot add control file %s' % filepath)
159
1713.1.14 by Robert Collins
Review feedback.
160
    for filepath, parent_ie in files_to_add:
1713.1.11 by Robert Collins
refactor smart_add to pass around the parent inventory entry and use that, resulting in another 100bzrlib/inventory.py performance improvement, and making inventory writing the dominating factory in add. (Robert Collins)
161
        # filepath is tree-relative
162
        abspath = tree.abspath(filepath)
163
1713.1.9 by Robert Collins
Paired performance tuning of bzr add. (Robert Collins, Martin Pool).
164
        # find the kind of the path being added. This is not
165
        # currently determined when we list directories 
166
        # recursively, but in theory we can determine while 
167
        # doing the directory listing on *some* platformans.
168
        # TODO: a safe, portable, clean interface which will 
169
        # be faster than os.listdir() + stat. Specifically,
170
        # readdir - dirent.d_type supplies the file type when
171
        # it is defined. (Apparently Mac OSX has the field but
172
        # does not fill it in ?!) Robert C, Martin P.
1185.56.2 by Michael Ellerman
Raise NoSuchFile when someone tries to add a non-existant file.
173
        try:
1713.1.11 by Robert Collins
refactor smart_add to pass around the parent inventory entry and use that, resulting in another 100bzrlib/inventory.py performance improvement, and making inventory writing the dominating factory in add. (Robert Collins)
174
            kind = bzrlib.osutils.file_kind(abspath)
1185.56.2 by Michael Ellerman
Raise NoSuchFile when someone tries to add a non-existant file.
175
        except OSError, e:
176
            if hasattr(e, 'errno') and e.errno == errno.ENOENT:
1713.1.11 by Robert Collins
refactor smart_add to pass around the parent inventory entry and use that, resulting in another 100bzrlib/inventory.py performance improvement, and making inventory writing the dominating factory in add. (Robert Collins)
177
                raise errors.NoSuchFile(abspath)
1185.56.2 by Michael Ellerman
Raise NoSuchFile when someone tries to add a non-existant file.
178
            raise
426 by Martin Pool
- Skip symlinks during recursive add (path from aaron)
179
1713.1.9 by Robert Collins
Paired performance tuning of bzr add. (Robert Collins, Martin Pool).
180
        # we need to call this to determine the inventory kind to create.
1399.1.1 by Robert Collins
move checks for versionability of file kinds into InventoryEntry
181
        if not InventoryEntry.versionable_kind(kind):
1713.1.9 by Robert Collins
Paired performance tuning of bzr add. (Robert Collins, Martin Pool).
182
            if filepath in user_files:
1713.1.11 by Robert Collins
refactor smart_add to pass around the parent inventory entry and use that, resulting in another 100bzrlib/inventory.py performance improvement, and making inventory writing the dominating factory in add. (Robert Collins)
183
                raise BadFileKindError("cannot add %s of type %s" % (abspath, kind))
599 by Martin Pool
- better error reporting from smart_add
184
            else:
1713.1.11 by Robert Collins
refactor smart_add to pass around the parent inventory entry and use that, resulting in another 100bzrlib/inventory.py performance improvement, and making inventory writing the dominating factory in add. (Robert Collins)
185
                warning("skipping %s (can't add file of kind '%s')", abspath, kind)
426 by Martin Pool
- Skip symlinks during recursive add (path from aaron)
186
                continue
187
1713.1.11 by Robert Collins
refactor smart_add to pass around the parent inventory entry and use that, resulting in another 100bzrlib/inventory.py performance improvement, and making inventory writing the dominating factory in add. (Robert Collins)
188
        if parent_ie is not None:
189
            versioned = bzrlib.osutils.basename(filepath) in parent_ie.children
190
        else:
191
            # without the parent ie, use the relatively slower inventory 
192
            # probing method
193
            versioned = inv.has_filename(filepath)
86 by mbp at sourcefrog
first cut at recursive add
194
1092.1.27 by Robert Collins
two bugfixes to smart_add - do not add paths from nested trees to the parent tree, and do not mutate the user supplied file list
195
        if kind == 'directory':
196
            try:
1713.1.11 by Robert Collins
refactor smart_add to pass around the parent inventory entry and use that, resulting in another 100bzrlib/inventory.py performance improvement, and making inventory writing the dominating factory in add. (Robert Collins)
197
                sub_branch = bzrlib.bzrdir.BzrDir.open(abspath)
1092.1.27 by Robert Collins
two bugfixes to smart_add - do not add paths from nested trees to the parent tree, and do not mutate the user supplied file list
198
                sub_tree = True
199
            except NotBranchError:
200
                sub_tree = False
1185.1.53 by Robert Collins
raise a specific error on unsupported branches so that they can be distinguished from generic errors
201
            except errors.UnsupportedFormatError:
202
                sub_tree = True
1092.1.27 by Robert Collins
two bugfixes to smart_add - do not add paths from nested trees to the parent tree, and do not mutate the user supplied file list
203
        else:
204
            sub_tree = False
205
1713.1.11 by Robert Collins
refactor smart_add to pass around the parent inventory entry and use that, resulting in another 100bzrlib/inventory.py performance improvement, and making inventory writing the dominating factory in add. (Robert Collins)
206
        if filepath == '':
1713.1.9 by Robert Collins
Paired performance tuning of bzr add. (Robert Collins, Martin Pool).
207
            # mutter("tree root doesn't need to be added")
1092.1.27 by Robert Collins
two bugfixes to smart_add - do not add paths from nested trees to the parent tree, and do not mutate the user supplied file list
208
            sub_tree = False
91 by mbp at sourcefrog
special handling of root directory for recursive add
209
        elif versioned:
1713.1.9 by Robert Collins
Paired performance tuning of bzr add. (Robert Collins, Martin Pool).
210
            pass
1713.1.11 by Robert Collins
refactor smart_add to pass around the parent inventory entry and use that, resulting in another 100bzrlib/inventory.py performance improvement, and making inventory writing the dominating factory in add. (Robert Collins)
211
            # mutter("%r is already versioned", abspath)
1092.1.27 by Robert Collins
two bugfixes to smart_add - do not add paths from nested trees to the parent tree, and do not mutate the user supplied file list
212
        elif sub_tree:
1713.1.11 by Robert Collins
refactor smart_add to pass around the parent inventory entry and use that, resulting in another 100bzrlib/inventory.py performance improvement, and making inventory writing the dominating factory in add. (Robert Collins)
213
            mutter("%r is a nested bzr tree", abspath)
70 by mbp at sourcefrog
Prepare for smart recursive add.
214
        else:
1713.1.11 by Robert Collins
refactor smart_add to pass around the parent inventory entry and use that, resulting in another 100bzrlib/inventory.py performance improvement, and making inventory writing the dominating factory in add. (Robert Collins)
215
            added.extend(__add_one(tree, inv, parent_ie, filepath, kind, action))
87 by mbp at sourcefrog
- clean up smart_add code, and make it commit the inventory
216
1092.1.27 by Robert Collins
two bugfixes to smart_add - do not add paths from nested trees to the parent tree, and do not mutate the user supplied file list
217
        if kind == 'directory' and recurse and not sub_tree:
1713.1.11 by Robert Collins
refactor smart_add to pass around the parent inventory entry and use that, resulting in another 100bzrlib/inventory.py performance improvement, and making inventory writing the dominating factory in add. (Robert Collins)
218
            try:
219
                if parent_ie is not None:
220
                    # must be present:
221
                    this_ie = parent_ie.children[bzrlib.osutils.basename(filepath)]
222
                else:
223
                    # without the parent ie, use the relatively slower inventory 
224
                    # probing method
225
                    this_id = inv.path2id(filepath)
226
                    if this_id is None:
227
                        this_ie = None
228
                    else:
229
                        this_ie = inv[this_id]
230
            except KeyError:
231
                this_ie = None
232
233
            for subf in os.listdir(abspath):
1713.1.9 by Robert Collins
Paired performance tuning of bzr add. (Robert Collins, Martin Pool).
234
                # here we could use TreeDirectory rather than 
235
                # string concatenation.
1713.1.11 by Robert Collins
refactor smart_add to pass around the parent inventory entry and use that, resulting in another 100bzrlib/inventory.py performance improvement, and making inventory writing the dominating factory in add. (Robert Collins)
236
                subp = bzrlib.osutils.pathjoin(filepath, subf)
1713.1.9 by Robert Collins
Paired performance tuning of bzr add. (Robert Collins, Martin Pool).
237
                # TODO: is_control_filename is very slow. Make it faster. 
238
                # TreeDirectory.is_control_filename could also make this 
239
                # faster - its impossible for a non root dir to have a 
240
                # control file.
1534.5.5 by Robert Collins
Move is_control_file into WorkingTree.is_control_filename and test.
241
                if tree.is_control_filename(subp):
1185.31.4 by John Arbash Meinel
Fixing mutter() calls to not have to do string processing.
242
                    mutter("skip control directory %r", subp)
87 by mbp at sourcefrog
- clean up smart_add code, and make it commit the inventory
243
                else:
1713.1.9 by Robert Collins
Paired performance tuning of bzr add. (Robert Collins, Martin Pool).
244
                    # ignore while selecting files - if we globbed in the
245
                    # outer loop we would ignore user files.
1185.46.8 by Aaron Bentley
bzr add reports ignored patterns.
246
                    ignore_glob = tree.is_ignored(subp)
247
                    if ignore_glob is not None:
1713.1.9 by Robert Collins
Paired performance tuning of bzr add. (Robert Collins, Martin Pool).
248
                        # mutter("skip ignored sub-file %r", subp)
1185.46.8 by Aaron Bentley
bzr add reports ignored patterns.
249
                        if ignore_glob not in ignored:
250
                            ignored[ignore_glob] = []
251
                        ignored[ignore_glob].append(subp)
252
                    else:
1713.1.9 by Robert Collins
Paired performance tuning of bzr add. (Robert Collins, Martin Pool).
253
                        #mutter("queue to add sub-file %r", subp)
1713.1.14 by Robert Collins
Review feedback.
254
                        files_to_add.append((subp, this_ie))
1185.46.8 by Aaron Bentley
bzr add reports ignored patterns.
255
256
    if len(added) > 0:
1508.1.10 by Robert Collins
bzrlib.add.smart_add_branch is now smart_add_tree. (Robert Collins)
257
        tree._write_inventory(inv)
1185.46.8 by Aaron Bentley
bzr add reports ignored patterns.
258
    return added, ignored
1185.3.3 by Martin Pool
- patch from mpe to automatically add parent directories
259
1685.1.80 by Wouter van Heyst
more code cleanup
260
1713.1.11 by Robert Collins
refactor smart_add to pass around the parent inventory entry and use that, resulting in another 100bzrlib/inventory.py performance improvement, and making inventory writing the dominating factory in add. (Robert Collins)
261
def __add_one(tree, inv, parent_ie, path, kind, action):
1713.1.14 by Robert Collins
Review feedback.
262
    """Add a new entry to the inventory and automatically add unversioned parents.
263
264
    Actual adding of the entry is delegated to the action callback.
265
266
    :param inv: Inventory which will receive the new entry.
267
    :param parent_ie: Parent inventory entry if known, or None.  If
268
    None, the parent is looked up by name and used if present, otherwise
269
    it is recursively added.
270
    :param kind: Kind of new entry (file, directory, etc)
271
    :param action: callback(inv, parent_ie, path, kind); return ignored.
272
    :returns: A list of paths which have been added.
273
    """
1185.3.3 by Martin Pool
- patch from mpe to automatically add parent directories
274
275
    # Nothing to do if path is already versioned.
1508.1.10 by Robert Collins
bzrlib.add.smart_add_branch is now smart_add_tree. (Robert Collins)
276
    # This is safe from infinite recursion because the tree root is
1185.3.3 by Martin Pool
- patch from mpe to automatically add parent directories
277
    # always versioned.
1713.1.11 by Robert Collins
refactor smart_add to pass around the parent inventory entry and use that, resulting in another 100bzrlib/inventory.py performance improvement, and making inventory writing the dominating factory in add. (Robert Collins)
278
    if parent_ie is not None:
279
        # we have a parent ie already
280
        added = []
281
    else:
282
        # slower but does not need parent_ie
283
        if inv.has_filename(path):
284
            return []
285
        # add parent
286
        added = __add_one(tree, inv, None, dirname(path), 'directory', action)
287
        parent_id = inv.path2id(dirname(path))
288
        if parent_id is not None:
289
            parent_ie = inv[inv.path2id(dirname(path))]
290
        else:
291
            parent_ie = None
292
    action(inv, parent_ie, path, kind)
1185.3.3 by Martin Pool
- patch from mpe to automatically add parent directories
293
1185.46.8 by Aaron Bentley
bzr add reports ignored patterns.
294
    return added + [path]