| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 62d1e2f commit 075a664
2 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -513,7 +513,26 @@ def string_decode(v: str) -> str: | |||
| 513 | 513 | ||
| 514 | 514 | if len(optval) < 2 or optval[0] != '"': | |
| 515 | 515 | # Does not open quoting. | |
| 516 | - pass | ||
| 516 | + # A value ending in an odd number of backslashes | ||
| 517 | + # continues on the next line, exactly as git does: the | ||
| 518 | + # final backslash and the newline are removed and the | ||
| 519 | + # next line is appended verbatim (leading whitespace | ||
| 520 | + # included). An even number means the last backslash | ||
| 521 | + # is escaped and the value ends there. | ||
| 522 | + while True: | ||
| 523 | + trailing = len(optval) - len(optval.rstrip("\\")) | ||
| 524 | + if trailing % 2 == 0: | ||
| 525 | + break | ||
| 526 | + continuation = fp.readline() | ||
| 527 | + if not continuation: | ||
| 528 | + # Backslash at end of file: git drops it. | ||
| 529 | + optval = optval[:-1] | ||
| 530 | + break | ||
| 531 | + lineno = lineno + 1 | ||
| 532 | + joined = continuation.decode(defenc) | ||
| 533 | + while joined.endswith("\n") or joined.endswith("\r"): | ||
| 534 | + joined = joined[:-1] | ||
| 535 | + optval = optval[:-1] + joined | ||
| 517 | 536 | elif optval[-1] != '"': | |
| 518 | 537 | # Opens quoting and does not close: appears to start multi-line quoting. | |
| 519 | 538 | is_multi_line = True | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -143,6 +143,26 @@ def test_multi_line_config(self): | |||
| 143 | 143 | ) | |
| 144 | 144 | self.assertEqual(len(config.sections()), 23) | |
| 145 | 145 | ||
| 146 | + def test_backslash_line_continuation(self): | ||
| 147 | + """An unquoted value ending in a backslash continues on the next line, | ||
| 148 | + exactly as git config parses it: the final backslash and the newline | ||
| 149 | + are removed and the next line is appended verbatim.""" | ||
| 150 | + cases = [ | ||
| 151 | + (b"[a]\n\tk = line1\\\n line2\n", "line1 line2"), | ||
| 152 | + (b"[a]\n\tk = one\\\n two\\\n three\n", "one two three"), | ||
| 153 | + (b"[a]\n\tk = val\\\\\n next\n", "val\\\\"), | ||
| 154 | + (b"[a]\n\tk = end\\\n", "end"), | ||
| 155 | + (b"[alias]\n\tco = checkout \\\n\t\t-v\n", "checkout \t\t-v"), | ||
| 156 | + ] | ||
| 157 | + for content, expected in cases: | ||
| 158 | + config_file = io.BytesIO(content) | ||
| 159 | + config_file.name = "backslash_continuation.config" | ||
| 160 | + config = GitConfigParser(config_file) | ||
| 161 | + config.read() | ||
| 162 | + section = "alias" if b"[alias]" in content else "a" | ||
| 163 | + key = "co" if section == "alias" else "k" | ||
| 164 | + self.assertEqual(config.get_value(section, key), expected) | ||
| 165 | + | ||
| 146 | 166 | def test_config_value_with_trailing_new_line(self): | |
| 147 | 167 | config_content = b'[section-header]\nkey:"value\n"' | |
| 148 | 168 | config_file = io.BytesIO(config_content) | |
| Back | FazBrowse Home | New Git URL |
0 commit comments