Skip to content

Commit f89b899

Browse files
author
Lukas Geiger
committed
chore: add CloudLockFixer test workflow
1 parent 9d668ab commit f89b899

9 files changed

Lines changed: 107 additions & 22 deletions

File tree

.github/workflows/tests.yml

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
name: CloudLockFixer tests
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
workflow_dispatch:
9+
10+
permissions:
11+
contents: read
12+
13+
jobs:
14+
tests:
15+
runs-on: windows-latest
16+
strategy:
17+
fail-fast: false
18+
matrix:
19+
python-version: ["3.10", "3.11", "3.12"]
20+
21+
steps:
22+
- name: Check out repository
23+
uses: actions/checkout@v6
24+
25+
- name: Set up Python
26+
uses: actions/setup-python@v6
27+
with:
28+
python-version: ${{ matrix.python-version }}
29+
cache: pip
30+
31+
- name: Install dependencies
32+
run: |
33+
python -m pip install --upgrade pip
34+
python -m pip install -r requirements.txt pytest
35+
36+
- name: Run tests
37+
env:
38+
PYTHONPATH: src
39+
PYTHONIOENCODING: utf-8
40+
run: python -m pytest -q

CHANGELOG.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,14 @@ Format basiert auf [Keep a Changelog](https://keepachangelog.com/de/1.1.0/).
66
## [Unreleased]
77

88
### Hinzugefügt / Added
9-
-
9+
- GitHub Actions workflow for Windows smoke tests on Python 3.10, 3.11 and 3.12.
10+
- `llms.txt` with canonical machine-readable project context.
11+
12+
### Geändert / Changed
13+
- Roadmap and README test counts now reflect the current i18n and multicloud implementation.
14+
15+
### Behoben / Fixed
16+
- Locale detection no longer uses Python's deprecated `locale.getdefaultlocale()`.
1017

1118
## [1.0.0] - 2026-05-30
1219

README.de.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ automatisch zu `#>` auskommentiert.
8787
- **P3 (fertig):** Präventiv-Wächter (Änderungsrate *konfigurierter* Ordner
8888
beobachten → Sync-Client automatisch pausieren/fortsetzen; bounded + stat-only,
8989
hydratisiert keine Online-only-Placeholder; opt-in).
90-
- **Tests:** `pytest`, **17 grün** (Core + P2/P3 + Regressionen).
90+
- **Tests:** `pytest`, **49 grün** (Core + P2/P3 + i18n + Multicloud-Regressionen).
9191
- **Im Lifetest gehärtet (2026-05-29):** `is_running()/pause()` robust gegen
9292
nicht-UTF-8-`tasklist`-Ausgabe; `delete` entfernt read-only-Attribute statt an
9393
WinError 5 zu scheitern. Erster echter Einsatz: ein Ordner-Rename, den manuelle

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ automatically commented out with `#>`.
8888
- **P3 (done):** Preventive watcher (observes the change rate of *configured*
8989
folders → pauses/resumes the sync client; bounded, stat-only, does not
9090
hydrate online-only placeholders; opt-in).
91-
- **Tests:** `pytest`, 17 passing (core + P2/P3 + regressions).
91+
- **Tests:** `pytest`, 49 passing (core + P2/P3 + i18n + multicloud regressions).
9292
- **Open/future:** more provider adapters (Dropbox / Google Drive / iCloud);
9393
optional suppression of sync-client relaunch during long operations.
9494

ROADMAP.md

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,22 @@
1212
- Autostart via Registry
1313
- PyInstaller-Build
1414

15-
## v1.1.0 — i18n + Bugfixes (aktuell)
15+
## v1.1.0 — i18n + Bugfixes (erledigt)
1616

1717
- [x] Bugfixes: Verify-Cleanup, Watcher-Resume, Queue-Race-Condition
18-
- [ ] Internationalisierung: Deutsch + Englisch
19-
- [ ] Sprachauswahl im Tray-Menü (de/en/auto)
20-
- [ ] Systemsprache-Erkennung via locale
21-
22-
## v1.2.0 — Windows Multicloud
23-
24-
- [ ] Google Drive Provider (GoogleDriveFS, virtueller Mount)
25-
- [ ] Dropbox Provider
26-
- [ ] iCloud Provider
27-
- [ ] Auto-Discovery installierter Cloud-Sync-Clients
28-
- [ ] Dynamische Provider-Anzeige im Tray
29-
- [ ] Virtual-mount Guard (kein Pause für gemountete Laufwerke)
30-
- [ ] Multi-Provider Präventiv-Wächter
18+
- [x] Internationalisierung: Deutsch + Englisch
19+
- [x] Sprachauswahl im Tray-Menü (de/en/auto)
20+
- [x] Systemsprache-Erkennung via locale
21+
22+
## v1.2.0 — Windows Multicloud (erledigt)
23+
24+
- [x] Google Drive Provider (GoogleDriveFS, virtueller Mount)
25+
- [x] Dropbox Provider
26+
- [x] iCloud Provider
27+
- [x] Auto-Discovery installierter Cloud-Sync-Clients
28+
- [x] Dynamische Provider-Anzeige im Tray
29+
- [x] Virtual-mount Guard (kein Pause für gemountete Laufwerke)
30+
- [x] Multi-Provider Präventiv-Wächter
3131

3232
## v2.0.0 — Cross-Platform
3333

TODO.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,17 @@
3030
- [x] ROADMAP.md (langfristige Planung)
3131
- [x] PORTIERUNGSPLAN.md (Linux/macOS)
3232

33+
## Erkenntnisse aus MCP-Integration (2026-05-31)
34+
35+
Beim Port der copy+delete-Logik in den ellmos-filecommander-mcp-Server (TypeScript) wurden folgende Punkte entdeckt:
36+
37+
- [ ] **EBUSY als Fehlercode aufnehmen:** Windows gibt bei File-Locks durch andere Prozesse (inkl. Cloud-Sync) `EBUSY` zurück, nicht nur EPERM/EACCES. CLFs `ops.py` sollte EBUSY in die Retry-Trigger-Codes aufnehmen (aktuell nur EXDEV + Access Denied).
38+
- [ ] **Delete-nach-Copy bei aktivem Lock:** Wenn die Kopie erfolgreich ist aber das Löschen des Originals mit EBUSY scheitert (Datei noch vom Sync-Client gehalten), ist das ein Teilerfolg. CLF handhabt das bereits via Queue-Retry — aber der Status sollte explizit als "kopiert, Löschung ausstehend" im queue.txt sichtbar sein.
39+
- [ ] **Verzeichnis-Rename mit gelockter Innendatei:** Bei `fs.rename()` auf ein Verzeichnis, dessen Inhalt einen gelockten File enthält, gibt Windows EPERM (nicht EBUSY). Die copy+delete-Strategie funktioniert hier korrekt (rekursives Kopieren + rekursives Löschen), aber das Löschen des Quellverzeichnisses scheitert wenn eine Innendatei noch gelockt ist. CLFs `ops.py` sollte diesen Fall explizit behandeln.
40+
3341
## Nächste Schritte (aus ROADMAP.md)
3442

43+
- [ ] Test-CI beobachten und bei Bedarf Windows-spezifische Runtime-Abhängigkeiten ergänzen
3544
- [ ] Cross-Platform: Linux-Support (siehe PORTIERUNGSPLAN.md)
3645
- [ ] Cross-Platform: macOS-Support (siehe PORTIERUNGSPLAN.md)
3746
- [ ] Weitere Provider: Box, Nextcloud, pCloud, Synology Drive

llms.txt

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# CloudLockFixer
2+
3+
CloudLockFixer is a Windows tray and CLI tool for delayed rename, move and delete
4+
operations in cloud-sync folders. It is designed for OneDrive, Dropbox, Google
5+
Drive and iCloud folders where Windows Cloud Files locks can make normal file
6+
operations fail.
7+
8+
Canonical repository: https://github.com/file-bricks/CloudLockFixer
9+
10+
Primary interfaces:
11+
- Tray app: `START.bat` or `PYTHONPATH=src python -m cloudlockfixer`
12+
- CLI: `PYTHONPATH=src python -m cloudlockfixer.cli`
13+
- Queue file: `%LOCALAPPDATA%\CloudLockFixer\queue.txt`
14+
- Tests: `PYTHONPATH=src python -m pytest -q`
15+
16+
Safety boundaries:
17+
- The tool performs destructive filesystem operations only after queued user or
18+
script instructions.
19+
- Move and rename operations use copy, verify and delete fallback logic so that
20+
deletion happens only after a verified copy.
21+
- Runtime queues, logs and local credentials are not part of the repository.
22+
23+
Key files:
24+
- `README.md`: English user overview and quickstart
25+
- `README.de.md`: German user overview and quickstart
26+
- `docs/DESIGN.md`: design and safety model
27+
- `src/cloudlockfixer/ops.py`: copy/delete and retry-safe filesystem operations
28+
- `src/cloudlockfixer/providers.py`: cloud provider detection and pause policy
29+
- `tests/`: regression tests for core, i18n, provider and tray-adjacent behavior

src/cloudlockfixer/i18n.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@
290290
def detect_language() -> Language:
291291
"""Sprache aus System-Locale ableiten (Fallback: Deutsch)."""
292292
try:
293-
lang, _ = locale.getdefaultlocale()
293+
lang, _ = locale.getlocale()
294294
if lang and lang.lower().startswith("en"):
295295
return "en"
296296
except (ValueError, TypeError):

tests/test_i18n.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,17 +59,17 @@ def test_format_missing_param_returns_template():
5959

6060

6161
def test_detect_language_german(monkeypatch):
62-
monkeypatch.setattr("locale.getdefaultlocale", lambda: ("de_DE", "UTF-8"))
62+
monkeypatch.setattr("locale.getlocale", lambda: ("de_DE", "UTF-8"))
6363
assert detect_language() == "de"
6464

6565

6666
def test_detect_language_english(monkeypatch):
67-
monkeypatch.setattr("locale.getdefaultlocale", lambda: ("en_US", "UTF-8"))
67+
monkeypatch.setattr("locale.getlocale", lambda: ("en_US", "UTF-8"))
6868
assert detect_language() == "en"
6969

7070

7171
def test_detect_language_fallback(monkeypatch):
72-
monkeypatch.setattr("locale.getdefaultlocale", lambda: (None, None))
72+
monkeypatch.setattr("locale.getlocale", lambda: (None, None))
7373
assert detect_language() == "de"
7474

7575

@@ -80,7 +80,7 @@ def test_available_keys_sorted():
8080

8181

8282
def test_resolve_language_auto(monkeypatch):
83-
monkeypatch.setattr("locale.getdefaultlocale", lambda: ("en_US", "UTF-8"))
83+
monkeypatch.setattr("locale.getlocale", lambda: ("en_US", "UTF-8"))
8484
assert resolve_language({"language": "auto"}) == "en"
8585

8686

0 commit comments

Comments
 (0)