tools: restore.sh refuses a flag in the stock launcher's place, in its own words and 2

restore.sh checks its first word for a dash-led flag and its third word for being left over, but
the optional second word - the stock launcher package - went straight to recovery.py: `restore.sh
<list> --reset` answered "not a package name: '--reset'" and exited 1, the status the header keeps for
a restore that started and did not finish, with no usage line and nothing saying the TV was left alone.
A dash-led second word is now refused like the first, before anything is resolved or sent.

test_restore_command_line.py gains the shape (three flags), and its docstring names it.
This commit is contained in:
xbsheng committed 2026-11-06 16:53:49 +08:00
1 parent 3c122bc073
commit 727b57ffba
2 files changed
+39 -3

No files matched your search

+27 -3
View File
@@ -1,4 +1,5 @@
"""restore.sh reads its own command line before it moves: no list, a flag, a list that is not there, a third word.
"""restore.sh reads its own command line before it moves: no list, a flag in either word, a list that is
not there, a third word.
The undo is the script an owner reaches for when the TV already looks wrong, and it read its first two
words only:
@@ -22,9 +23,16 @@ words only:
`--reset` copied over from theme.sh) was dropped without a word and the TV was restored anyway, while
recovery.py refuses three words with its usage line and exit 2 when a caller hands them over.
restore.ps1 refuses them on its own: PowerShell binds two positional arguments.
- A dash-led word in the second place - `restore.sh <list> --reset`, the flag pasted from theme.sh where
the stock launcher goes - passed the first word's check because the list was fine, and recovery.py
answered `not a package name: '--reset'` with exit 1, the status this script keeps for a restore that
started and did not finish: no usage line, no "Nothing was sent to the TV", and a message about a
package name where the reader had typed a flag. restore.ps1 refuses it on its own - PowerShell reads a
dash-led word as a parameter name.
All four now answer before anything is sent, in the script's own words with its usage line: no list and a
dash-led word exit 2 (the command line is not one it can read, and the header says so), the folder that is
All five now answer before anything is sent, in the script's own words with its usage line: no list and a
dash-led word, in either of the two places the script reads (the list and the optional stock launcher),
exit 2 (the command line is not one it can read, and the header says so), the folder that is
not there keeps the path as typed so recovery.py's refusal is what the reader reads, and a word left over
exits 2 saying it would not have been used. What the script does with the two words it takes is unchanged -
the list is still resolved against the caller's directory in the `pwd -W` form Git Bash needs for the
@@ -171,6 +179,22 @@ class RestoreCommandLineTest(unittest.TestCase):
self.assertEqual(result.stdout, "")
self.assertEqual(self.sent(), [])
def test_a_dash_led_stock_launcher_word_is_a_flag_it_does_not_have(self):
# The second word is the stock launcher package, and theme.sh's `--reset` pasted there passed
# the first word's check: recovery.py answered "not a package name: '--reset'" with exit 1.
for word in ("--reset", "-h", "--help"):
with self.subTest(word):
self.state_path.write_text(json.dumps({"commands": []}))
result, output = self.run_script("restore.sh", str(self.list_path), word)
self.assertEqual(result.returncode, 2, output)
self.assertIn(word + " is a flag it does not have", result.stderr)
self.assertIn("usage: TV_HOST=<tv ip> tools/restore.sh", result.stderr)
self.assertIn("Nothing was sent to the TV", result.stderr)
self.assertNotIn("not a package name", output,
"recovery.py read the flag as a package name")
self.assertEqual(result.stdout, "")
self.assertEqual(self.sent(), [])
def test_restore_ps1_already_answers_both_shapes(self):
extra = "com.google.android.tvlauncher"
cases = [((str(self.list_path), extra, extra), extra),
+12
View File
@@ -26,6 +26,18 @@ case "$LIST" in
echo "usage: TV_HOST=<tv ip> tools/restore.sh <debloat list> [stock launcher package]" >&2
exit 2 ;;
esac
# The same word one place later. The second word is the optional stock launcher package, and the flag
# that gets pasted there - `--reset` copied over from theme.sh, `-h` - passed the list check because the
# list itself was fine; recovery.py then answered "not a package name: '--reset'" and exited 1, the status
# this script keeps for a restore that started and did not finish, with no usage line and nothing saying
# the TV was left alone, so a reader who typed a flag read it as a failed restore. restore.ps1 refuses it
# on its own: PowerShell reads a dash-led word as a parameter name.
case "${2:-}" in
-*)
echo "restore.sh takes a debloat list and an optional stock launcher package, and $2 is a flag it does not have. Nothing was sent to the TV." >&2
echo "usage: TV_HOST=<tv ip> tools/restore.sh <debloat list> [stock launcher package]" >&2
exit 2 ;;
esac
# A list and the optional stock launcher, and nothing else. Only the first two words were read, so a
# line with a word appended - the stock package named twice, a second list path, `--reset` copied over
# from theme.sh - restored the TV while that word was dropped without a word, on the one script an