Skip to content

Commit 56bf06b

Browse files
author
Lukas Geiger
committed
Use portable Git status paths and Python 3.10 metadata parsing
Signed-off-by: Lukas Geiger <lukas@um-bruch.org>
1 parent 9724481 commit 56bf06b

4 files changed

Lines changed: 37 additions & 4 deletions

File tree

‎.github/workflows/ci.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ jobs:
8080
- name: Install Project Dependencies
8181
run: |
8282
python -m pip install --upgrade pip
83-
python -m pip install -r requirements.txt pytest Pillow
83+
python -m pip install -r requirements.txt pytest Pillow tomli
8484
8585
- name: Run Pytest Test Suite
8686
run: pytest -v

‎features/project_view.py‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
from __future__ import annotations
1212

13-
from pathlib import Path
13+
from pathlib import Path, PurePosixPath, PureWindowsPath
1414
from typing import Optional, Dict, TYPE_CHECKING
1515
from PySide6.QtWidgets import (
1616
QWidget, QVBoxLayout, QHBoxLayout, QTreeView, QFileSystemModel,
@@ -52,10 +52,13 @@ def status_for_path(
5252
Returns:
5353
GitFileStatus oder None.
5454
"""
55+
path_type = PureWindowsPath if PureWindowsPath(repo_root).drive else PurePosixPath
5556
try:
56-
rel = Path(abs_path).relative_to(repo_root)
57+
rel = path_type(abs_path).relative_to(path_type(repo_root))
5758
except ValueError:
5859
return None
60+
if ".." in rel.parts:
61+
return None
5962
return status_dict.get(rel.as_posix())
6063

6164

‎tests/test_git_project_view_status.py‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,32 @@ def test_windows_nested_backslash(self):
9696
self.assertIsNotNone(result)
9797
self.assertTrue(result.is_modified)
9898

99+
def test_windows_forward_slashes_and_case(self):
100+
status = _file_status("src/main.py", is_modified=True)
101+
result = status_for_path("c:/PROJECT/src/main.py", r"C:\project", {"src/main.py": status})
102+
self.assertIs(result, status)
103+
104+
def test_windows_unc_share(self):
105+
status = _file_status("src/main.py", is_modified=True)
106+
result = status_for_path(
107+
r"\\server\share\repo\src\main.py", r"\\server\share\repo", {"src/main.py": status}
108+
)
109+
self.assertIs(result, status)
110+
111+
def test_windows_other_drive_is_outside(self):
112+
self.assertIsNone(status_for_path(r"D:\repo\main.py", r"C:\repo", {"main.py": _file_status("main.py")}))
113+
114+
def test_sibling_prefix_is_outside(self):
115+
self.assertIsNone(status_for_path("/repo-other/main.py", "/repo", {"main.py": _file_status("main.py")}))
116+
117+
def test_parent_traversal_is_outside(self):
118+
self.assertIsNone(status_for_path("/repo/../main.py", "/repo", {"../main.py": _file_status("../main.py")}))
119+
120+
def test_posix_literal_backslash_filename(self):
121+
name = r"file\name.py"
122+
status = _file_status(name, is_modified=True)
123+
self.assertIs(status_for_path("/repo/" + name, "/repo", {name: status}), status)
124+
99125

100126
if __name__ == "__main__":
101127
unittest.main()

‎tests/test_metadata.py‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,13 @@
22

33
import json
44
import re
5-
import tomllib
65
from pathlib import Path
76

7+
try:
8+
import tomllib
9+
except ModuleNotFoundError: # Python 3.10
10+
import tomli as tomllib
11+
812
import pytest
913

1014
PROJECT_ROOT = Path(__file__).resolve().parents[1]

0 commit comments

Comments
 (0)