~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/add.py

Paired performance tuning of bzr add. (Robert Collins, Martin Pool).

Show diffs side-by-side

added added

removed removed

Lines of Context:
97
97
    import os, errno
98
98
    from bzrlib.errors import BadFileKindError, ForbiddenFileError
99
99
    assert isinstance(recurse, bool)
100
 
 
 
100
    
 
101
    orig_list = file_list
101
102
    file_list = _prepare_file_list(file_list)
102
 
    user_list = file_list[:]
 
103
    mutter("smart add of %r, originally %r", file_list, orig_list)
103
104
    inv = tree.read_working_inventory()
104
105
    added = []
105
106
    ignored = {}
106
107
    user_files = set(file_list)
107
108
 
108
 
    for f in file_list:
109
 
        rf = tree.relpath(f)
110
 
        af = tree.abspath(rf)
111
 
 
 
109
    for filepath in file_list:
 
110
        # convert a random abs or cwd-relative path to tree relative.
 
111
        rf = tree.relpath(filepath)
 
112
 
 
113
        # validate user parameters. Our recursive code avoids adding new files
 
114
        # that need such validation 
 
115
        if filepath in user_files and tree.is_control_filename(rf):
 
116
            raise ForbiddenFileError('cannot add control file %s' % filepath)
 
117
 
 
118
        # find the kind of the path being added. This is not
 
119
        # currently determined when we list directories 
 
120
        # recursively, but in theory we can determine while 
 
121
        # doing the directory listing on *some* platformans.
 
122
        # TODO: a safe, portable, clean interface which will 
 
123
        # be faster than os.listdir() + stat. Specifically,
 
124
        # readdir - dirent.d_type supplies the file type when
 
125
        # it is defined. (Apparently Mac OSX has the field but
 
126
        # does not fill it in ?!) Robert C, Martin P.
112
127
        try:
113
 
            kind = bzrlib.osutils.file_kind(af)
 
128
            kind = bzrlib.osutils.file_kind(filepath)
114
129
        except OSError, e:
115
130
            if hasattr(e, 'errno') and e.errno == errno.ENOENT:
116
 
                raise errors.NoSuchFile(rf)
 
131
                raise errors.NoSuchFile(filepath)
117
132
            raise
118
133
 
 
134
        # we need to call this to determine the inventory kind to create.
119
135
        if not InventoryEntry.versionable_kind(kind):
120
 
            if f in user_list:
121
 
                raise BadFileKindError("cannot add %s of type %s" % (f, kind))
 
136
            if filepath in user_files:
 
137
                raise BadFileKindError("cannot add %s of type %s" % (filepath, kind))
122
138
            else:
123
 
                warning("skipping %s (can't add file of kind '%s')", f, kind)
 
139
                warning("skipping %s (can't add file of kind '%s')", filepath, kind)
124
140
                continue
125
141
 
126
 
        mutter("smart add of %r, abs=%r", f, af)
127
 
            
128
 
        # validate user parameters. Our recursive code avoids adding new files
129
 
        # that need such validation 
130
 
        if f in user_files and tree.is_control_filename(af):
131
 
            raise ForbiddenFileError('cannot add control file %s' % f)
132
 
 
133
 
        versioned = (inv.path2id(rf) != None)
 
142
        # TODO make has_filename faster or provide a better api for accessing/determining 
 
143
        # this status. perhaps off the inventory directory object.
 
144
        versioned = inv.has_filename(rf)
134
145
 
135
146
        if kind == 'directory':
136
147
            try:
137
 
                sub_branch = WorkingTree.open(af)
 
148
                sub_branch = bzrlib.bzrdir.BzrDir.open(filepath)
138
149
                sub_tree = True
139
150
            except NotBranchError:
140
151
                sub_tree = False
144
155
            sub_tree = False
145
156
 
146
157
        if rf == '':
147
 
            mutter("tree root doesn't need to be added")
 
158
            # mutter("tree root doesn't need to be added")
148
159
            sub_tree = False
149
160
        elif versioned:
150
 
            mutter("%r is already versioned", f)
 
161
            pass
 
162
            # mutter("%r is already versioned", filepath)
151
163
        elif sub_tree:
152
 
            mutter("%r is a bzr tree", f)
 
164
            mutter("%r is a nested bzr tree", filepath)
153
165
        else:
154
166
            added.extend(__add_one(tree, inv, rf, kind, action))
155
167
 
156
168
        if kind == 'directory' and recurse and not sub_tree:
157
 
            for subf in os.listdir(af):
 
169
            for subf in os.listdir(filepath):
 
170
                # here we could use TreeDirectory rather than 
 
171
                # string concatenation.
158
172
                subp = bzrlib.osutils.pathjoin(rf, subf)
 
173
                # TODO: is_control_filename is very slow. Make it faster. 
 
174
                # TreeDirectory.is_control_filename could also make this 
 
175
                # faster - its impossible for a non root dir to have a 
 
176
                # control file.
159
177
                if tree.is_control_filename(subp):
160
178
                    mutter("skip control directory %r", subp)
161
179
                else:
 
180
                    # ignore while selecting files - if we globbed in the
 
181
                    # outer loop we would ignore user files.
162
182
                    ignore_glob = tree.is_ignored(subp)
163
183
                    if ignore_glob is not None:
164
 
                        mutter("skip ignored sub-file %r", subp)
 
184
                        # mutter("skip ignored sub-file %r", subp)
165
185
                        if ignore_glob not in ignored:
166
186
                            ignored[ignore_glob] = []
167
187
                        ignored[ignore_glob].append(subp)
168
188
                    else:
169
 
                        mutter("queue to add sub-file %r", subp)
 
189
                        #mutter("queue to add sub-file %r", subp)
170
190
                        file_list.append(tree.abspath(subp))
171
191
 
172
 
    mutter('added %d entries', len(added))
173
 
    
174
192
    if len(added) > 0:
175
193
        tree._write_inventory(inv)
176
 
 
177
194
    return added, ignored
178
195
 
179
196