/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/ignores.py

Add bzrlib.pyutils, which has get_named_object, a wrapper around __import__.

This is used to replace various ad hoc implementations of the same logic,
notably the version used in registry's _LazyObjectGetter which had a bug when
getting a module without also getting a member.  And of course, this new
function has unit tests, unlike the replaced code.

This also adds a KnownHooksRegistry subclass to provide a more natural home for
some other logic.

I'm not thrilled about the name of the new module or the new functions, but it's
hard to think of good names for such generic functionality.

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
"""Lists of ignore files, etc."""
18
18
 
19
19
import errno
 
20
import os
 
21
from cStringIO import StringIO
20
22
 
21
23
import bzrlib
22
24
from bzrlib import (
39
41
    '*~',
40
42
    '.#*',
41
43
    '[#]*#',
 
44
    '__pycache__',
42
45
]
43
46
 
44
47
 
181
184
    The ignore file will be automatically added under version control.
182
185
 
183
186
    :param tree: Working tree to update the ignore list.
 
187
    :param name_pattern_list: List of ignore patterns.
 
188
    :return: None
184
189
    """
 
190
    # read in the existing ignores set
185
191
    ifn = tree.abspath(bzrlib.IGNORE_FILENAME)
186
192
    if tree.has_filename(ifn):
187
 
        f = open(ifn, 'rt')
 
193
        f = open(ifn, 'rU')
188
194
        try:
189
 
            igns = f.read().decode('utf-8')
 
195
            file_contents = f.read()
 
196
            # figure out what kind of line endings are used
 
197
            newline = getattr(f, 'newlines', None)
 
198
            if type(newline) is tuple:
 
199
                newline = newline[0]
 
200
            elif newline is None:
 
201
                newline = os.linesep
190
202
        finally:
191
203
            f.close()
192
204
    else:
193
 
        igns = ""
194
 
 
195
 
    # TODO: If the file already uses crlf-style termination, maybe
196
 
    # we should use that for the newly added lines?
197
 
 
198
 
    if igns and igns[-1] != '\n':
199
 
        igns += '\n'
200
 
    for name_pattern in name_pattern_list:
201
 
        igns += name_pattern + '\n'
202
 
 
 
205
        file_contents = ""
 
206
        newline = os.linesep
 
207
    
 
208
    sio = StringIO(file_contents)
 
209
    try:
 
210
        ignores = parse_ignore_file(sio)
 
211
    finally:
 
212
        sio.close()
 
213
    
 
214
    # write out the updated ignores set
203
215
    f = atomicfile.AtomicFile(ifn, 'wb')
204
216
    try:
205
 
        f.write(igns.encode('utf-8'))
 
217
        # write the original contents, preserving original line endings
 
218
        f.write(newline.join(file_contents.split('\n')))
 
219
        if len(file_contents) > 0 and not file_contents.endswith('\n'):
 
220
            f.write(newline)
 
221
        for pattern in name_pattern_list:
 
222
            if not pattern in ignores:
 
223
                f.write(pattern.encode('utf-8'))
 
224
                f.write(newline)
206
225
        f.commit()
207
226
    finally:
208
227
        f.close()