Skip to content
Open
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
## [Unreleased]

### 修复
- 本地下载遇到大量同名文件时继续递增编号,避免超过 999 个编号后重复使用进程号文件名并覆盖之前的下载
- 云端协同对端专家的模型、连接器、知识库和对话模式会显示在本端输入框上方
- 侧栏 Beta 标记跟随主题色
- 管理员用量统计里,其他用户创建的专家显示名称而不是 id
Expand Down
12 changes: 5 additions & 7 deletions src/octop/infra/utils/user_downloads.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,12 @@ def unique_download_path(filename: str, *, home: Path | None = None) -> Path:
dest_dir.mkdir(parents=True, exist_ok=True)
safe = sanitize_download_filename(filename)
path = dest_dir / safe
if not path.exists():
return path
stem, suffix = path.stem, path.suffix
for index in range(1, 1000):
candidate = dest_dir / f"{stem} ({index}){suffix}"
if not candidate.exists():
return candidate
return dest_dir / f"{stem}-{os.getpid()}{suffix}"
index = 1
while path.exists():
path = dest_dir / f"{stem} ({index}){suffix}"
index += 1
return path


def save_user_download(
Expand Down
16 changes: 16 additions & 0 deletions tests/unit/utils/test_user_downloads.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,22 @@ def test_save_user_download_writes_bytes(tmp_path: Path) -> None:
assert path.parent == downloads


def test_save_user_download_preserves_files_after_many_collisions(tmp_path: Path) -> None:
downloads = tmp_path / "Downloads"
downloads.mkdir()
(downloads / "note.txt").write_bytes(b"original")
for index in range(1, 1000):
(downloads / f"note ({index}).txt").touch()

first = save_user_download("note.txt", b"first", home=tmp_path)
second = save_user_download("note.txt", b"second", home=tmp_path)

assert first != second
assert first.read_bytes() == b"first"
assert second.read_bytes() == b"second"
assert (downloads / "note.txt").read_bytes() == b"original"


def test_local_dashboard_request_requires_loopback_host_and_peer() -> None:
assert is_local_dashboard_request(_Req("127.0.0.1:8088", "127.0.0.1"))
assert is_local_dashboard_request(_Req("localhost:8088", "127.0.0.1"))
Expand Down
Loading