1717#include " cuttlefish/host/commands/cvd/cli/commands/reset.h"
1818
1919#include < ctype.h>
20+ #include < fmt/format.h>
2021
2122#include < algorithm>
2223#include < iostream>
2829#include " cuttlefish/flag_parser/gflags_compat.h"
2930#include " cuttlefish/host/commands/cvd/cli/command_request.h"
3031#include " cuttlefish/host/commands/cvd/cli/commands/command_handler.h"
32+ #include " cuttlefish/host/commands/cvd/cli/help_format.h"
3133#include " cuttlefish/host/commands/cvd/cli/types.h"
3234#include " cuttlefish/host/commands/cvd/instances/instance_manager.h"
35+ #include " cuttlefish/host/commands/cvd/utils/common.h"
3336#include " cuttlefish/result/result.h"
3437
3538namespace cuttlefish {
@@ -38,64 +41,7 @@ namespace {
3841constexpr char kResetSubcmd [] = " reset" ;
3942
4043constexpr char kSummaryHelpText [] =
41- " Used to stop devices, optionally clean up instance files, and shut down "
42- " the deprecated cvd server process" ;
43-
44- constexpr char kDetailedHelpText [] = R"( usage: cvd reset <args>
45-
46- * Warning: Cvd reset is an experimental implementation. When you are in panic,
47- cvd reset is the last resort.
48-
49- args:
50- --help Prints this message.
51- help
52-
53- --device-by-cvd-only Terminates devices that a cvd server started
54- This excludes the devices launched by "launch_cvd"
55- or "cvd_internal_start" directly (default: false)
56-
57- --clean-runtime-dir Cleans up the runtime directory for the devices
58- Yet to be implemented. For now, if true, only if
59- stop_cvd supports --clear_instance_dirs and the
60- device could be stopped by stop_cvd, the flag takes
61- effects. (default: true)
62-
63- --yes Resets without asking the user confirmation.
64- -y
65-
66- description:
67-
68- 1. Gracefully stops all devices that the cvd client can reach.
69- 2. Forcefully stops all run_cvd processes and their subprocesses.
70- 3. Kill the cvd server itself if unresponsive.
71- 4. Reset the states of the involved instance lock files
72- -- If cvd reset stops a device, it resets the corresponding lock file.
73- 5. Optionally, cleans up the runtime files of the stopped devices.)" ;
74-
75- struct ParsedFlags {
76- bool clean_runtime_dir = true ;
77- bool is_confirmed_by_flag = false ;
78- };
79-
80- static Result<ParsedFlags> ParseResetFlags (cvd_common::Args subcmd_args) {
81- if (subcmd_args.size () > 2 && subcmd_args.at (2 ) == " help" ) {
82- // Turn `cvd reset help` into `cvd reset --help`
83- subcmd_args[2 ] = " --help" ;
84- }
85-
86- ParsedFlags parsed_flags;
87-
88- Flag y_flag =
89- GflagsCompatFlag (" yes" , parsed_flags.is_confirmed_by_flag ).Alias (" y" );
90- std::vector<Flag> flags{
91- y_flag,
92- GflagsCompatFlag (" clean-runtime-dir" , parsed_flags.clean_runtime_dir ),
93- };
94- CF_EXPECT (
95- ConsumeFlags (flags, subcmd_args, {.fail_on_unexpected_argument = true }));
96-
97- return parsed_flags;
98- }
44+ " Remove all instance groups and kills orphaned cuttlefish processes" ;
9945
10046static bool GetUserConfirm () {
10147 std::cout << " Are you sure to reset all the devices, runtime files, "
@@ -114,15 +60,17 @@ CvdResetCommandHandler::CvdResetCommandHandler(
11460
11561Result<void > CvdResetCommandHandler::Handle (const CommandRequest& request) {
11662 std::vector<std::string> subcmd_args = request.SubcommandArguments ();
117- auto options = CF_EXPECT (ParseResetFlags (subcmd_args));
63+ std::vector<Flag> flags = CF_EXPECT (Flags (request));
64+ CF_EXPECT (
65+ ConsumeFlags (flags, subcmd_args, {.fail_on_unexpected_argument = true }));
11866
11967 // cvd reset. Give one more opportunity
120- if (!options .is_confirmed_by_flag && !GetUserConfirm ()) {
121- std::cout << " For more details: " << " cvd reset -- help" << std::endl;
68+ if (!flags_ .is_confirmed_by_flag && !GetUserConfirm ()) {
69+ std::cout << " For more details: " << " cvd help reset " << std::endl;
12270 return {};
12371 }
12472
125- if (options .clean_runtime_dir ) {
73+ if (flags_ .clean_runtime_dir ) {
12674 CF_EXPECT (instance_manager_.ResetAndClearInstanceDirs ());
12775 } else {
12876 CF_EXPECT (instance_manager_.Reset ());
@@ -138,9 +86,63 @@ std::string CvdResetCommandHandler::SummaryHelp() const {
13886 return kSummaryHelpText ;
13987}
14088
141- Result<std::string> CvdResetCommandHandler::DetailedHelp (
142- const CommandRequest& /* request*/ ) {
143- return kDetailedHelpText ;
89+ std::vector<HelpParagraph> CvdResetCommandHandler::Description () const {
90+ return {
91+ HelpParagraph::Raw (
92+ " Usage:\n cvd reset [--yes] [--noclean-runtime-dir]" ),
93+ HelpParagraph (" Warning: `cvd reset` is an experimental command and "
94+ " should only be used as a last resort. Prefer `cvd remove` "
95+ " and/or `cvd clear` instead." ),
96+ HelpParagraph (
97+ " Attempts to remove any trace of running Cuttlefish devices *owned "
98+ " by the current user*. This includes Cuttlefish devices not tracked "
99+ " by CVD, such as those started by the legacy launch_cvd invocations. "
100+ " It's particularly useful for file-in-use errors and when ADB "
101+ " remains connected to untracked devices." ),
102+ HelpParagraph (
103+ " This is a destructive operation that cannot be undone, so the "
104+ " command always asks for confirmation from the user and exits if it "
105+ " can't get it. Confirmation can be provided on the command line with "
106+ " the --yes flag which allows the command to be used in scripts and "
107+ " other non-interactive use cases." ),
108+ HelpParagraph (
109+ " By default, all instance directories and files are deleted as part "
110+ " of the reset. It is possible to skip this step for untracked "
111+ " instances (those not members of any known instance group) by "
112+ " passing the --noclean-runtime-dir flag. This allows examining the "
113+ " runtime files of any untracked instances after the reset. Tracked "
114+ " instances can be managed using other commands (like stop) to "
115+ " preserve their files, so this option doesn't apply to them and "
116+ " their runtime files are always deleted during reset." ),
117+ HelpParagraph (" `cvd reset` executes the following steps:" ),
118+ HelpParagraph (" 1. Stop and remove all known instance groups." ),
119+ HelpParagraph (" 2. Gracefully stop all remaining devices that CVD can "
120+ " reach and optionally clean their runtime directories." ),
121+ HelpParagraph (
122+ " 3. Kill all remaining run_cvd processes and their subprocesses." ),
123+ HelpParagraph (" 4. Release host resources previously used by any "
124+ " untracked devices." ),
125+ HelpParagraph (
126+ fmt::format (" These steps are a best-effort attempt at resetting CVD "
127+ " to a clean state, but it may sometimes not be enough. "
128+ " In those cases the best course of action might be to "
129+ " reboot the system and then delete the '{}' directory." ,
130+ CvdDir ())),
131+ };
132+ }
133+
134+ Result<std::vector<Flag>> CvdResetCommandHandler::Flags (const CommandRequest&) {
135+ Flag y_flag = GflagsCompatFlag (" yes" , flags_.is_confirmed_by_flag )
136+ .Alias (" y" )
137+ .Help (
138+ " Provide user confirmation in advance so the command "
139+ " doesn't ask for it interactively." );
140+ Flag clean_runtime_dir_flag =
141+ GflagsCompatFlag (" clean-runtime-dir" , flags_.clean_runtime_dir )
142+ .Help (
143+ " Clean up the runtime directory for untracked devices (not "
144+ " members of any known instance group)" );
145+ return std::vector<Flag>{y_flag, clean_runtime_dir_flag};
144146}
145147
146148std::unique_ptr<CvdCommandHandler> NewCvdResetCommandHandler (
0 commit comments