| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 60dd946 commit a15f791
2 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -480,6 +480,32 @@ def is_line_continuation(value: str) -> bool: | |||
| 480 | 480 | return False | |
| 481 | 481 | return escaped | |
| 482 | 482 | ||
| 483 | + def parse_value(value: str) -> str: | ||
| 484 | + parsed: List[str] = [] | ||
| 485 | + whitespace: List[str] = [] | ||
| 486 | + quoted = escaped = False | ||
| 487 | + escapes = {"b": "\b", "n": "\n", "t": "\t", '"': '"', "\\": "\\"} | ||
| 488 | + for char in value: | ||
| 489 | + if escaped: | ||
| 490 | + parsed.append(escapes.get(char, "\\" + char)) | ||
| 491 | + escaped = False | ||
| 492 | + continue | ||
| 493 | + if char.isspace() and not quoted: | ||
| 494 | + if parsed: | ||
| 495 | + whitespace.append(char) | ||
| 496 | + continue | ||
| 497 | + if char in "#;" and not quoted: | ||
| 498 | + break | ||
| 499 | + parsed.extend(whitespace) | ||
| 500 | + whitespace.clear() | ||
| 501 | + if char == "\\": | ||
| 502 | + escaped = True | ||
| 503 | + elif char == '"': | ||
| 504 | + quoted = not quoted | ||
| 505 | + else: | ||
| 506 | + parsed.append(char) | ||
| 507 | + return "".join(parsed) | ||
| 508 | + | ||
| 483 | 509 | while True: | |
| 484 | 510 | # We assume to read binary! | |
| 485 | 511 | line = fp.readline().decode(defenc) | |
@@ -529,9 +555,10 @@ def is_line_continuation(value: str) -> bool: | |||
| 529 | 555 | # A value ending in an odd number of backslashes | |
| 530 | 556 | # continues on the next line, exactly as git does: the | |
| 531 | 557 | # final backslash and the newline are removed and the | |
| 532 | - # next line is appended verbatim (leading whitespace | ||
| 533 | - # included). An even number means the last backslash | ||
| 534 | - # is escaped and the value ends there. | ||
| 558 | + # next line is appended before the complete value is | ||
| 559 | + # parsed. An even number means the last backslash is | ||
| 560 | + # escaped and the value ends there. | ||
| 561 | + continued = False | ||
| 535 | 562 | while True: | |
| 536 | 563 | if not is_line_continuation(optval): | |
| 537 | 564 | break | |
@@ -545,6 +572,9 @@ def is_line_continuation(value: str) -> bool: | |||
| 545 | 572 | while joined.endswith("\n") or joined.endswith("\r"): | |
| 546 | 573 | joined = joined[:-1] | |
| 547 | 574 | optval = optval[:-1] + joined | |
| 575 | + continued = True | ||
| 576 | + if continued: | ||
| 577 | + optval = parse_value(optval) | ||
| 548 | 578 | elif optval[-1] != '"': | |
| 549 | 579 | # Opens quoting and does not close: appears to start multi-line quoting. | |
| 550 | 580 | is_multi_line = True | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -146,10 +146,14 @@ def test_multi_line_config(self): | |||
| 146 | 146 | def test_backslash_line_continuation(self): | |
| 147 | 147 | """An unquoted value ending in a backslash continues on the next line, | |
| 148 | 148 | exactly as git config parses it: the final backslash and the newline | |
| 149 | - are removed and the next line is appended verbatim.""" | ||
| 149 | + are removed before the complete logical value is parsed.""" | ||
| 150 | 150 | cases = [ | |
| 151 | 151 | (b"[a]\n\tk = line1\\\n line2\n", "line1 line2"), | |
| 152 | 152 | (b"[a]\n\tk = one\\\n two\\\n three\n", "one two three"), | |
| 153 | + (b"[a]\n\tk = one\\\n two \n", "one two"), | ||
| 154 | + (b"[a]\n\tk = one\\\n two ; ignored\n", "one two"), | ||
| 155 | + (b'[a]\n\tk = one\\\n "two"\n', "one two"), | ||
| 156 | + (b"[a]\n\tk = one\\\n two\\tthree\n", "one two\tthree"), | ||
| 153 | 157 | (b"[a]\n\tk = val\\\\\n next\n", "val\\\\"), | |
| 154 | 158 | (b"[a]\n\tk = end\\\n", "end"), | |
| 155 | 159 | (b"[alias]\n\tco = checkout \\\n\t\t-v\n", "checkout \t\t-v"), | |
@@ -170,6 +174,7 @@ def test_comment_backslash_does_not_continue_value(self, rw_dir): | |||
| 170 | 174 | config_file.write(b"[a]\n\tk = one\\\n two ; ignored \\\n\tx = two\n") | |
| 171 | 175 | ||
| 172 | 176 | with GitConfigParser(config_path, read_only=False) as config: | |
| 177 | + self.assertEqual(config.get_value("a", "k"), "one two") | ||
| 173 | 178 | self.assertEqual(config.get_value("a", "x"), "two") | |
| 174 | 179 | config.set_value("a", "added", "three") | |
| 175 | 180 | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments