From 5d19ab0d8e9b734e3452c6e1210a7f2501709397 Mon Sep 17 00:00:00 2001 From: Trim21 Date: Mon, 19 Aug 2024 00:13:21 +0800 Subject: [PATCH] fix: keep lock file eol (#9468) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Randy Döring <30527984+radoering@users.noreply.github.com> --- src/poetry/packages/locker.py | 29 +++++++++++++++++++++++++++-- tests/packages/test_locker.py | 17 +++++++++++++++++ 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/src/poetry/packages/locker.py b/src/poetry/packages/locker.py index 420cd392d10..80177f16dd3 100644 --- a/src/poetry/packages/locker.py +++ b/src/poetry/packages/locker.py @@ -290,8 +290,33 @@ def _should_write(self, lock: TOMLDocument) -> bool: return do_write def _write_lock_data(self, data: TOMLDocument) -> None: - lockfile = TOMLFile(self.lock) - lockfile.write(data) + if self.lock.exists(): + # The following code is roughly equivalent to + # • lockfile = TOMLFile(self.lock) + # • lockfile.read() + # • lockfile.write(data) + # However, lockfile.read() takes more than half a second even + # for a modestly sized project like Poetry itself and the only reason + # for reading the lockfile is to determine the line endings. Thus, + # we do that part for ourselves here, which only takes about 10 ms. + + # get original line endings + with open(self.lock, encoding="utf-8", newline="") as f: + line = f.readline() + linesep = "\r\n" if line.endswith("\r\n") else "\n" + + # enforce original line endings + content = data.as_string() + if linesep == "\n": + content = content.replace("\r\n", "\n") + elif linesep == "\r\n": + content = re.sub(r"(? None: + sep = "\n" if os.linesep == "\r\n" else "\r\n" + + with open(locker.lock, "wb") as f: + f.write((sep * 10).encode()) + + assert locker.set_lock_data(root, [Package("test", version="0.0.1")]) + + with locker.lock.open(encoding="utf-8", newline="") as f: + line, *_ = f.read().splitlines(keepends=True) + + if sep == "\r\n": + assert line.endswith("\r\n") + else: + assert not line.endswith("\r\n")