Skip to content

fix: 处理历史记录目录创建时旧文件冲突#236

Merged
WSXYT merged 3 commits into
masterfrom
seer/fix/history-dir-file-conflict
May 15, 2026
Merged

fix: 处理历史记录目录创建时旧文件冲突#236
WSXYT merged 3 commits into
masterfrom
seer/fix/history-dir-file-conflict

Conversation

@seer-by-sentry
Copy link
Copy Markdown
Contributor

修复了在创建历史记录目录(例如 roll_call_history)时,如果该路径下存在旧版文件而非目录,会导致 FileExistsError 的问题。pathlib.Path.mkdir(exist_ok=True) 仅在目标路径已存在且为目录时才不会报错,但无法处理同名文件的情况。

问题原因:
旧版本应用将历史记录存储为单个文件,而新版本将其改为按班级存储在同名目录下。用户从旧版本升级后,旧文件会阻碍新版本创建目录。

解决方案:
app/common/history/file_utils.pyget_history_file_path 函数中,在调用 mkdir 之前,增加了一个检查。如果目标路径已存在但不是目录(即为旧版文件),则先删除该文件,然后日志记录此操作,再尝试创建目录。这确保了平滑升级,避免了 FileExistsError

Fixes SECRANDOM-9S

@WSXYT WSXYT marked this pull request as ready for review May 15, 2026 13:15
Copilot AI review requested due to automatic review settings May 15, 2026 13:15
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

该 PR 修复了创建历史记录目录(如 data/history/roll_call_history)时,若同名路径存在旧版“文件”而非“目录”导致 mkdir(exist_ok=True) 仍抛出 FileExistsError 的升级兼容问题。

Changes:

  • get_history_file_path 中检测到历史记录路径存在且非目录时,先记录日志并删除旧文件。
  • 随后再执行 mkdir(parents=True, exist_ok=True),确保目录创建成功。

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread app/common/history/file_utils.py Outdated
history_dir = get_path(f"data/history/{history_type}_history")
if history_dir.exists() and not history_dir.is_dir():
logger.warning(f"检测到旧版历史记录文件,正在删除以创建目录: {history_dir}")
history_dir.unlink()
Comment thread app/common/history/file_utils.py Outdated
Comment on lines +72 to +74
if history_dir.exists() and not history_dir.is_dir():
logger.warning(f"检测到旧版历史记录文件,正在删除以创建目录: {history_dir}")
history_dir.unlink()
Comment thread app/common/history/file_utils.py Outdated
Comment on lines +72 to +74
if history_dir.exists() and not history_dir.is_dir():
logger.warning(f"检测到旧版历史记录文件,正在删除以创建目录: {history_dir}")
history_dir.unlink()

This comment was marked as outdated.

@WSXYT
Copy link
Copy Markdown
Collaborator

WSXYT commented May 15, 2026

@copilot Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.

Location: app/common/history/file_utils.py#L72-L74

Potential issue: The history_dir.unlink() call, intended to remove an old history file
during an upgrade, is not protected by a try-except block. If deleting the file fails
(e.g., due to a PermissionError on a locked or read-only file), the resulting
OSError will propagate uncaught. Functions like load_history_data() and
save_history_data() call get_history_file_path() before their own exception
handling, so the error will travel up to UI-level functions like calculate_weight()
and get_draw_sessions_history(), causing an application crash. This undermines the
goal of a smooth upgrade process.

Copy link
Copy Markdown
Contributor

Copilot AI commented May 15, 2026

@copilot Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.
...

已确认这是有效问题,并已修复(提交 3ff5676)。我在 get_history_file_path() 中为旧文件删除和目录创建都增加了异常兜底与错误日志,避免 unlink()/mkdir() 的未处理异常直接向上抛出导致 UI 层崩溃。

Copilot finished work on behalf of WSXYT May 15, 2026 13:26
Copilot AI requested a review from WSXYT May 15, 2026 13:26
Comment on lines +76 to +85
except PermissionError as e:
logger.error(f"删除旧版历史记录文件失败(权限不足): {history_dir}, 错误: {e}")
except OSError as e:
logger.error(f"删除旧版历史记录文件失败: {history_dir}, 错误: {e}")
try:
history_dir.mkdir(parents=True, exist_ok=True)
except FileExistsError:
logger.error(f"创建历史记录目录失败,目标仍为文件: {history_dir}")
except OSError as e:
logger.error(f"创建历史记录目录失败: {history_dir}, 错误: {e}")

This comment was marked as outdated.

@WSXYT
Copy link
Copy Markdown
Collaborator

WSXYT commented May 15, 2026

@copilot Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.

Location: app/common/history/file_utils.py#L76-L85

Potential issue: When unlink() fails on a history file, for instance due to a
PermissionError from a file lock, the error is caught but execution continues. The
subsequent mkdir() call also fails, and this error is also caught. The function then
returns a path that incorrectly treats the file as a directory. A calling function,
save_history_data, attempts to write to this invalid path, triggering a
NotADirectoryError. This error is caught by a broad except Exception block, which
returns False and silently discards the history data. This results in permanent data
loss without any notification to the user until the file is manually removed.

Copy link
Copy Markdown
Contributor

Copilot AI commented May 15, 2026

@copilot Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.
...

已确认是有效问题,并在提交 8936a6f 中修复。现在 get_history_file_path() 增加 strict 模式,load_history_data() / save_history_data() 在严格模式下获取路径:若历史目录不可用会直接记录错误并返回 {}/False,不再继续使用无效路径执行读写。

Copilot finished work on behalf of WSXYT May 15, 2026 13:47
@WSXYT WSXYT merged commit ea52742 into master May 15, 2026
1 check passed
@WSXYT WSXYT deleted the seer/fix/history-dir-file-conflict branch May 15, 2026 13:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants