mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-18 21:16:47 +00:00
fix(docsync): stop a push from stealing another file's pairing
Papra answers a push of bytes it already holds with the document that has them. Two trip files with the same content therefore pushed to one document, and the unique index on (link_id, remote_id) aborted that run and every run after it with a constraint error. The pairing now stays with the file that owns it and the second file is recorded as a conflict. Also in this pass: - Paperless no longer adopts a same-bytes document that lacks the scope's tag when a consume outlives the poll budget; that document belongs to someone else's filing and delete-through would have trashed it. - The pull path writes the file row, the retirement of the copy it replaces and the pairing in one transaction, and announces them only once committed. - PATCH links stops accepting remoteRootId/remoteRootPath, which it read and silently dropped. - The MCP sync tool clears shelved items before running, as the REST route does.
This commit is contained in:
@@ -570,3 +570,31 @@ describe('planReconcile > a pairing whose download never landed', () => {
|
||||
expect(p.actions.map(a => a.kind)).toEqual(['touch']);
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Names are compared through the same sanitiser the local one went through.
|
||||
*
|
||||
* A provider name TREK had to clean up — a slash, a control character, a
|
||||
* leading dot — otherwise reads as "TREK renamed this document" on the very
|
||||
* next run, and the provider's copy is renamed to the cleaned version without
|
||||
* anybody asking for it.
|
||||
*/
|
||||
describe('planReconcile > a provider name TREK had to clean up', () => {
|
||||
it('does not read the cleaning as a local rename', () => {
|
||||
const p = plan({
|
||||
items: [item({ remoteName: 'a/b.pdf', contentSha256: 'aaa' })],
|
||||
remote: [remote({ remoteId: 'r1', name: 'a/b.pdf', remoteVersion: 'v1' })],
|
||||
local: [local({ fileId: 1, name: 'b.pdf' })], // what sanitizeIncomingName made of it
|
||||
});
|
||||
expect(p.actions.map(a => a.kind)).toEqual(['touch']);
|
||||
});
|
||||
|
||||
it('still follows a real rename at the provider', () => {
|
||||
const p = plan({
|
||||
items: [item({ remoteName: 'b.pdf', contentSha256: 'aaa' })],
|
||||
remote: [remote({ remoteId: 'r1', name: 'invoice.pdf', remoteVersion: 'v1' })],
|
||||
local: [local({ fileId: 1, name: 'b.pdf' })],
|
||||
});
|
||||
expect(p.actions.map(a => a.kind)).toEqual(['rename_local']);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user