hgext/convert/filemap.py
changeset 5376 d60a067227a5
parent 5375 dae323e453aa
child 5377 756a43a30e34
equal deleted inserted replaced
5375:dae323e453aa 5376:d60a067227a5
       
     1 # Copyright 2007 Bryan O'Sullivan <bos@serpentine.com>
       
     2 #
       
     3 # This software may be used and distributed according to the terms of
       
     4 # the GNU General Public License, incorporated herein by reference.
       
     5 
       
     6 import shlex
       
     7 from mercurial.i18n import _
       
     8 from mercurial import util
       
     9 
       
    10 def rpairs(name):
       
    11     e = len(name)
       
    12     while e != -1:
       
    13         yield name[:e], name[e+1:]
       
    14         e = name.rfind('/', 0, e)
       
    15 
       
    16 class filemapper(object):
       
    17     '''Map and filter filenames when importing.
       
    18     A name can be mapped to itself, a new name, or None (omit from new
       
    19     repository).'''
       
    20 
       
    21     def __init__(self, ui, path=None):
       
    22         self.ui = ui
       
    23         self.include = {}
       
    24         self.exclude = {}
       
    25         self.rename = {}
       
    26         if path:
       
    27             if self.parse(path):
       
    28                 raise util.Abort(_('errors in filemap'))
       
    29 
       
    30     def parse(self, path):
       
    31         errs = 0
       
    32         def check(name, mapping, listname):
       
    33             if name in mapping:
       
    34                 self.ui.warn(_('%s:%d: %r already in %s list\n') %
       
    35                              (lex.infile, lex.lineno, name, listname))
       
    36                 return 1
       
    37             return 0
       
    38         lex = shlex.shlex(open(path), path, True)
       
    39         lex.wordchars += '!@#$%^&*()-=+[]{}|;:,./<>?'
       
    40         cmd = lex.get_token()
       
    41         while cmd:
       
    42             if cmd == 'include':
       
    43                 name = lex.get_token()
       
    44                 errs += check(name, self.exclude, 'exclude')
       
    45                 self.include[name] = name
       
    46             elif cmd == 'exclude':
       
    47                 name = lex.get_token()
       
    48                 errs += check(name, self.include, 'include')
       
    49                 errs += check(name, self.rename, 'rename')
       
    50                 self.exclude[name] = name
       
    51             elif cmd == 'rename':
       
    52                 src = lex.get_token()
       
    53                 dest = lex.get_token()
       
    54                 errs += check(src, self.exclude, 'exclude')
       
    55                 self.rename[src] = dest
       
    56             elif cmd == 'source':
       
    57                 errs += self.parse(lex.get_token())
       
    58             else:
       
    59                 self.ui.warn(_('%s:%d: unknown directive %r\n') %
       
    60                              (lex.infile, lex.lineno, cmd))
       
    61                 errs += 1
       
    62             cmd = lex.get_token()
       
    63         return errs
       
    64 
       
    65     def lookup(self, name, mapping):
       
    66         for pre, suf in rpairs(name):
       
    67             try:
       
    68                 return mapping[pre], pre, suf
       
    69             except KeyError, err:
       
    70                 pass
       
    71         return '', name, ''
       
    72 
       
    73     def __call__(self, name):
       
    74         if self.include:
       
    75             inc = self.lookup(name, self.include)[0]
       
    76         else:
       
    77             inc = name
       
    78         if self.exclude:
       
    79             exc = self.lookup(name, self.exclude)[0]
       
    80         else:
       
    81             exc = ''
       
    82         if not inc or exc:
       
    83             return None
       
    84         newpre, pre, suf = self.lookup(name, self.rename)
       
    85         if newpre:
       
    86             if newpre == '.':
       
    87                 return suf
       
    88             if suf:
       
    89                 return newpre + '/' + suf
       
    90             return newpre
       
    91         return name
       
    92 
       
    93     def active(self):
       
    94         return bool(self.include or self.exclude or self.rename)