53 self.exclude = {} |
53 self.exclude = {} |
54 self.rename = {} |
54 self.rename = {} |
55 self.targetprefixes = None |
55 self.targetprefixes = None |
56 if path: |
56 if path: |
57 if self.parse(path): |
57 if self.parse(path): |
58 raise error.Abort(_('errors in filemap')) |
58 raise error.Abort(_(b'errors in filemap')) |
59 |
59 |
60 def parse(self, path): |
60 def parse(self, path): |
61 errs = 0 |
61 errs = 0 |
62 |
62 |
63 def check(name, mapping, listname): |
63 def check(name, mapping, listname): |
64 if not name: |
64 if not name: |
65 self.ui.warn( |
65 self.ui.warn( |
66 _('%s:%d: path to %s is missing\n') |
66 _(b'%s:%d: path to %s is missing\n') |
67 % (lex.infile, lex.lineno, listname) |
67 % (lex.infile, lex.lineno, listname) |
68 ) |
68 ) |
69 return 1 |
69 return 1 |
70 if name in mapping: |
70 if name in mapping: |
71 self.ui.warn( |
71 self.ui.warn( |
72 _('%s:%d: %r already in %s list\n') |
72 _(b'%s:%d: %r already in %s list\n') |
73 % (lex.infile, lex.lineno, name, listname) |
73 % (lex.infile, lex.lineno, name, listname) |
74 ) |
74 ) |
75 return 1 |
75 return 1 |
76 if name.startswith('/') or name.endswith('/') or '//' in name: |
76 if name.startswith(b'/') or name.endswith(b'/') or b'//' in name: |
77 self.ui.warn( |
77 self.ui.warn( |
78 _('%s:%d: superfluous / in %s %r\n') |
78 _(b'%s:%d: superfluous / in %s %r\n') |
79 % (lex.infile, lex.lineno, listname, pycompat.bytestr(name)) |
79 % (lex.infile, lex.lineno, listname, pycompat.bytestr(name)) |
80 ) |
80 ) |
81 return 1 |
81 return 1 |
82 return 0 |
82 return 0 |
83 |
83 |
84 lex = common.shlexer( |
84 lex = common.shlexer( |
85 filepath=path, wordchars='!@#$%^&*()-=+[]{}|;:,./<>?' |
85 filepath=path, wordchars=b'!@#$%^&*()-=+[]{}|;:,./<>?' |
86 ) |
86 ) |
87 cmd = lex.get_token() |
87 cmd = lex.get_token() |
88 while cmd: |
88 while cmd: |
89 if cmd == 'include': |
89 if cmd == b'include': |
90 name = normalize(lex.get_token()) |
90 name = normalize(lex.get_token()) |
91 errs += check(name, self.exclude, 'exclude') |
91 errs += check(name, self.exclude, b'exclude') |
92 self.include[name] = name |
92 self.include[name] = name |
93 elif cmd == 'exclude': |
93 elif cmd == b'exclude': |
94 name = normalize(lex.get_token()) |
94 name = normalize(lex.get_token()) |
95 errs += check(name, self.include, 'include') |
95 errs += check(name, self.include, b'include') |
96 errs += check(name, self.rename, 'rename') |
96 errs += check(name, self.rename, b'rename') |
97 self.exclude[name] = name |
97 self.exclude[name] = name |
98 elif cmd == 'rename': |
98 elif cmd == b'rename': |
99 src = normalize(lex.get_token()) |
99 src = normalize(lex.get_token()) |
100 dest = normalize(lex.get_token()) |
100 dest = normalize(lex.get_token()) |
101 errs += check(src, self.exclude, 'exclude') |
101 errs += check(src, self.exclude, b'exclude') |
102 self.rename[src] = dest |
102 self.rename[src] = dest |
103 elif cmd == 'source': |
103 elif cmd == b'source': |
104 errs += self.parse(normalize(lex.get_token())) |
104 errs += self.parse(normalize(lex.get_token())) |
105 else: |
105 else: |
106 self.ui.warn( |
106 self.ui.warn( |
107 _('%s:%d: unknown directive %r\n') |
107 _(b'%s:%d: unknown directive %r\n') |
108 % (lex.infile, lex.lineno, pycompat.bytestr(cmd)) |
108 % (lex.infile, lex.lineno, pycompat.bytestr(cmd)) |
109 ) |
109 ) |
110 errs += 1 |
110 errs += 1 |
111 cmd = lex.get_token() |
111 cmd = lex.get_token() |
112 return errs |
112 return errs |
116 for pre, suf in rpairs(name): |
116 for pre, suf in rpairs(name): |
117 try: |
117 try: |
118 return mapping[pre], pre, suf |
118 return mapping[pre], pre, suf |
119 except KeyError: |
119 except KeyError: |
120 pass |
120 pass |
121 return '', name, '' |
121 return b'', name, b'' |
122 |
122 |
123 def istargetfile(self, filename): |
123 def istargetfile(self, filename): |
124 """Return true if the given target filename is covered as a destination |
124 """Return true if the given target filename is covered as a destination |
125 of the filemap. This is useful for identifying what parts of the target |
125 of the filemap. This is useful for identifying what parts of the target |
126 repo belong to the source repo and what parts don't.""" |
126 repo belong to the source repo and what parts don't.""" |
129 for before, after in self.rename.iteritems(): |
129 for before, after in self.rename.iteritems(): |
130 self.targetprefixes.add(after) |
130 self.targetprefixes.add(after) |
131 |
131 |
132 # If "." is a target, then all target files are considered from the |
132 # If "." is a target, then all target files are considered from the |
133 # source. |
133 # source. |
134 if not self.targetprefixes or '.' in self.targetprefixes: |
134 if not self.targetprefixes or b'.' in self.targetprefixes: |
135 return True |
135 return True |
136 |
136 |
137 filename = normalize(filename) |
137 filename = normalize(filename) |
138 for pre, suf in rpairs(filename): |
138 for pre, suf in rpairs(filename): |
139 # This check is imperfect since it doesn't account for the |
139 # This check is imperfect since it doesn't account for the |
254 for rev, wanted, arg in self.convertedorder: |
254 for rev, wanted, arg in self.convertedorder: |
255 if rev not in self.origparents: |
255 if rev not in self.origparents: |
256 try: |
256 try: |
257 self.origparents[rev] = self.getcommit(rev).parents |
257 self.origparents[rev] = self.getcommit(rev).parents |
258 except error.RepoLookupError: |
258 except error.RepoLookupError: |
259 self.ui.debug("unknown revmap source: %s\n" % rev) |
259 self.ui.debug(b"unknown revmap source: %s\n" % rev) |
260 continue |
260 continue |
261 if arg is not None: |
261 if arg is not None: |
262 self.children[arg] = self.children.get(arg, 0) + 1 |
262 self.children[arg] = self.children.get(arg, 0) + 1 |
263 |
263 |
264 for rev, wanted, arg in self.convertedorder: |
264 for rev, wanted, arg in self.convertedorder: |
314 # indicated by i. If we're interested in any of these files, |
314 # indicated by i. If we're interested in any of these files, |
315 # we're interested in rev. |
315 # we're interested in rev. |
316 try: |
316 try: |
317 files = self.base.getchangedfiles(rev, i) |
317 files = self.base.getchangedfiles(rev, i) |
318 except NotImplementedError: |
318 except NotImplementedError: |
319 raise error.Abort(_("source repository doesn't support --filemap")) |
319 raise error.Abort(_(b"source repository doesn't support --filemap")) |
320 for f in files: |
320 for f in files: |
321 if self.filemapper(f): |
321 if self.filemapper(f): |
322 return True |
322 return True |
323 |
323 |
324 # The include directive is documented to include nothing else (though |
324 # The include directive is documented to include nothing else (though |
329 # Allow empty commits in the source revision through. The getchanges() |
329 # Allow empty commits in the source revision through. The getchanges() |
330 # method doesn't even bother calling this if it determines that the |
330 # method doesn't even bother calling this if it determines that the |
331 # close marker is significant (i.e. all of the branch ancestors weren't |
331 # close marker is significant (i.e. all of the branch ancestors weren't |
332 # eliminated). Therefore if there *is* a close marker, getchanges() |
332 # eliminated). Therefore if there *is* a close marker, getchanges() |
333 # doesn't consider it significant, and this revision should be dropped. |
333 # doesn't consider it significant, and this revision should be dropped. |
334 return not files and 'close' not in self.commits[rev].extra |
334 return not files and b'close' not in self.commits[rev].extra |
335 |
335 |
336 def mark_not_wanted(self, rev, p): |
336 def mark_not_wanted(self, rev, p): |
337 # Mark rev as not interesting and update data structures. |
337 # Mark rev as not interesting and update data structures. |
338 |
338 |
339 if p is None: |
339 if p is None: |