From d434436ae925e4eabe529335776e2aa23518db8f Mon Sep 17 00:00:00 2001 From: GideonBear <87426140+GideonBear@users.noreply.github.com> Date: Fri, 1 Aug 2025 19:51:39 +0200 Subject: [PATCH] Do not ask which file to restore if there is only one option --- .../cmd/test_end_to_end_restore.py | 11 +++++----- .../cmd/test_listing_in_restore_cmd.py | 2 +- .../arg_parser/test_restore_arg_parser.py | 3 +++ .../test_restore_asking_the_user.py | 4 ++-- trashcli/restore/args.py | 1 + trashcli/restore/handler.py | 22 +++++++++++++------ trashcli/restore/restore_arg_parser.py | 2 ++ trashcli/restore/restore_asking_the_user.py | 11 +++++++++- trashcli/restore/run_restore_action.py | 4 +++- 9 files changed, 42 insertions(+), 18 deletions(-) diff --git a/tests/test_restore/cmd/test_end_to_end_restore.py b/tests/test_restore/cmd/test_end_to_end_restore.py index 87420f07..e04295e2 100644 --- a/tests/test_restore/cmd/test_end_to_end_restore.py +++ b/tests/test_restore/cmd/test_end_to_end_restore.py @@ -31,10 +31,9 @@ def test_no_file_trashed(self): def test_original_file_not_existing(self): self.fake_trash_dir.add_trashinfo3("foo", "/path", datetime(2000,1,1,0,0,1)) - result = self.run_command("trash-restore", ["/"], input='0') + result = self.run_command("trash-restore", ["/"]) - self.assertEqual(" 0 2000-01-01 00:00:01 /path\n" - "What file to restore [0..0]: \n" + self.assertEqual("2000-01-01 00:00:01 /path\n" "[Errno 2] No such file or directory: '%s/files/foo'\n" % self.trash_dir, result.output()) @@ -67,11 +66,11 @@ def test_restore_with_relative_path(self): result = self.run_command("trash-restore", ["%(curdir)s" % {'curdir': "."}, - '--sort=path'], input='0') + '--sort=path']) self.assertEqual("""\ - 0 2000-01-01 00:00:01 %(curdir)s/path/to/file1 -What file to restore [0..0]: """ % {'curdir': self.curdir}, +2000-01-01 00:00:01 %(curdir)s/path/to/file1 +""" % {'curdir': self.curdir}, result.stdout) self.assertEqual("", result.stderr) self.assertEqual("contents", read_file(pj(self.curdir, "path/to/file1"))) diff --git a/tests/test_restore/cmd/test_listing_in_restore_cmd.py b/tests/test_restore/cmd/test_listing_in_restore_cmd.py index c5788849..e6358acf 100644 --- a/tests/test_restore/cmd/test_listing_in_restore_cmd.py +++ b/tests/test_restore/cmd/test_listing_in_restore_cmd.py @@ -70,6 +70,6 @@ class FakeHandler(Handler): def __init__(self, original_locations): self.original_locations = original_locations - def handle_trashed_files(self, trashed_files, _overwrite): + def handle_trashed_files(self, trashed_files, _overwrite, _no_ask): for trashed_file in trashed_files: self.original_locations.append(trashed_file.original_location) diff --git a/tests/test_restore/components/arg_parser/test_restore_arg_parser.py b/tests/test_restore/components/arg_parser/test_restore_arg_parser.py index d5aeedca..6d390d97 100644 --- a/tests/test_restore/components/arg_parser/test_restore_arg_parser.py +++ b/tests/test_restore/components/arg_parser/test_restore_arg_parser.py @@ -13,6 +13,7 @@ def test_default_path(self): args = self.parser.parse_restore_args([''], "curdir") self.assertEqual(RunRestoreArgs(path='curdir', + path_passed=False, sort=Sort.ByDate, trash_dir=None, overwrite=False), @@ -22,6 +23,7 @@ def test_path_specified_relative_path(self): args = self.parser.parse_restore_args(['', 'path'], "curdir") self.assertEqual(RunRestoreArgs(path='curdir/path', + path_passed=True, sort=Sort.ByDate, trash_dir=None, overwrite=False), @@ -31,6 +33,7 @@ def test_path_specified_fullpath(self): args = self.parser.parse_restore_args(['', '/a/path'], "ignored") self.assertEqual(RunRestoreArgs(path='/a/path', + path_passed=True, sort=Sort.ByDate, trash_dir=None, overwrite=False), diff --git a/tests/test_restore/components/collaborators/test_restore_asking_the_user.py b/tests/test_restore/components/collaborators/test_restore_asking_the_user.py index dfd46f41..11b13cf0 100644 --- a/tests/test_restore/components/collaborators/test_restore_asking_the_user.py +++ b/tests/test_restore/components/collaborators/test_restore_asking_the_user.py @@ -22,7 +22,7 @@ def test(self): self.input.set_reply('0') self.asking_user.restore_asking_the_user(['trashed_file1', - 'trashed_file2'], False) + 'trashed_file2'], False, False) self.assertEqual('What file to restore [0..1]: ', self.input.last_prompt()) @@ -34,7 +34,7 @@ def test2(self): self.input.raise_exception(KeyboardInterrupt) self.asking_user.restore_asking_the_user(['trashed_file1', - 'trashed_file2'], False) + 'trashed_file2'], False, False) self.assertEqual('What file to restore [0..1]: ', self.input.last_prompt()) diff --git a/trashcli/restore/args.py b/trashcli/restore/args.py index bf1e1841..66958d16 100644 --- a/trashcli/restore/args.py +++ b/trashcli/restore/args.py @@ -16,6 +16,7 @@ def __repr__(self): class RunRestoreArgs( NamedTuple('RunRestoreArgs', [ ('path', str), + ('path_passed', bool), ('sort', Sort), ('trash_dir', Optional[str]), ('overwrite', bool), diff --git a/trashcli/restore/handler.py b/trashcli/restore/handler.py index 4b2ce355..9ae092ec 100644 --- a/trashcli/restore/handler.py +++ b/trashcli/restore/handler.py @@ -28,23 +28,31 @@ def __init__(self, def handle_trashed_files(self, trashed_files, # type: List[TrashedFile] overwrite, # type: bool + single_no_ask, # type: bool ): if not trashed_files: self.report_no_files_found(self.cwd.getcwd_as_realpath()) else: - for i, trashed_file in enumerate(trashed_files): - self.output.println("%4d %s %s" % (i, - trashed_file.deletion_date, - trashed_file.original_location)) - self.restore_asking_the_user(trashed_files, overwrite) + if single_no_ask and len(trashed_files) == 1: + trashed_file = trashed_files[0] + self.output.println("%s %s" % (trashed_file.deletion_date, + trashed_file.original_location)) + self.restore_asking_the_user(trashed_files, overwrite, no_ask=True) + else: + for i, trashed_file in enumerate(trashed_files): + self.output.println("%4d %s %s" % (i, + trashed_file.deletion_date, + trashed_file.original_location)) + self.restore_asking_the_user(trashed_files, overwrite) - def restore_asking_the_user(self, trashed_files, overwrite=False): + def restore_asking_the_user(self, trashed_files, overwrite=False, no_ask=False): my_output = OutputRecorder() restore_asking_the_user = RestoreAskingTheUser(self.input, self.restorer, my_output) restore_asking_the_user.restore_asking_the_user(trashed_files, - overwrite) + overwrite, + no_ask) my_output.apply_to(self.output) def report_no_files_found(self, directory): # type: (str) -> None diff --git a/trashcli/restore/restore_arg_parser.py b/trashcli/restore/restore_arg_parser.py index 435639cf..a8c57b56 100644 --- a/trashcli/restore/restore_arg_parser.py +++ b/trashcli/restore/restore_arg_parser.py @@ -51,10 +51,12 @@ def parse_restore_args(self, if parsed.version: return PrintVersionArgs(argv0=sys_argv[0]) else: + path_passed = parsed.path != "" path = os.path.normpath( os.path.join(curdir + os.path.sep, parsed.path)) return RunRestoreArgs(path=path, + path_passed=path_passed, sort=cast(Sort, { 'path': Sort.ByPath, 'date': Sort.ByDate, diff --git a/trashcli/restore/restore_asking_the_user.py b/trashcli/restore/restore_asking_the_user.py index 0bf78788..72e882dd 100644 --- a/trashcli/restore/restore_asking_the_user.py +++ b/trashcli/restore/restore_asking_the_user.py @@ -58,9 +58,12 @@ def read_user_input(self, return Right( InputRead(user_input, args.trashed_files, args.overwrite)) - def restore_asking_the_user(self, trashed_files, overwrite): + def restore_asking_the_user(self, trashed_files, overwrite, no_ask): input = Right(Context(trashed_files, overwrite)) compose(input, [ + select_all, + self.restore_selected_files, + ] if no_ask else [ self.read_user_input, trashed_files_to_restore, self.restore_selected_files, @@ -138,6 +141,12 @@ def trashed_files_to_restore(input_read, # type: InputRead return Left(Die("Invalid entry: %s" % e)) +def select_all(input_read, # type: InputRead + ): # type: (...) -> Either[Die, SelectedFiles] + selected_files = SelectedFiles(input_read.trashed_files, input_read.overwrite) + return Right(selected_files) + + class InvalidEntry(Exception): pass diff --git a/trashcli/restore/run_restore_action.py b/trashcli/restore/run_restore_action.py index 84331528..3867c9cf 100644 --- a/trashcli/restore/run_restore_action.py +++ b/trashcli/restore/run_restore_action.py @@ -26,7 +26,8 @@ def run_action(self, args, # type: RunRestoreArgs trashed_files = sort_files(args.sort, trashed_files) self.handler.handle_trashed_files(trashed_files, - args.overwrite) + args.overwrite, + args.path_passed) def all_files_trashed_from_path(self, path, # type: str @@ -44,6 +45,7 @@ class Handler: def handle_trashed_files(self, trashed_files, overwrite, # type: bool + single_no_ask, # type: bool ): raise NotImplementedError()