annotate hgext3rd/fastimport/vendor/python_fastimport/parser.py @ 86:28704a2a7461 vendor/python-fastimport

Import python-fastimport-0.9.8
author Roy Marples <roy@marples.name>
date Tue, 19 Jan 2021 22:56:34 +0000
parents
children 2fc99e3479d9
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
86
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
1 # Copyright (C) 2008-2010 Canonical Ltd
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
2 #
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
3 # This program is free software; you can redistribute it and/or modify
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
4 # it under the terms of the GNU General Public License as published by
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
5 # the Free Software Foundation; either version 2 of the License, or
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
6 # (at your option) any later version.
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
7 #
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
8 # This program is distributed in the hope that it will be useful,
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
11 # GNU General Public License for more details.
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
12 #
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
13 # You should have received a copy of the GNU General Public License
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
14 # along with this program. If not, see <http://www.gnu.org/licenses/>.
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
15
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
16 """Parser of import data into command objects.
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
17
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
18 In order to reuse existing front-ends, the stream format is a subset of
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
19 the one used by git-fast-import (as of the 1.5.4 release of git at least).
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
20 The grammar is:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
21
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
22 stream ::= cmd*;
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
23
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
24 cmd ::= new_blob
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
25 | new_commit
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
26 | new_tag
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
27 | reset_branch
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
28 | checkpoint
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
29 | progress
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
30 ;
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
31
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
32 new_blob ::= 'blob' lf
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
33 mark?
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
34 file_content;
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
35 file_content ::= data;
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
36
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
37 new_commit ::= 'commit' sp ref_str lf
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
38 mark?
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
39 ('author' sp name '<' email '>' when lf)?
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
40 'committer' sp name '<' email '>' when lf
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
41 commit_msg
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
42 ('from' sp (ref_str | hexsha1 | sha1exp_str | idnum) lf)?
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
43 ('merge' sp (ref_str | hexsha1 | sha1exp_str | idnum) lf)*
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
44 file_change*
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
45 lf?;
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
46 commit_msg ::= data;
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
47
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
48 file_change ::= file_clr
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
49 | file_del
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
50 | file_rnm
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
51 | file_cpy
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
52 | file_obm
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
53 | file_inm;
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
54 file_clr ::= 'deleteall' lf;
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
55 file_del ::= 'D' sp path_str lf;
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
56 file_rnm ::= 'R' sp path_str sp path_str lf;
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
57 file_cpy ::= 'C' sp path_str sp path_str lf;
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
58 file_obm ::= 'M' sp mode sp (hexsha1 | idnum) sp path_str lf;
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
59 file_inm ::= 'M' sp mode sp 'inline' sp path_str lf
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
60 data;
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
61
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
62 new_tag ::= 'tag' sp tag_str lf
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
63 'from' sp (ref_str | hexsha1 | sha1exp_str | idnum) lf
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
64 'tagger' sp name '<' email '>' when lf
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
65 tag_msg;
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
66 tag_msg ::= data;
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
67
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
68 reset_branch ::= 'reset' sp ref_str lf
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
69 ('from' sp (ref_str | hexsha1 | sha1exp_str | idnum) lf)?
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
70 lf?;
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
71
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
72 checkpoint ::= 'checkpoint' lf
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
73 lf?;
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
74
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
75 progress ::= 'progress' sp not_lf* lf
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
76 lf?;
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
77
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
78 # note: the first idnum in a stream should be 1 and subsequent
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
79 # idnums should not have gaps between values as this will cause
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
80 # the stream parser to reserve space for the gapped values. An
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
81 # idnum can be updated in the future to a new object by issuing
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
82 # a new mark directive with the old idnum.
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
83 #
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
84 mark ::= 'mark' sp idnum lf;
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
85 data ::= (delimited_data | exact_data)
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
86 lf?;
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
87
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
88 # note: delim may be any string but must not contain lf.
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
89 # data_line may contain any data but must not be exactly
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
90 # delim. The lf after the final data_line is included in
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
91 # the data.
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
92 delimited_data ::= 'data' sp '<<' delim lf
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
93 (data_line lf)*
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
94 delim lf;
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
95
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
96 # note: declen indicates the length of binary_data in bytes.
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
97 # declen does not include the lf preceeding the binary data.
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
98 #
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
99 exact_data ::= 'data' sp declen lf
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
100 binary_data;
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
101
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
102 # note: quoted strings are C-style quoting supporting \c for
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
103 # common escapes of 'c' (e..g \n, \t, \\, \") or \nnn where nnn
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
104 # is the signed byte value in octal. Note that the only
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
105 # characters which must actually be escaped to protect the
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
106 # stream formatting is: \, " and LF. Otherwise these values
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
107 # are UTF8.
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
108 #
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
109 ref_str ::= ref;
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
110 sha1exp_str ::= sha1exp;
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
111 tag_str ::= tag;
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
112 path_str ::= path | '"' quoted(path) '"' ;
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
113 mode ::= '100644' | '644'
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
114 | '100755' | '755'
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
115 | '120000'
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
116 ;
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
117
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
118 declen ::= # unsigned 32 bit value, ascii base10 notation;
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
119 bigint ::= # unsigned integer value, ascii base10 notation;
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
120 binary_data ::= # file content, not interpreted;
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
121
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
122 when ::= raw_when | rfc2822_when;
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
123 raw_when ::= ts sp tz;
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
124 rfc2822_when ::= # Valid RFC 2822 date and time;
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
125
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
126 sp ::= # ASCII space character;
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
127 lf ::= # ASCII newline (LF) character;
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
128
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
129 # note: a colon (':') must precede the numerical value assigned to
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
130 # an idnum. This is to distinguish it from a ref or tag name as
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
131 # GIT does not permit ':' in ref or tag strings.
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
132 #
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
133 idnum ::= ':' bigint;
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
134 path ::= # GIT style file path, e.g. "a/b/c";
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
135 ref ::= # GIT ref name, e.g. "refs/heads/MOZ_GECKO_EXPERIMENT";
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
136 tag ::= # GIT tag name, e.g. "FIREFOX_1_5";
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
137 sha1exp ::= # Any valid GIT SHA1 expression;
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
138 hexsha1 ::= # SHA1 in hexadecimal format;
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
139
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
140 # note: name and email are UTF8 strings, however name must not
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
141 # contain '<' or lf and email must not contain any of the
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
142 # following: '<', '>', lf.
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
143 #
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
144 name ::= # valid GIT author/committer name;
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
145 email ::= # valid GIT author/committer email;
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
146 ts ::= # time since the epoch in seconds, ascii base10 notation;
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
147 tz ::= # GIT style timezone;
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
148
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
149 # note: comments may appear anywhere in the input, except
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
150 # within a data command. Any form of the data command
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
151 # always escapes the related input from comment processing.
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
152 #
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
153 # In case it is not clear, the '#' that starts the comment
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
154 # must be the first character on that the line (an lf have
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
155 # preceeded it).
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
156 #
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
157 comment ::= '#' not_lf* lf;
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
158 not_lf ::= # Any byte that is not ASCII newline (LF);
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
159 """
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
160 from __future__ import print_function
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
161
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
162 import collections
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
163 import re
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
164 import sys
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
165 import codecs
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
166
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
167 from fastimport import (
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
168 commands,
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
169 dates,
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
170 errors,
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
171 )
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
172 from fastimport.helpers import (
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
173 newobject as object,
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
174 utf8_bytes_string,
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
175 )
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
176
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
177
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
178 ## Stream parsing ##
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
179
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
180 class LineBasedParser(object):
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
181
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
182 def __init__(self, input_stream):
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
183 """A Parser that keeps track of line numbers.
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
184
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
185 :param input: the file-like object to read from
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
186 """
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
187 self.input = input_stream
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
188 self.lineno = 0
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
189 # Lines pushed back onto the input stream
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
190 self._buffer = []
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
191
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
192 def abort(self, exception, *args):
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
193 """Raise an exception providing line number information."""
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
194 raise exception(self.lineno, *args)
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
195
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
196 def readline(self):
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
197 """Get the next line including the newline or '' on EOF."""
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
198 self.lineno += 1
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
199 if self._buffer:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
200 return self._buffer.pop()
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
201 else:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
202 return self.input.readline()
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
203
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
204 def next_line(self):
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
205 """Get the next line without the newline or None on EOF."""
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
206 line = self.readline()
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
207 if line:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
208 return line[:-1]
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
209 else:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
210 return None
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
211
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
212 def push_line(self, line):
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
213 """Push line back onto the line buffer.
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
214
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
215 :param line: the line with no trailing newline
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
216 """
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
217 self.lineno -= 1
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
218 self._buffer.append(line + b'\n')
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
219
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
220 def read_bytes(self, count):
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
221 """Read a given number of bytes from the input stream.
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
222
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
223 Throws MissingBytes if the bytes are not found.
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
224
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
225 Note: This method does not read from the line buffer.
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
226
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
227 :return: a string
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
228 """
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
229 result = self.input.read(count)
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
230 found = len(result)
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
231 self.lineno += result.count(b'\n')
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
232 if found != count:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
233 self.abort(errors.MissingBytes, count, found)
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
234 return result
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
235
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
236 def read_until(self, terminator):
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
237 """Read the input stream until the terminator is found.
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
238
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
239 Throws MissingTerminator if the terminator is not found.
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
240
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
241 Note: This method does not read from the line buffer.
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
242
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
243 :return: the bytes read up to but excluding the terminator.
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
244 """
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
245
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
246 lines = []
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
247 term = terminator + b'\n'
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
248 while True:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
249 line = self.input.readline()
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
250 if line == term:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
251 break
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
252 else:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
253 lines.append(line)
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
254 return b''.join(lines)
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
255
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
256
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
257 # Regular expression used for parsing. (Note: The spec states that the name
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
258 # part should be non-empty but git-fast-export doesn't always do that so
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
259 # the first bit is \w*, not \w+.) Also git-fast-import code says the
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
260 # space before the email is optional.
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
261 _WHO_AND_WHEN_RE = re.compile(br'([^<]*)<(.*)> (.+)')
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
262 _WHO_RE = re.compile(br'([^<]*)<(.*)>')
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
263
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
264
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
265 class ImportParser(LineBasedParser):
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
266
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
267 def __init__(self, input_stream, verbose=False, output=sys.stdout,
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
268 user_mapper=None, strict=True):
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
269 """A Parser of import commands.
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
270
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
271 :param input_stream: the file-like object to read from
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
272 :param verbose: display extra information of not
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
273 :param output: the file-like object to write messages to (YAGNI?)
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
274 :param user_mapper: if not None, the UserMapper used to adjust
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
275 user-ids for authors, committers and taggers.
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
276 :param strict: Raise errors on strictly invalid data
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
277 """
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
278 LineBasedParser.__init__(self, input_stream)
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
279 self.verbose = verbose
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
280 self.output = output
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
281 self.user_mapper = user_mapper
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
282 self.strict = strict
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
283 # We auto-detect the date format when a date is first encountered
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
284 self.date_parser = None
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
285 self.features = {}
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
286
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
287 def warning(self, msg):
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
288 sys.stderr.write("warning line %d: %s\n" % (self.lineno, msg))
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
289
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
290 def iter_commands(self):
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
291 """Iterator returning ImportCommand objects."""
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
292 while True:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
293 line = self.next_line()
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
294 if line is None:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
295 if b'done' in self.features:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
296 raise errors.PrematureEndOfStream(self.lineno)
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
297 break
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
298 elif len(line) == 0 or line.startswith(b'#'):
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
299 continue
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
300 # Search for commands in order of likelihood
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
301 elif line.startswith(b'commit '):
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
302 yield self._parse_commit(line[len(b'commit '):])
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
303 elif line.startswith(b'blob'):
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
304 yield self._parse_blob()
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
305 elif line.startswith(b'done'):
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
306 break
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
307 elif line.startswith(b'progress '):
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
308 yield commands.ProgressCommand(line[len(b'progress '):])
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
309 elif line.startswith(b'reset '):
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
310 yield self._parse_reset(line[len(b'reset '):])
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
311 elif line.startswith(b'tag '):
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
312 yield self._parse_tag(line[len(b'tag '):])
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
313 elif line.startswith(b'checkpoint'):
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
314 yield commands.CheckpointCommand()
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
315 elif line.startswith(b'feature'):
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
316 yield self._parse_feature(line[len(b'feature '):])
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
317 else:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
318 self.abort(errors.InvalidCommand, line)
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
319
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
320 def iter_file_commands(self):
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
321 """Iterator returning FileCommand objects.
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
322
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
323 If an invalid file command is found, the line is silently
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
324 pushed back and iteration ends.
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
325 """
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
326 while True:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
327 line = self.next_line()
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
328 if line is None:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
329 break
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
330 elif len(line) == 0 or line.startswith(b'#'):
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
331 continue
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
332 # Search for file commands in order of likelihood
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
333 elif line.startswith(b'M '):
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
334 yield self._parse_file_modify(line[2:])
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
335 elif line.startswith(b'D '):
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
336 path = self._path(line[2:])
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
337 yield commands.FileDeleteCommand(path)
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
338 elif line.startswith(b'R '):
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
339 old, new = self._path_pair(line[2:])
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
340 yield commands.FileRenameCommand(old, new)
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
341 elif line.startswith(b'C '):
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
342 src, dest = self._path_pair(line[2:])
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
343 yield commands.FileCopyCommand(src, dest)
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
344 elif line.startswith(b'deleteall'):
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
345 yield commands.FileDeleteAllCommand()
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
346 else:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
347 self.push_line(line)
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
348 break
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
349
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
350 def _parse_blob(self):
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
351 """Parse a blob command."""
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
352 lineno = self.lineno
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
353 mark = self._get_mark_if_any()
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
354 data = self._get_data(b'blob')
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
355 return commands.BlobCommand(mark, data, lineno)
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
356
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
357 def _parse_commit(self, ref):
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
358 """Parse a commit command."""
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
359 lineno = self.lineno
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
360 mark = self._get_mark_if_any()
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
361 author = self._get_user_info(b'commit', b'author', False)
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
362 more_authors = []
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
363 while True:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
364 another_author = self._get_user_info(b'commit', b'author', False)
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
365 if another_author is not None:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
366 more_authors.append(another_author)
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
367 else:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
368 break
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
369 committer = self._get_user_info(b'commit', b'committer')
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
370 message = self._get_data(b'commit', b'message')
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
371 from_ = self._get_from()
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
372 merges = []
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
373 while True:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
374 merge = self._get_merge()
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
375 if merge is not None:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
376 # while the spec suggests it's illegal, git-fast-export
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
377 # outputs multiple merges on the one line, e.g.
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
378 # merge :x :y :z
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
379 these_merges = merge.split(b' ')
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
380 merges.extend(these_merges)
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
381 else:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
382 break
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
383 properties = {}
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
384 while True:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
385 name_value = self._get_property()
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
386 if name_value is not None:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
387 name, value = name_value
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
388 properties[name] = value
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
389 else:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
390 break
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
391 return commands.CommitCommand(ref, mark, author, committer, message,
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
392 from_, merges, list(self.iter_file_commands()), lineno=lineno,
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
393 more_authors=more_authors, properties=properties)
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
394
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
395 def _parse_feature(self, info):
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
396 """Parse a feature command."""
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
397 parts = info.split(b'=', 1)
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
398 name = parts[0]
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
399 if len(parts) > 1:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
400 value = self._path(parts[1])
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
401 else:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
402 value = None
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
403 self.features[name] = value
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
404 return commands.FeatureCommand(name, value, lineno=self.lineno)
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
405
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
406 def _parse_file_modify(self, info):
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
407 """Parse a filemodify command within a commit.
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
408
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
409 :param info: a string in the format "mode dataref path"
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
410 (where dataref might be the hard-coded literal 'inline').
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
411 """
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
412 params = info.split(b' ', 2)
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
413 path = self._path(params[2])
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
414 mode = self._mode(params[0])
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
415 if params[1] == b'inline':
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
416 dataref = None
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
417 data = self._get_data(b'filemodify')
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
418 else:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
419 dataref = params[1]
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
420 data = None
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
421 return commands.FileModifyCommand(path, mode, dataref,
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
422 data)
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
423
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
424 def _parse_reset(self, ref):
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
425 """Parse a reset command."""
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
426 from_ = self._get_from()
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
427 return commands.ResetCommand(ref, from_)
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
428
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
429 def _parse_tag(self, name):
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
430 """Parse a tag command."""
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
431 from_ = self._get_from(b'tag')
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
432 tagger = self._get_user_info(b'tag', b'tagger',
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
433 accept_just_who=True)
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
434 message = self._get_data(b'tag', b'message')
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
435 return commands.TagCommand(name, from_, tagger, message)
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
436
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
437 def _get_mark_if_any(self):
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
438 """Parse a mark section."""
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
439 line = self.next_line()
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
440 if line.startswith(b'mark :'):
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
441 return line[len(b'mark :'):]
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
442 else:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
443 self.push_line(line)
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
444 return None
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
445
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
446 def _get_from(self, required_for=None):
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
447 """Parse a from section."""
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
448 line = self.next_line()
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
449 if line is None:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
450 return None
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
451 elif line.startswith(b'from '):
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
452 return line[len(b'from '):]
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
453 elif required_for:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
454 self.abort(errors.MissingSection, required_for, 'from')
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
455 else:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
456 self.push_line(line)
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
457 return None
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
458
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
459 def _get_merge(self):
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
460 """Parse a merge section."""
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
461 line = self.next_line()
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
462 if line is None:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
463 return None
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
464 elif line.startswith(b'merge '):
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
465 return line[len(b'merge '):]
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
466 else:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
467 self.push_line(line)
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
468 return None
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
469
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
470 def _get_property(self):
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
471 """Parse a property section."""
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
472 line = self.next_line()
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
473 if line is None:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
474 return None
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
475 elif line.startswith(b'property '):
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
476 return self._name_value(line[len(b'property '):])
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
477 else:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
478 self.push_line(line)
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
479 return None
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
480
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
481 def _get_user_info(self, cmd, section, required=True,
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
482 accept_just_who=False):
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
483 """Parse a user section."""
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
484 line = self.next_line()
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
485 if line.startswith(section + b' '):
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
486 return self._who_when(line[len(section + b' '):], cmd, section,
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
487 accept_just_who=accept_just_who)
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
488 elif required:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
489 self.abort(errors.MissingSection, cmd, section)
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
490 else:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
491 self.push_line(line)
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
492 return None
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
493
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
494 def _get_data(self, required_for, section=b'data'):
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
495 """Parse a data section."""
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
496 line = self.next_line()
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
497 if line.startswith(b'data '):
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
498 rest = line[len(b'data '):]
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
499 if rest.startswith(b'<<'):
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
500 return self.read_until(rest[2:])
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
501 else:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
502 size = int(rest)
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
503 read_bytes = self.read_bytes(size)
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
504 # optional LF after data.
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
505 next_line = self.input.readline()
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
506 self.lineno += 1
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
507 if len(next_line) > 1 or next_line != b'\n':
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
508 self.push_line(next_line[:-1])
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
509 return read_bytes
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
510 else:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
511 self.abort(errors.MissingSection, required_for, section)
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
512
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
513 def _who_when(self, s, cmd, section, accept_just_who=False):
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
514 """Parse who and when information from a string.
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
515
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
516 :return: a tuple of (name,email,timestamp,timezone). name may be
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
517 the empty string if only an email address was given.
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
518 """
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
519 match = _WHO_AND_WHEN_RE.search(s)
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
520 if match:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
521 datestr = match.group(3).lstrip()
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
522 if self.date_parser is None:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
523 # auto-detect the date format
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
524 if len(datestr.split(b' ')) == 2:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
525 date_format = 'raw'
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
526 elif datestr == b'now':
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
527 date_format = 'now'
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
528 else:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
529 date_format = 'rfc2822'
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
530 self.date_parser = dates.DATE_PARSERS_BY_NAME[date_format]
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
531 try:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
532 when = self.date_parser(datestr, self.lineno)
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
533 except ValueError:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
534 print("failed to parse datestr '%s'" % (datestr,))
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
535 raise
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
536 name = match.group(1).rstrip()
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
537 email = match.group(2)
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
538 else:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
539 match = _WHO_RE.search(s)
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
540 if accept_just_who and match:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
541 # HACK around missing time
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
542 # TODO: output a warning here
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
543 when = dates.DATE_PARSERS_BY_NAME['now']('now')
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
544 name = match.group(1)
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
545 email = match.group(2)
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
546 elif self.strict:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
547 self.abort(errors.BadFormat, cmd, section, s)
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
548 else:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
549 name = s
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
550 email = None
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
551 when = dates.DATE_PARSERS_BY_NAME['now']('now')
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
552 if len(name) > 0:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
553 if name.endswith(b' '):
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
554 name = name[:-1]
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
555 # While it shouldn't happen, some datasets have email addresses
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
556 # which contain unicode characters. See bug 338186. We sanitize
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
557 # the data at this level just in case.
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
558 if self.user_mapper:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
559 name, email = self.user_mapper.map_name_and_email(name, email)
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
560
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
561 return Authorship(name, email, when[0], when[1])
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
562
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
563 def _name_value(self, s):
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
564 """Parse a (name,value) tuple from 'name value-length value'."""
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
565 parts = s.split(b' ', 2)
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
566 name = parts[0]
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
567 if len(parts) == 1:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
568 value = None
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
569 else:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
570 size = int(parts[1])
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
571 value = parts[2]
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
572 still_to_read = size - len(value)
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
573 if still_to_read > 0:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
574 read_bytes = self.read_bytes(still_to_read)
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
575 value += b'\n' + read_bytes[:still_to_read - 1]
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
576 return (name, value)
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
577
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
578 def _path(self, s):
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
579 """Parse a path."""
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
580 if s.startswith(b'"'):
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
581 if not s.endswith(b'"'):
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
582 self.abort(errors.BadFormat, '?', '?', s)
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
583 else:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
584 return _unquote_c_string(s[1:-1])
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
585 return s
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
586
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
587 def _path_pair(self, s):
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
588 """Parse two paths separated by a space."""
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
589 # TODO: handle a space in the first path
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
590 if s.startswith(b'"'):
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
591 parts = s[1:].split(b'" ', 1)
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
592 else:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
593 parts = s.split(b' ', 1)
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
594 if len(parts) != 2:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
595 self.abort(errors.BadFormat, '?', '?', s)
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
596 elif parts[1].startswith(b'"') and parts[1].endswith(b'"'):
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
597 parts[1] = parts[1][1:-1]
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
598 elif parts[1].startswith(b'"') or parts[1].endswith(b'"'):
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
599 self.abort(errors.BadFormat, '?', '?', s)
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
600 return [_unquote_c_string(s) for s in parts]
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
601
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
602 def _mode(self, s):
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
603 """Check file mode format and parse into an int.
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
604
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
605 :return: mode as integer
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
606 """
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
607 # Note: Output from git-fast-export slightly different to spec
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
608 if s in [b'644', b'100644', b'0100644']:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
609 return 0o100644
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
610 elif s in [b'755', b'100755', b'0100755']:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
611 return 0o100755
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
612 elif s in [b'040000', b'0040000']:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
613 return 0o40000
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
614 elif s in [b'120000', b'0120000']:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
615 return 0o120000
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
616 elif s in [b'160000', b'0160000']:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
617 return 0o160000
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
618 else:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
619 self.abort(errors.BadFormat, 'filemodify', 'mode', s)
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
620
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
621
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
622 ESCAPE_SEQUENCE_BYTES_RE = re.compile(br'''
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
623 ( \\U........ # 8-digit hex escapes
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
624 | \\u.... # 4-digit hex escapes
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
625 | \\x.. # 2-digit hex escapes
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
626 | \\[0-7]{1,3} # Octal escapes
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
627 | \\N\{[^}]+\} # Unicode characters by name
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
628 | \\[\\'"abfnrtv] # Single-character escapes
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
629 )''', re.VERBOSE
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
630 )
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
631
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
632 ESCAPE_SEQUENCE_RE = re.compile(r'''
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
633 ( \\U........
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
634 | \\u....
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
635 | \\x..
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
636 | \\[0-7]{1,3}
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
637 | \\N\{[^}]+\}
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
638 | \\[\\'"abfnrtv]
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
639 )''', re.UNICODE | re.VERBOSE
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
640 )
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
641
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
642 def _unquote_c_string(s):
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
643 """replace C-style escape sequences (\n, \", etc.) with real chars."""
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
644
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
645 # doing a s.encode('utf-8').decode('unicode_escape') can return an
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
646 # incorrect output with unicode string (both in py2 and py3) the safest way
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
647 # is to match the escape sequences and decoding them alone.
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
648 def decode_match(match):
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
649 return utf8_bytes_string(
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
650 codecs.decode(match.group(0), 'unicode-escape')
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
651 )
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
652
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
653 if sys.version_info[0] >= 3 and isinstance(s, bytes):
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
654 return ESCAPE_SEQUENCE_BYTES_RE.sub(decode_match, s)
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
655 else:
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
656 return ESCAPE_SEQUENCE_RE.sub(decode_match, s)
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
657
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
658
28704a2a7461 Import python-fastimport-0.9.8
Roy Marples <roy@marples.name>
parents:
diff changeset
659 Authorship = collections.namedtuple('Authorship', 'name email timestamp timezone')