diff --git a/src/borg/archive.py b/src/borg/archive.py index 1e01c3b5e..e2e7cf000 100644 --- a/src/borg/archive.py +++ b/src/borg/archive.py @@ -149,6 +149,7 @@ Bytes sent to remote: {stats.tx_bytes} def show_progress(self, item=None, final=False, stream=None, dt=None): now = time.monotonic() if dt is None or now - self.last_progress > dt: + stream = stream or sys.stderr self.last_progress = now if self.output_json: if not final: @@ -160,6 +161,14 @@ Bytes sent to remote: {stats.tx_bytes} data.update({"time": time.time(), "type": "archive_progress", "finished": final}) msg = json.dumps(data) end = "\n" + elif not stream.isatty(): + # Non-TTY output: use normal linefeeds and do not truncate the path. + if not final: + msg = "{0.osize_fmt} O {0.usize_fmt} U {0.nfiles} N ".format(self) + msg += remove_surrogates(item.path) if item else "" + else: + msg = "" + end = "\n" else: columns, lines = get_terminal_size() if not final: @@ -174,7 +183,7 @@ Bytes sent to remote: {stats.tx_bytes} else: msg = " " * columns end = "\r" - print(msg, end=end, file=stream or sys.stderr, flush=True) + print(msg, end=end, file=stream, flush=True) def is_special(mode): diff --git a/src/borg/testsuite/archive_test.py b/src/borg/testsuite/archive_test.py index a3028d792..97a2ef71c 100644 --- a/src/borg/testsuite/archive_test.py +++ b/src/borg/testsuite/archive_test.py @@ -33,26 +33,51 @@ def test_stats_basic(stats): assert stats.usize == 20 -@pytest.mark.parametrize( - "item_path, update_size, expected_output", - [ - ("", 0, "20 B O 20 B U 1 N "), # test unchanged 'stats' fixture - ("foo", 10**3, "1.02 kB O 20 B U 1 N foo"), # test updated original size and set item path - # test long item path which exceeds 80 characters - ("foo" * 40, 10**3, "1.02 kB O 20 B U 1 N foofoofoofoofoofoofoofoofo...foofoofoofoofoofoofoofoofoofoo"), - ], -) -def test_stats_progress(item_path, update_size, expected_output, stats, monkeypatch, columns=80): - monkeypatch.setenv("COLUMNS", str(columns)) - out = StringIO() - item = Item(path=item_path) if item_path else None - s = expected_output +def test_stats_progress_tty(stats, monkeypatch, columns=80): + class TTYStringIO(StringIO): + def isatty(self): + return True - stats.update(update_size, unique=False) - stats.show_progress(item=item, stream=out) + monkeypatch.setenv("COLUMNS", str(columns)) + out = TTYStringIO() + stats.show_progress(stream=out) + s = "20 B O 20 B U 1 N " buf = " " * (columns - len(s)) assert out.getvalue() == s + buf + "\r" + out = TTYStringIO() + stats.update(10**3, unique=False) + stats.show_progress(item=Item(path="foo"), final=False, stream=out) + s = "1.02 kB O 20 B U 1 N foo" + buf = " " * (columns - len(s)) + assert out.getvalue() == s + buf + "\r" + + out = TTYStringIO() + stats.show_progress(item=Item(path="foo" * 40), final=False, stream=out) + s = "1.02 kB O 20 B U 1 N foofoofoofoofoofoofoofoofo...foofoofoofoofoofoofoofoofoofoo" + buf = " " * (columns - len(s)) + assert out.getvalue() == s + buf + "\r" + + +def test_stats_progress_file(stats, monkeypatch): + out = StringIO() + stats.show_progress(stream=out) + s = "20 B O 20 B U 1 N " + assert out.getvalue() == s + "\n" + + out = StringIO() + stats.update(10**3, unique=False) + path = "foo" + stats.show_progress(item=Item(path=path), final=False, stream=out) + s = f"1.02 kB O 20 B U 1 N {path}" + assert out.getvalue() == s + "\n" + + out = StringIO() + path = "foo" * 40 + stats.show_progress(item=Item(path=path), final=False, stream=out) + s = f"1.02 kB O 20 B U 1 N {path}" + assert out.getvalue() == s + "\n" + def test_stats_format(stats): assert ( diff --git a/src/borg/testsuite/archiver/create_cmd_test.py b/src/borg/testsuite/archiver/create_cmd_test.py index c0543ad78..94deb4211 100644 --- a/src/borg/testsuite/archiver/create_cmd_test.py +++ b/src/borg/testsuite/archiver/create_cmd_test.py @@ -634,7 +634,7 @@ def test_progress_on(archivers, request): create_regular_file(archiver.input_path, "file1", size=1024 * 80) cmd(archiver, "repo-create", RK_ENCRYPTION) output = cmd(archiver, "create", "test4", "input", "--progress") - assert "\r" in output + assert "0 B O 0 B U 0 N" in output def test_progress_off(archivers, request): @@ -642,7 +642,7 @@ def test_progress_off(archivers, request): create_regular_file(archiver.input_path, "file1", size=1024 * 80) cmd(archiver, "repo-create", RK_ENCRYPTION) output = cmd(archiver, "create", "test5", "input") - assert "\r" not in output + assert "0 B O 0 B U 0 N" not in output def test_file_status(archivers, request):