UploadToFolderReplacing теперь матчит конвертируемые расширения (.xls↔.xlsx) и при
совпадении вызывает UpdateFile. Но OnlyOffice не конвертирует тело при UpdateFile,
поэтому сырой .xls (OLE2) ложится под прежним именем .xlsx — расширение не
соответствует содержимому, файл не открывается.
после UpdateFile id 3799/3800 имели размер 192000/7168 B и magic d0cf 11e0 (OLE2 .xls)
при title .xlsx;
после rm + свежего upload сервер сконвертировал в настоящий .xlsx (50743 B, PK).
Что сделать
В UploadToFolderReplacing применять UpdateFileтолько когда расширения совпадают
(stored ext == local ext).
Если матч по stem сработал через эквивалентность (legacy .xls/.doc/.ppt ↔ OOXML),
делать delete (все дубли по stem) → upload — пусть сервер конвертирует в OOXML.
AssertNoFileConflict (--no-replace) оставить conversion-aware, но без UpdateFile-пути.
Тест: повторный upload .xls при существующем .xlsx → файл перезалит (несколько id меняется),
содержимое — валидный OOXML (не OLE2 под .xlsx).
exact-ext (pdf→pdf, xlsx→xlsx) по-прежнему через UpdateFile (регрессия покрыта);
offline-тесты; go test -race ./..., go vet ./..., gofmt -l . — чисто.
Оценка: S
## Проблема (регрессия от #82)
`UploadToFolderReplacing` теперь матчит конвертируемые расширения (`.xls`↔`.xlsx`) и при
совпадении вызывает `UpdateFile`. Но OnlyOffice **не конвертирует** тело при `UpdateFile`,
поэтому сырой `.xls` (OLE2) ложится **под прежним именем `.xlsx`** — расширение не
соответствует содержимому, файл не открывается.
Живое доказательство (2026-09-27, `Banks/Caixa/extractos/`):
- после `UpdateFile` id 3799/3800 имели размер 192000/7168 B и magic `d0cf 11e0` (OLE2 `.xls`)
при title `.xlsx`;
- после `rm` + свежего upload сервер сконвертировал в настоящий `.xlsx` (50743 B, `PK`).
## Что сделать
- В `UploadToFolderReplacing` применять `UpdateFile` **только когда расширения совпадают**
(`stored ext == local ext`).
- Если матч по stem сработал через **эквивалентность** (legacy `.xls/.doc/.ppt` ↔ OOXML),
делать **delete (все дубли по stem) → upload** — пусть сервер конвертирует в OOXML.
- `AssertNoFileConflict` (--no-replace) оставить conversion-aware, но без UpdateFile-пути.
- Тест: повторный upload `.xls` при существующем `.xlsx` → файл перезалит (несколько id меняется),
содержимое — валидный OOXML (не OLE2 под `.xlsx`).
## Acceptance
- [ ] повторный `oo dav upload <folder> f.xls --replace` → один файл, содержимое валидный `.xlsx`;
- [ ] exact-ext (pdf→pdf, xlsx→xlsx) по-прежнему через UpdateFile (регрессия покрыта);
- [ ] offline-тесты; `go test -race ./...`, `go vet ./...`, `gofmt -l .` — чисто.
Оценка: S
Начинаю. План: TDD — сначала тесты на planUploadReplacement (exact-ext → UpdateFile; legacy↔OOXML → delete+upload), затем правка files_stem.go. AssertNoFileConflict уже conversion-aware и UpdateFile не вызывает — не трогаем. Live — по наличию env.
Начинаю. План: TDD — сначала тесты на planUploadReplacement (exact-ext → UpdateFile; legacy↔OOXML → delete+upload), затем правка files_stem.go. AssertNoFileConflict уже conversion-aware и UpdateFile не вызывает — не трогаем. Live — по наличию env.
Готово — PR #85 (#85), ветка fix/dav-updatefile-convert#84, коммит aad6315.
Причина
UploadToFolderReplacing матчил legacy↔OOXML (.xls ↔ сохранённый .xlsx) через EquivalentUploadExt и вызывал UpdateFile. OnlyOffice при update тело не конвертирует → сырой .xls (OLE2) оставался под именем .xlsx.
Правило update vs delete+upload
planUploadReplacement: UpdateFile ставится только если FileEntryExt(keep) == normalizeExt(ext) (расширения точно совпадают, включая пустое).
Матч по эквивалентности (расширения разные) → keeper + все дубли идут в DeleteIDs, UpdateID пуст.
UploadToFolderReplacing: при UpdateID != "" — update in-place (+ удаление лишних дублей); иначе — delete всех совпадений и свежий upload (сервер конвертирует). Fallback при ошибке update (delete+upload) сохранён.
AssertNoFileConflict (--no-replace) не менялся: он уже conversion-aware и UpdateFile не вызывает.
Тесты
Правленые/новые offline-тесты в files_replace_test.go: exact-ext (pdf→pdf, xlsx→xlsx, xls→xls) → UpdateID, без delete; converted .xls при .xlsx → delete+upload; коллапс converted-дублей; повторный .xls → delete+upload (регрессия #84).
go test -race ./... — ok (все пакеты), go vet ./... — чисто. gofmt -l по моим файлам пусто; в репо есть пре-существующие (не мои) неотформатированные cmd/office/... файлы — не трогал (вне scope).
Live (реальный OO, временная папка oo-it-84-*, удалена)
1-й upload test.xls (публичный OLE2-фикстур) → kit84.xlsx, 8192 B, download Microsoft Excel 2007+ (PK).
Повтор upload .xls → таблица replaced=3889 (delete+upload, не UpdateFile), в папке один файл, download снова валидный OOXML PK.
pdf→pdf повтор → тот же id 3890, replaced пусто (путь UpdateFile) — регрессии нет.
Папка удалена через oo dav rm --folders. Banks/Caixa не трогал.
## Готово — PR #85 (https://git.produktor.io/eSlider/go-onlyoffice/pulls/85), ветка `fix/dav-updatefile-convert#84`, коммит aad6315.
### Причина
`UploadToFolderReplacing` матчил legacy↔OOXML (`.xls` ↔ сохранённый `.xlsx`) через `EquivalentUploadExt` и вызывал `UpdateFile`. OnlyOffice при update тело не конвертирует → сырой `.xls` (OLE2) оставался под именем `.xlsx`.
### Правило update vs delete+upload
- `planUploadReplacement`: `UpdateFile` ставится **только если `FileEntryExt(keep) == normalizeExt(ext)`** (расширения точно совпадают, включая пустое).
- Матч по эквивалентности (расширения разные) → keeper + все дубли идут в `DeleteIDs`, `UpdateID` пуст.
- `UploadToFolderReplacing`: при `UpdateID != ""` — update in-place (+ удаление лишних дублей); иначе — delete всех совпадений и свежий upload (сервер конвертирует). Fallback при ошибке update (delete+upload) сохранён.
- `AssertNoFileConflict` (`--no-replace`) не менялся: он уже conversion-aware и `UpdateFile` не вызывает.
### Тесты
- Правленые/новые offline-тесты в `files_replace_test.go`: exact-ext (pdf→pdf, xlsx→xlsx, xls→xls) → `UpdateID`, без delete; converted `.xls` при `.xlsx` → delete+upload; коллапс converted-дублей; повторный `.xls` → delete+upload (регрессия #84).
- `go test -race ./...` — ok (все пакеты), `go vet ./...` — чисто. `gofmt -l` по моим файлам пусто; в репо есть **пре-существующие** (не мои) неотформатированные `cmd/office/...` файлы — не трогал (вне scope).
### Live (реальный OO, временная папка `oo-it-84-*`, удалена)
- 1-й upload `test.xls` (публичный OLE2-фикстур) → `kit84.xlsx`, 8192 B, download `Microsoft Excel 2007+` (`PK`).
- Повтор upload `.xls` → таблица `replaced=3889` (delete+upload, не UpdateFile), в папке один файл, download снова валидный OOXML `PK`.
- `pdf→pdf` повтор → тот же id 3890, `replaced` пусто (путь UpdateFile) — регрессии нет.
- Папка удалена через `oo dav rm --folders`. `Banks/Caixa` не трогал.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Проблема (регрессия от #82)
UploadToFolderReplacingтеперь матчит конвертируемые расширения (.xls↔.xlsx) и присовпадении вызывает
UpdateFile. Но OnlyOffice не конвертирует тело приUpdateFile,поэтому сырой
.xls(OLE2) ложится под прежним именем.xlsx— расширение несоответствует содержимому, файл не открывается.
Живое доказательство (2026-09-27,
Banks/Caixa/extractos/):UpdateFileid 3799/3800 имели размер 192000/7168 B и magicd0cf 11e0(OLE2.xls)при title
.xlsx;rm+ свежего upload сервер сконвертировал в настоящий.xlsx(50743 B,PK).Что сделать
UploadToFolderReplacingприменятьUpdateFileтолько когда расширения совпадают(
stored ext == local ext)..xls/.doc/.ppt↔ OOXML),делать delete (все дубли по stem) → upload — пусть сервер конвертирует в OOXML.
AssertNoFileConflict(--no-replace) оставить conversion-aware, но без UpdateFile-пути..xlsпри существующем.xlsx→ файл перезалит (несколько id меняется),содержимое — валидный OOXML (не OLE2 под
.xlsx).Acceptance
oo dav upload <folder> f.xls --replace→ один файл, содержимое валидный.xlsx;go test -race ./...,go vet ./...,gofmt -l .— чисто.Оценка: S
Начинаю. План: TDD — сначала тесты на planUploadReplacement (exact-ext → UpdateFile; legacy↔OOXML → delete+upload), затем правка files_stem.go. AssertNoFileConflict уже conversion-aware и UpdateFile не вызывает — не трогаем. Live — по наличию env.
Готово — PR #85 (#85), ветка
fix/dav-updatefile-convert#84, коммитaad6315.Причина
UploadToFolderReplacingматчил legacy↔OOXML (.xls↔ сохранённый.xlsx) черезEquivalentUploadExtи вызывалUpdateFile. OnlyOffice при update тело не конвертирует → сырой.xls(OLE2) оставался под именем.xlsx.Правило update vs delete+upload
planUploadReplacement:UpdateFileставится только еслиFileEntryExt(keep) == normalizeExt(ext)(расширения точно совпадают, включая пустое).DeleteIDs,UpdateIDпуст.UploadToFolderReplacing: приUpdateID != ""— update in-place (+ удаление лишних дублей); иначе — delete всех совпадений и свежий upload (сервер конвертирует). Fallback при ошибке update (delete+upload) сохранён.AssertNoFileConflict(--no-replace) не менялся: он уже conversion-aware иUpdateFileне вызывает.Тесты
files_replace_test.go: exact-ext (pdf→pdf, xlsx→xlsx, xls→xls) →UpdateID, без delete; converted.xlsпри.xlsx→ delete+upload; коллапс converted-дублей; повторный.xls→ delete+upload (регрессия #84).go test -race ./...— ok (все пакеты),go vet ./...— чисто.gofmt -lпо моим файлам пусто; в репо есть пре-существующие (не мои) неотформатированныеcmd/office/...файлы — не трогал (вне scope).Live (реальный OO, временная папка
oo-it-84-*, удалена)test.xls(публичный OLE2-фикстур) →kit84.xlsx, 8192 B, downloadMicrosoft Excel 2007+(PK)..xls→ таблицаreplaced=3889(delete+upload, не UpdateFile), в папке один файл, download снова валидный OOXMLPK.pdf→pdfповтор → тот же id 3890,replacedпусто (путь UpdateFile) — регрессии нет.oo dav rm --folders.Banks/Caixaне трогал.