Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion scripts/msys2-install-deps
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/bin/bash

pacman -S --needed --noconfirm git mingw-w64-ucrt-x86_64-{toolchain,pkgconf,lz4,openssl,rclone,python-msgpack,python-platformdirs,python,cython,python-setuptools,python-wheel,python-build,python-pkgconfig,python-packaging,python-pip,python-paramiko,rust,python-maturin}
pacman -S --needed --noconfirm git mingw-w64-ucrt-x86_64-{toolchain,pkgconf,lz4,openssl,rclone,python-msgpack,python-platformdirs,python,cython,python-setuptools,python-setuptools-scm,python-wheel,python-build,python-pkgconfig,python-packaging,python-pip,python-paramiko,rust,python-maturin}

if [ "$1" = "development" ]; then
pacman -S --needed --noconfirm mingw-w64-ucrt-x86_64-python-{pytest,pytest-benchmark,pytest-cov,pytest-xdist}
Expand Down
6 changes: 5 additions & 1 deletion src/borg/helpers/time.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,11 @@ def parse_local_timestamp(timestamp, tzinfo=None):
"""
dt = datetime.fromisoformat(timestamp)
if dt.tzinfo is None:
dt = dt.astimezone(tz=tzinfo)
try:
dt = dt.astimezone(tz=tzinfo)
except OSError as e:
# e.g. win32 local time conversion fails for timestamps close to (or before) the epoch.
raise ValueError(f"cannot convert {timestamp} to local time: {e}") from None
return dt


Expand Down
10 changes: 6 additions & 4 deletions src/borg/testsuite/archiver/completion_cmd_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -615,12 +615,14 @@ def test_completion_repo_is_a_directory(archivers, request, shell):
def test_bash_repo_url_no_directories(archivers, request, tmp_path):
archiver = request.getfixturevalue(archivers)
(tmp_path / "somerepo").mkdir()
for url in REPO_URLS:
# a local directory looking like the start of the URL, so that plain directory completion finds it
(tmp_path / url.split("/")[0]).mkdir(exist_ok=True)
# local directories looking like the start of the URLs, so that plain directory completion finds them.
# created by bash: on win32, MSYS2/Cygwin map the colon to a valid file name character.
dirs = " ".join(sorted({url.split("/")[0] for url in REPO_URLS}))
script = cmd(archiver, "completion", "bash")
for url in REPO_URLS:
result = _run_bash_completion_fn(script, f'cd "{tmp_path}"\n_borg_complete_repo_dirs "{url}"\n')
result = _run_bash_completion_fn(
script, f'cd "{tmp_path}"\nmkdir -p {dirs}\n_borg_complete_repo_dirs "{url}"\n'
)
assert result.returncode == 0, f"stderr: {result.stderr}"
assert result.stdout == "", f"directories offered for {url}: {result.stdout}"
result = _run_bash_completion_fn(script, f'cd "{tmp_path}"\n_borg_complete_repo_dirs some\n')
Expand Down
5 changes: 3 additions & 2 deletions src/borg/testsuite/archiver/recreate_cmd_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -262,9 +262,10 @@ def test_recreate_with_given_timestamp(archivers, request):
# this shall recreate the archive with a different nominal timestamp.
# --timestamp is the only change requested, so this also checks that a timestamp
# change alone is enough to make recreate do the work instead of skipping the archive.
cmd(archiver, "recreate", "-a", "test0", "--timestamp", "1970-01-02T00:00:00")
# not 1970-01-02: win32 cannot convert that to local time east of UTC.
cmd(archiver, "recreate", "-a", "test0", "--timestamp", "1970-01-03T00:00:00")
info = cmd(archiver, "info", "-a", "test0").splitlines()
dtime = datetime(1970, 1, 2, 0, 0, 0).astimezone() # local time in local timezone
dtime = datetime(1970, 1, 3, 0, 0, 0).astimezone() # local time in local timezone
s_time = dtime.strftime("%Y-%m-%d %H:%M:.. %z").replace("+", r"\+")
assert any([re.search(r"Time \(nominal\).+ %s" % s_time, item) for item in info])
# start/end time are just from the recreate operation
Expand Down
14 changes: 13 additions & 1 deletion src/borg/testsuite/helpers/time_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@

from ...helpers.time import safe_ns, safe_s, safe_timestamp, SUPPORT_32BIT_PLATFORMS, calculate_relative_offset
from ...helpers.time import format_time, format_time_ns, OutputTimestamp
from ...helpers.time import ns_to_pax_time, pax_time_to_ns
from ...helpers.time import ns_to_pax_time, pax_time_to_ns, parse_local_timestamp
from ...helpers import time as time_module


def utcfromtimestamp(timestamp):
Expand Down Expand Up @@ -107,3 +108,14 @@ def test_ns_to_pax_time(ns, expected):
)
def test_pax_time_to_ns(value, expected):
assert pax_time_to_ns(value) == expected


def test_parse_local_timestamp_oserror(monkeypatch):
# win32 fails to convert 1970-01-02T00:00:00 to local time east of UTC.
class FailingDatetime(datetime):
def astimezone(self, tz=None):
raise OSError(22, "Invalid argument")

monkeypatch.setattr(time_module, "datetime", FailingDatetime)
with pytest.raises(ValueError, match="cannot convert 1970-01-02T00:00:00 to local time"):
parse_local_timestamp("1970-01-02T00:00:00")
Loading