github.com/ActiveState/cli@v0.0.0-20240508170324-6801f60cd051/cmd/state/internal/cmdtree/cmdtree.go (about) 1 package cmdtree 2 3 import ( 4 "time" 5 6 "github.com/ActiveState/cli/cmd/state/internal/cmdtree/exechandlers/cmdcall" 7 "github.com/ActiveState/cli/internal/captain" 8 "github.com/ActiveState/cli/internal/condition" 9 "github.com/ActiveState/cli/internal/locale" 10 "github.com/ActiveState/cli/internal/logging" 11 "github.com/ActiveState/cli/internal/primer" 12 "github.com/ActiveState/cli/internal/profile" 13 "github.com/ActiveState/cli/internal/runners/state" 14 secretsapi "github.com/ActiveState/cli/pkg/platform/api/secrets" 15 ) 16 17 // CmdTree manages a tree of captain.Command instances. 18 type CmdTree struct { 19 cmd *captain.Command 20 } 21 22 // New prepares a CmdTree. 23 func New(prime *primer.Values, args ...string) *CmdTree { 24 defer profile.Measure("cmdtree:New", time.Now()) 25 26 globals := newGlobalOptions() 27 28 authCmd := newAuthCommand(prime, globals) 29 authCmd.AddChildren( 30 newSignupCommand(prime), 31 newLogoutCommand(prime), 32 ) 33 34 cveCmd := newCveCommand(prime) 35 cveCmd.AddChildren( 36 newReportCommand(prime), 37 newOpenCommand(prime), 38 ) 39 40 exportCmd := newExportCommand(prime) 41 exportCmd.AddChildren( 42 newJWTCommand(prime), 43 newPrivateKeyCommand(prime), 44 newAPIKeyCommand(prime), 45 newExportConfigCommand(prime), 46 newExportGithubActionCommand(prime), 47 newExportDocsCommand(prime), 48 newExportEnvCommand(prime), 49 newLogCommand(prime), 50 ) 51 52 platformsCmd := newPlatformsCommand(prime) 53 platformsCmd.AddChildren( 54 newPlatformsSearchCommand(prime), 55 newPlatformsAddCommand(prime), 56 newPlatformsRemoveCommand(prime), 57 ) 58 59 scriptsCmd := newScriptsCommand(prime) 60 scriptsCmd.AddChildren( 61 newScriptsEditCommand(prime), 62 ) 63 64 languagesCmd := newLanguagesCommand(prime) 65 languagesCmd.AddChildren( 66 newLanguageInstallCommand(prime), 67 newLanguageSearchCommand(prime), 68 ) 69 70 cleanCmd := newCleanCommand(prime) 71 cleanCmd.AddChildren( 72 newCleanUninstallCommand(prime, globals), 73 newCleanCacheCommand(prime, globals), 74 newCleanConfigCommand(prime), 75 ) 76 77 deployCmd := newDeployCommand(prime) 78 deployCmd.AddChildren( 79 newDeployInstallCommand(prime), 80 newDeployConfigureCommand(prime), 81 newDeploySymlinkCommand(prime), 82 newDeployReportCommand(prime), 83 newDeployUninstallCommand(prime), 84 ) 85 86 tutorialCmd := newTutorialCommand(prime) 87 tutorialCmd.AddChildren(newTutorialProjectCommand(prime)) 88 89 eventsCmd := newEventsCommand(prime) 90 eventsCmd.AddChildren(newEventsLogCommand(prime)) 91 92 installCmd := newInstallCommand(prime) 93 uninstallCmd := newUninstallCommand(prime) 94 importCmd := newImportCommand(prime, globals) 95 searchCmd := newSearchCommand(prime) 96 infoCmd := newInfoCommand(prime) 97 98 pkgsCmd := newPackagesCommand(prime) 99 addAs := addCmdAs{ 100 pkgsCmd, 101 prime, 102 } 103 addAs.deprecatedAlias(installCmd, "add") 104 addAs.deprecatedAlias(installCmd, "update") 105 addAs.deprecatedAlias(uninstallCmd, "remove") 106 addAs.deprecatedAlias(importCmd, "import") 107 addAs.deprecatedAlias(searchCmd, "search") 108 109 bundlesCmd := newBundlesCommand(prime) 110 bundlesCmd.AddChildren( 111 newBundleInstallCommand(prime), 112 newBundleUninstallCommand(prime), 113 newBundlesSearchCommand(prime), 114 ) 115 116 secretsClient := secretsapi.InitializeClient(prime.Auth()) 117 secretsCmd := newSecretsCommand(secretsClient, prime) 118 secretsCmd.AddChildren( 119 newSecretsGetCommand(prime), 120 newSecretsSetCommand(prime), 121 newSecretsSyncCommand(secretsClient, prime), 122 ) 123 124 projectsCmd := newProjectsCommand(prime) 125 projectsCmd.AddChildren( 126 newRemoteProjectsCommand(prime), 127 newProjectsEditCommand(prime), 128 newDeleteProjectsCommand(prime), 129 newMoveProjectsCommand(prime), 130 ) 131 132 updateCmd := newUpdateCommand(prime) 133 updateCmd.AddChildren( 134 newUpdateLockCommand(prime, globals), 135 newUpdateUnlockCommand(prime, globals)) 136 137 branchCmd := newBranchCommand(prime) 138 branchCmd.AddChildren( 139 /* Disabled as per https://www.pivotaltracker.com/story/show/177051006 140 newBranchAddCommand(prime), 141 */ 142 newBranchSwitchCommand(prime), 143 ) 144 prepareCmd := newPrepareCommand(prime) 145 prepareCmd.AddChildren(newPrepareCompletionsCommand(prime)) 146 147 configCmd := newConfigCommand(prime) 148 configCmd.AddChildren(newConfigGetCommand(prime), newConfigSetCommand(prime)) 149 150 checkoutCmd := newCheckoutCommand(prime) 151 152 useCmd := newUseCommand(prime) 153 useCmd.AddChildren( 154 newUseResetCommand(prime, globals), 155 newUseShowCommand(prime), 156 ) 157 158 shellCmd := newShellCommand(prime) 159 160 refreshCmd := newRefreshCommand(prime) 161 162 artifactsCmd := newArtifactsCommand(prime) 163 artifactsCmd.AddChildren( 164 newArtifactsDownloadCommand(prime), 165 ) 166 167 stateCmd := newStateCommand(globals, prime) 168 stateCmd.AddChildren( 169 newHelloCommand(prime), 170 newActivateCommand(prime), 171 newInitCommand(prime), 172 newPushCommand(prime), 173 cveCmd, 174 projectsCmd, 175 authCmd, 176 exportCmd, 177 newOrganizationsCommand(prime), 178 newRunCommand(prime), 179 newShowCommand(prime), 180 installCmd, 181 uninstallCmd, 182 importCmd, 183 searchCmd, 184 infoCmd, 185 pkgsCmd, 186 bundlesCmd, 187 platformsCmd, 188 newHistoryCommand(prime), 189 cleanCmd, 190 languagesCmd, 191 deployCmd, 192 scriptsCmd, 193 eventsCmd, 194 newPullCommand(prime, globals), 195 updateCmd, 196 newForkCommand(prime), 197 newPpmCommand(prime), 198 newInviteCommand(prime), 199 tutorialCmd, 200 prepareCmd, 201 newProtocolCommand(prime), 202 newExecCommand(prime, args...), 203 newRevertCommand(prime, globals), 204 newResetCommand(prime, globals), 205 secretsCmd, 206 branchCmd, 207 newLearnCommand(prime), 208 configCmd, 209 checkoutCmd, 210 useCmd, 211 shellCmd, 212 refreshCmd, 213 newSwitchCommand(prime), 214 newTestCommand(prime), 215 newCommitCommand(prime), 216 newPublish(prime), 217 newEvalCommand(prime), 218 newManifestCommmand(prime), 219 artifactsCmd, 220 ) 221 222 return &CmdTree{ 223 cmd: stateCmd, 224 } 225 } 226 227 type globalOptions struct { 228 Verbose bool 229 Output string 230 Monochrome bool 231 NonInteractive bool 232 } 233 234 // Group instances are used to group command help output. 235 var ( 236 EnvironmentSetupGroup = captain.NewCommandGroup(locale.Tl("group_environment_setup", "Environment Setup"), 10) 237 EnvironmentUsageGroup = captain.NewCommandGroup(locale.Tl("group_environment_usage", "Environment Usage"), 9) 238 ProjectUsageGroup = captain.NewCommandGroup(locale.Tl("group_project_usages", "Project Usage"), 8) 239 PackagesGroup = captain.NewCommandGroup(locale.Tl("group_packages", "Package Management"), 7) 240 PlatformGroup = captain.NewCommandGroup(locale.Tl("group_tools", "Platform"), 6) 241 VCSGroup = captain.NewCommandGroup(locale.Tl("group_vcs", "Version Control"), 5) 242 AutomationGroup = captain.NewCommandGroup(locale.Tl("group_automation", "Automation"), 4) 243 UtilsGroup = captain.NewCommandGroup(locale.Tl("group_utils", "Utilities"), 3) 244 AuthorGroup = captain.NewCommandGroup(locale.Tl("group_author", "Author"), 6) 245 ) 246 247 func newGlobalOptions() *globalOptions { 248 return &globalOptions{} 249 } 250 251 func newStateCommand(globals *globalOptions, prime *primer.Values) *captain.Command { 252 opts := state.NewOptions() 253 var help bool 254 255 runner := state.New(opts, prime) 256 cmd := captain.NewCommand( 257 "state", 258 "", 259 locale.T("state_description"), 260 prime, 261 []*captain.Flag{ 262 { 263 Name: "locale", 264 Shorthand: "l", 265 Description: locale.T("flag_state_locale_description"), 266 Persist: true, 267 Value: &opts.Locale, 268 }, 269 { 270 Name: "verbose", 271 Shorthand: "v", 272 Description: locale.T("flag_state_verbose_description"), 273 Persist: true, 274 OnUse: func() { 275 if !condition.InUnitTest() { 276 logging.CurrentHandler().SetVerbose(true) 277 } 278 }, 279 Value: &globals.Verbose, 280 }, 281 { 282 Name: "mono", // Name and Shorthand should be kept in sync with cmd/state/output.go 283 Persist: true, 284 Description: locale.T("flag_state_monochrome_output_description"), 285 Value: &globals.Monochrome, 286 }, 287 { 288 Name: "output", // Name and Shorthand should be kept in sync with cmd/state/output.go 289 Shorthand: "o", 290 Description: locale.T("flag_state_output_description"), 291 Persist: true, 292 Value: &globals.Output, 293 }, 294 { 295 Name: "non-interactive", // Name and Shorthand should be kept in sync with cmd/state/output.go 296 Description: locale.T("flag_state_non_interactive_description"), 297 Shorthand: "n", 298 Persist: true, 299 Value: &globals.NonInteractive, 300 }, 301 { 302 Name: "version", 303 Description: locale.T("flag_state_version_description"), 304 Value: &opts.Version, 305 }, 306 { 307 Name: "help", 308 Description: locale.Tl("flag_help", "Help for this command"), 309 Shorthand: "h", 310 Persist: true, 311 Value: &help, // need to store the value somewhere, but Cobra handles this flag by itself 312 }, 313 }, 314 []*captain.Argument{}, 315 func(ccmd *captain.Command, args []string) error { 316 if globals.Verbose { 317 logging.CurrentHandler().SetVerbose(true) 318 } 319 320 return runner.Run(ccmd.Usage) 321 }, 322 ) 323 324 cmdCall := cmdcall.New(prime) 325 326 cmd.SetHasVariableArguments() 327 cmd.OnExecStart(cmdCall.OnExecStart) 328 cmd.OnExecStop(cmdCall.OnExecStop) 329 cmd.SetSupportsStructuredOutput() 330 331 return cmd 332 } 333 334 // Execute runs the CmdTree using the provided CLI arguments. 335 func (ct *CmdTree) Execute(args []string) error { 336 defer profile.Measure("cmdtree:Execute", time.Now()) 337 return ct.cmd.Execute(args) 338 } 339 340 func (ct *CmdTree) OnExecStart(handler captain.ExecEventHandler) { 341 ct.cmd.OnExecStart(handler) 342 } 343 344 func (ct *CmdTree) OnExecStop(handler captain.ExecEventHandler) { 345 ct.cmd.OnExecStop(handler) 346 } 347 348 // Command returns the root command of the CmdTree 349 func (ct *CmdTree) Command() *captain.Command { 350 return ct.cmd 351 } 352 353 type addCmdAs struct { 354 parent *captain.Command 355 prime *primer.Values 356 } 357 358 func (a *addCmdAs) deprecatedAlias(aliased *captain.Command, name string) { 359 cmd := captain.NewCommand( 360 name, 361 aliased.Title(), 362 aliased.Description(), 363 a.prime, 364 aliased.Flags(), 365 aliased.Arguments(), 366 func(c *captain.Command, args []string) error { 367 msg := locale.Tl( 368 "cmd_deprecated_notice", 369 "This command is deprecated. Please use '[ACTIONABLE]state {{.V0}}[/RESET]' instead.", 370 aliased.Name(), 371 ) 372 373 a.prime.Output().Notice(msg) 374 375 return aliased.ExecuteFunc()(c, args) 376 }, 377 ) 378 379 cmd.SetHidden(true) 380 cmd.SetHasVariableArguments() 381 382 a.parent.AddChildren(cmd) 383 }