Skip to content

fix: revoke every share with chmod -rw, and report what changed - #58

Open
lionello wants to merge 2 commits into
masterfrom
fix-chmod
Open

fix: revoke every share with chmod -rw, and report what changed#58
lionello wants to merge 2 commits into
masterfrom
fix-chmod

Conversation

@lionello

@lionello lionello commented Aug 5, 2026

Copy link
Copy Markdown
Owner

Two bugs in chmod, found while answering a question about what the owner/group/world flags actually do. Independent of #55 — this branch is off master.

chmod -rw revoked only the first share, then failed

Deleting a permission answers 204 No Content, but the DELETE went through call(), which ends in .json():

invalid json response body at …/permissions/perm1 reason: Unexpected end of JSON input

The first share was already gone server-side by then, so an item with several shares was left partially unshared, with a confusing parse error and a nonzero exit. Anyone who ran chmod -rw on a file with two or more shares and saw that error was likely left believing nothing happened.

Fixed by using the existing del() helper, which was written for exactly this — its comment already says "DELETE returns 204 No Content on success, so don't go through call()". It was the only remaining call(…, 'DELETE') in the file.

That also avoids a trap the fix would otherwise have introduced: del() resolves to undefined, so ok = await del(…) would report "Nothing was changed" after a successful revoke. The flag is now set explicitly and initialized to false.

chmod printed nothing at all

chmod1 computed 'OK' / 'Nothing was changed' and chmod() discarded the return value, so the command was silent whether it changed something or not. Now logged per file, which also distinguishes a genuine no-op (e.g. -w against shares that are already read-only) from real work:

:/a.txt: OK
:/b.txt: Nothing was changed

Testing

No live API — the token here is expired — so I mocked the classic API with a /permissions collection that answers a real empty 204 for DELETE, and reproduced the original failure first (first share deleted, then the JSON parse error, second share untouched). After the fix, verified:

case result
two write shares, -rw both revoked, OK
two write shares, -w both PATCHed to read, OK
read-only share, -w no write requests, Nothing was changed
read-only share, -rw revoked, OK
unshared item Nothing was changed
two files on one command line one line each

Notes for the reviewer

  • npm run lint cannot run on master at all right now (ESLint 10 vs .eslintrc.js) — that is what fix: list and traverse folders shared with you (closes #7) #55 fixes. I borrowed that PR's eslint.config.js to lint this branch: no new errors, only the four pre-existing unused catch bindings that fix: list and traverse folders shared with you (closes #7) #55 cleans up. Prettier is clean.
  • Not addressed here, but worth knowing: the owner/group/world part of the mode is parsed and discarded. g-w, o-w, go-w and bare -w all collapse to the same action, and 600/700 are the same as each other, so there is no way to drop a public link while keeping a named-user share. In ls output those triads do carry meaning (triad 2 = people it is explicitly shared with, triad 3 = an anonymous link exists), which makes the flags misleading rather than merely redundant. Happy to file that separately.

🤖 Generated with Claude Code

Two problems in chmod, both found while answering "what does chmod do
with the owner/group/world flags".

`chmod -rw` revoked only the first share and then failed. Deleting a
permission answers 204 No Content, but the DELETE went through call(),
which ends in .json() and threw "invalid json response body: Unexpected
end of JSON input" on the empty body. The first share was already gone
server-side, so the item was left partially unshared with a confusing
parse error and a nonzero exit. Use the existing del() helper, written
for exactly this ("DELETE returns 204 No Content on success, so don't go
through call()").

That also fixes the `ok` tracking it would otherwise have broken: del()
resolves to undefined, so assigning its result would report "Nothing was
changed" after a successful revoke. Set the flag explicitly instead, and
initialize it to false now that it is a plain boolean.

Second, chmod1 computed 'OK' / 'Nothing was changed' and chmod() threw
it away, so the command printed nothing whichever happened. Log it per
file, which also disambiguates a no-op (e.g. -w against shares that are
already read-only) from real work.

Verified against a mock that answers 204 for DELETE the way the API
does: -rw now revokes every share; -w patches every write share to read;
read-only-under--w, an unshared item, and multiple files on one command
line all report correctly.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Comment thread bin/onedrive Outdated
// -rw write DELETE
// -rw read DELETE
let ok // FIXME track result from all shares
let ok = false // FIXME track result from all shares

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this FIXME not addressed? @defangdevs

Addresses the "FIXME track result from all shares" that the previous
commit left in place. That commit only kept `ok` correct after the switch
to del() -- it went from "result of the last mutation" to "did any
mutation happen", which is still the aggregate the FIXME complains about.

Count the shares instead, and say what happened:

  :/a.txt: 2 shares made read-only
  :/a.txt: 1 share made read-only, 2 shares already read-only
  :/a.txt: 2 shares revoked
  :/a.txt: Nothing was changed

The mixed case is the one that was previously unreportable: `-w` against
an item shared both ways patched the write shares and silently ignored
the read-only ones, and a single boolean could not distinguish that from
having changed everything.

A share that errors still aborts the remainder, so the counts describe
the shares reached before that point; noted in a comment where the vague
FIXME used to be. Deciding whether chmod should instead push past a
failing share and report per-share errors is a behavioral change, left
alone here.

Verified against the 204-answering mock across write-only, read-only and
mixed permission sets for both modes, plus the unshared item: counts,
singular/plural, and the emitted requests all match.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants