The request href is ours, written into the REPORT body verbatim; the
response href is the server's own spelling of it. Compared as raw
encodedPath, a server answering /my@dav.ics for a requested
/my%40dav.ics -- the case UrlUtils.equals exists for -- puts one
resource in unsolicited *and* in missing, drops its intact body, and
after three such runs quarantines it out of the download for good,
because nothing on that side can refund the count. Our own names never
carry an @, so this is about resources other clients created, which is
most of an existing collection.
The key is now scheme, host, port and the *decoded* path segments. A
list rather than a joined string, so /a%2Fb does not collide with /a/b;
with the host, so a same-path href from elsewhere cannot supply a body
for our row. The trailing slash still distinguishes, as UrlUtils.equals
also refuses to normalise it.
The syncer stops spending an unrefundable count on a guess: when the
server both omitted hrefs we asked for and volunteered hrefs we did not,
"omitted" and "we did not recognise its spelling" are indistinguishable,
so those are skipped rather than failed. A wasteful re-request is
recoverable; a permanently dropped task is not.