From 18b1f580f8ad064f73db209e82724891c782fdc7 Mon Sep 17 00:00:00 2001 From: Jan Cerman Date: Fri, 15 May 2026 11:52:31 +0200 Subject: [PATCH 1/4] DOCS-2791 Fix dxda help strings --- cmd/dx-download-agent/dx-download-agent.go | 192 +++++++++++++++++++-- 1 file changed, 182 insertions(+), 10 deletions(-) diff --git a/cmd/dx-download-agent/dx-download-agent.go b/cmd/dx-download-agent/dx-download-agent.go index e237e41..a2461f5 100644 --- a/cmd/dx-download-agent/dx-download-agent.go +++ b/cmd/dx-download-agent/dx-download-agent.go @@ -4,8 +4,10 @@ import ( "context" "flag" "fmt" + "io" "log" "os" + "strings" // The dxda package should contain all core functionality "github.com/dnanexus/dxda" @@ -21,7 +23,13 @@ type downloadCmd struct { var err error +const rootDescription = "CLI tool to manage the download of files from DNAnexus" const downloadUsage = "dx-download-agent download [-num_threads=N] " +const commandsUsage = "dx-download-agent commands" +const flagsUsage = "dx-download-agent flags []" +const helpUsage = "dx-download-agent help []" +const inspectSynopsis = "Inspect files downloaded in a manifest and validate their integrity" +const versionUsage = "dx-download-agent version" func (*downloadCmd) Name() string { return "download" } func (*downloadCmd) Synopsis() string { return "Download files in a manifest" } @@ -108,7 +116,7 @@ type progressCmd struct { } func (*progressCmd) Name() string { return "progress" } -func (*progressCmd) Synopsis() string { return "show current download progress" } +func (*progressCmd) Synopsis() string { return "Show current download progress" } const progressUsage = "dx-download-agent progress " @@ -150,13 +158,13 @@ const inspectUsage = "dx-download-agent inspect [-num_threads=N] 1 { + fmt.Fprintln(os.Stderr, flagsUsage) + return subcommands.ExitUsageError + } + + if f.NArg() == 0 { + printFlags(os.Stdout, flag.CommandLine) + return subcommands.ExitSuccess + } + + cmd := findRegisteredCommand(f.Arg(0)) + if cmd == nil { + fmt.Fprintf(os.Stderr, "Subcommand %s not understood\n", f.Arg(0)) + return subcommands.ExitFailure + } + + subflags := flag.NewFlagSet(cmd.Name(), flag.PanicOnError) + cmd.SetFlags(subflags) + printFlags(os.Stdout, subflags) + return subcommands.ExitSuccess +} + +type helpCmd struct{} + +func (*helpCmd) Name() string { return "help" } +func (*helpCmd) Synopsis() string { return "Describe subcommands and their syntax" } +func (*helpCmd) Usage() string { return helpUsage } +func (*helpCmd) SetFlags(*flag.FlagSet) {} +func (*helpCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus { + switch f.NArg() { + case 0: + explainTopLevel(os.Stdout) + return subcommands.ExitSuccess + case 1: + cmd := findRegisteredCommand(f.Arg(0)) + if cmd != nil { + explainCommand(os.Stdout, cmd) + return subcommands.ExitSuccess + } + fmt.Fprintf(os.Stderr, "Subcommand %s not understood\n", f.Arg(0)) + default: + } + + fmt.Fprintln(os.Stderr, helpUsage) + return subcommands.ExitUsageError +} + +func printCommandSummary(w io.Writer, cmd subcommands.Command) { + fmt.Fprintf(w, " %-15s %s\n", cmd.Name(), cmd.Synopsis()) +} + +func visitRegisteredCommands(fn func(subcommands.Command)) { + subcommands.DefaultCommander.VisitCommands(func(_ *subcommands.CommandGroup, cmd subcommands.Command) { + fn(cmd) + }) +} + +func findRegisteredCommand(name string) subcommands.Command { + var found subcommands.Command + visitRegisteredCommands(func(cmd subcommands.Command) { + if found == nil && cmd.Name() == name { + found = cmd + } + }) + return found +} + +func printFlags(w io.Writer, fs *flag.FlagSet) { + fs.VisitAll(func(f *flag.Flag) { + name, usage := flag.UnquoteUsage(f) + line := fmt.Sprintf(" -%s", f.Name) + if name != "" { + line += " " + name + } + fmt.Fprintln(w, line) + + trimmedUsage := strings.TrimSpace(usage) + if trimmedUsage == "" { + return + } + + for _, usageLine := range strings.Split(trimmedUsage, "\n") { + fmt.Fprintf(w, " %s\n", strings.TrimSpace(usageLine)) + } + }) +} + +func explainTopLevel(w io.Writer) { + fmt.Fprintf(w, "dx-download-agent %s\n", dxda.Version) + fmt.Fprintf(w, "%s\n\n", rootDescription) + fmt.Fprintln(w, "Usage:") + fmt.Fprintf(w, " %s\n", downloadUsage) + fmt.Fprintf(w, " %s\n", inspectUsage) + fmt.Fprintf(w, " %s\n", progressUsage) + fmt.Fprintf(w, " %s\n\n", versionUsage) + fmt.Fprintln(w, "Authentication:") + fmt.Fprintln(w, " Set DX_API_TOKEN or configure ~/.dnanexus_config/environment.json.") + fmt.Fprintln(w) + fmt.Fprintln(w, "Primary commands:") + printCommandSummary(w, &downloadCmd{}) + printCommandSummary(w, &inspectCmd{}) + printCommandSummary(w, &progressCmd{}) + fmt.Fprintln(w) + fmt.Fprintln(w, "Reference commands:") + printCommandSummary(w, &versionCmd{}) + printCommandSummary(w, &helpCmd{}) + printCommandSummary(w, &flagsCmd{}) + printCommandSummary(w, &commandsCmd{}) + fmt.Fprintln(w) +} + +func explainCommand(w io.Writer, cmd subcommands.Command) { + usage := strings.TrimSpace(cmd.Usage()) + if usage != "" { + fmt.Fprintln(w, usage) + } + + synopsis := strings.TrimSpace(cmd.Synopsis()) + if synopsis != "" { + fmt.Fprintf(w, "\n%s\n", synopsis) + } + + subflags := flag.NewFlagSet(cmd.Name(), flag.PanicOnError) + cmd.SetFlags(subflags) + + var hasFlags bool + subflags.VisitAll(func(*flag.Flag) { + hasFlags = true + }) + if !hasFlags { + return + } + + fmt.Fprintln(w) + printFlags(w, subflags) +} + // The CLI is simply a wrapper around the dxda package func main() { - subcommands.Register(subcommands.HelpCommand(), "") - subcommands.Register(subcommands.FlagsCommand(), "") - subcommands.Register(subcommands.CommandsCommand(), "") + subcommands.DefaultCommander.Explain = explainTopLevel + subcommands.DefaultCommander.ExplainCommand = explainCommand + + subcommands.Register(&helpCmd{}, "") + subcommands.Register(&flagsCmd{}, "") + subcommands.Register(&commandsCmd{}, "") subcommands.Register(&downloadCmd{}, "") subcommands.Register(&progressCmd{}, "") subcommands.Register(&inspectCmd{}, "") @@ -219,7 +391,7 @@ func main() { // TODO: modify this to use individual subcommand help if len(os.Args) == 1 { - fmt.Printf("Usage:\n For progress:\n $ %s\n\n For downloading:\n $ %s\n", progressUsage, downloadUsage) + explainTopLevel(os.Stderr) os.Exit(1) } From c79a4725f0bd580e08f59034ae7bae3ee3dbfe69 Mon Sep 17 00:00:00 2001 From: Jan Cerman Date: Fri, 15 May 2026 12:09:32 +0200 Subject: [PATCH 2/4] DOCS-2791 Reduce help patch scope --- cmd/dx-download-agent/dx-download-agent.go | 52 ++-------------------- 1 file changed, 4 insertions(+), 48 deletions(-) diff --git a/cmd/dx-download-agent/dx-download-agent.go b/cmd/dx-download-agent/dx-download-agent.go index a2461f5..4173906 100644 --- a/cmd/dx-download-agent/dx-download-agent.go +++ b/cmd/dx-download-agent/dx-download-agent.go @@ -25,9 +25,7 @@ var err error const rootDescription = "CLI tool to manage the download of files from DNAnexus" const downloadUsage = "dx-download-agent download [-num_threads=N] " -const commandsUsage = "dx-download-agent commands" const flagsUsage = "dx-download-agent flags []" -const helpUsage = "dx-download-agent help []" const inspectSynopsis = "Inspect files downloaded in a manifest and validate their integrity" const versionUsage = "dx-download-agent version" @@ -215,23 +213,6 @@ func (p *versionCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{ return subcommands.ExitSuccess } -type commandsCmd struct{} - -func (*commandsCmd) Name() string { return "commands" } -func (*commandsCmd) Synopsis() string { return "List all command names" } -func (*commandsCmd) Usage() string { return commandsUsage } -func (*commandsCmd) SetFlags(*flag.FlagSet) {} -func (*commandsCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus { - if f.NArg() != 0 { - fmt.Fprintln(os.Stderr, commandsUsage) - return subcommands.ExitUsageError - } - visitRegisteredCommands(func(cmd subcommands.Command) { - fmt.Fprintln(os.Stdout, cmd.Name()) - }) - return subcommands.ExitSuccess -} - type flagsCmd struct{} func (*flagsCmd) Name() string { return "flags" } @@ -261,31 +242,6 @@ func (*flagsCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) s return subcommands.ExitSuccess } -type helpCmd struct{} - -func (*helpCmd) Name() string { return "help" } -func (*helpCmd) Synopsis() string { return "Describe subcommands and their syntax" } -func (*helpCmd) Usage() string { return helpUsage } -func (*helpCmd) SetFlags(*flag.FlagSet) {} -func (*helpCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus { - switch f.NArg() { - case 0: - explainTopLevel(os.Stdout) - return subcommands.ExitSuccess - case 1: - cmd := findRegisteredCommand(f.Arg(0)) - if cmd != nil { - explainCommand(os.Stdout, cmd) - return subcommands.ExitSuccess - } - fmt.Fprintf(os.Stderr, "Subcommand %s not understood\n", f.Arg(0)) - default: - } - - fmt.Fprintln(os.Stderr, helpUsage) - return subcommands.ExitUsageError -} - func printCommandSummary(w io.Writer, cmd subcommands.Command) { fmt.Fprintf(w, " %-15s %s\n", cmd.Name(), cmd.Synopsis()) } @@ -344,9 +300,9 @@ func explainTopLevel(w io.Writer) { fmt.Fprintln(w) fmt.Fprintln(w, "Reference commands:") printCommandSummary(w, &versionCmd{}) - printCommandSummary(w, &helpCmd{}) + printCommandSummary(w, subcommands.HelpCommand()) printCommandSummary(w, &flagsCmd{}) - printCommandSummary(w, &commandsCmd{}) + printCommandSummary(w, subcommands.CommandsCommand()) fmt.Fprintln(w) } @@ -381,9 +337,9 @@ func main() { subcommands.DefaultCommander.Explain = explainTopLevel subcommands.DefaultCommander.ExplainCommand = explainCommand - subcommands.Register(&helpCmd{}, "") + subcommands.Register(subcommands.HelpCommand(), "") subcommands.Register(&flagsCmd{}, "") - subcommands.Register(&commandsCmd{}, "") + subcommands.Register(subcommands.CommandsCommand(), "") subcommands.Register(&downloadCmd{}, "") subcommands.Register(&progressCmd{}, "") subcommands.Register(&inspectCmd{}, "") From 8bc041ba0fa6141c10722f6b2d0f44406f4eba57 Mon Sep 17 00:00:00 2001 From: Jan Cerman Date: Fri, 15 May 2026 12:23:36 +0200 Subject: [PATCH 3/4] DOCS-2791 Remove custom flags command --- cmd/dx-download-agent/dx-download-agent.go | 50 +--------------------- 1 file changed, 2 insertions(+), 48 deletions(-) diff --git a/cmd/dx-download-agent/dx-download-agent.go b/cmd/dx-download-agent/dx-download-agent.go index 4173906..aaee1ac 100644 --- a/cmd/dx-download-agent/dx-download-agent.go +++ b/cmd/dx-download-agent/dx-download-agent.go @@ -25,7 +25,6 @@ var err error const rootDescription = "CLI tool to manage the download of files from DNAnexus" const downloadUsage = "dx-download-agent download [-num_threads=N] " -const flagsUsage = "dx-download-agent flags []" const inspectSynopsis = "Inspect files downloaded in a manifest and validate their integrity" const versionUsage = "dx-download-agent version" @@ -213,55 +212,10 @@ func (p *versionCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{ return subcommands.ExitSuccess } -type flagsCmd struct{} - -func (*flagsCmd) Name() string { return "flags" } -func (*flagsCmd) Synopsis() string { return "Describe all known top-level flags" } -func (*flagsCmd) Usage() string { return flagsUsage } -func (*flagsCmd) SetFlags(*flag.FlagSet) {} -func (*flagsCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus { - if f.NArg() > 1 { - fmt.Fprintln(os.Stderr, flagsUsage) - return subcommands.ExitUsageError - } - - if f.NArg() == 0 { - printFlags(os.Stdout, flag.CommandLine) - return subcommands.ExitSuccess - } - - cmd := findRegisteredCommand(f.Arg(0)) - if cmd == nil { - fmt.Fprintf(os.Stderr, "Subcommand %s not understood\n", f.Arg(0)) - return subcommands.ExitFailure - } - - subflags := flag.NewFlagSet(cmd.Name(), flag.PanicOnError) - cmd.SetFlags(subflags) - printFlags(os.Stdout, subflags) - return subcommands.ExitSuccess -} - func printCommandSummary(w io.Writer, cmd subcommands.Command) { fmt.Fprintf(w, " %-15s %s\n", cmd.Name(), cmd.Synopsis()) } -func visitRegisteredCommands(fn func(subcommands.Command)) { - subcommands.DefaultCommander.VisitCommands(func(_ *subcommands.CommandGroup, cmd subcommands.Command) { - fn(cmd) - }) -} - -func findRegisteredCommand(name string) subcommands.Command { - var found subcommands.Command - visitRegisteredCommands(func(cmd subcommands.Command) { - if found == nil && cmd.Name() == name { - found = cmd - } - }) - return found -} - func printFlags(w io.Writer, fs *flag.FlagSet) { fs.VisitAll(func(f *flag.Flag) { name, usage := flag.UnquoteUsage(f) @@ -301,7 +255,7 @@ func explainTopLevel(w io.Writer) { fmt.Fprintln(w, "Reference commands:") printCommandSummary(w, &versionCmd{}) printCommandSummary(w, subcommands.HelpCommand()) - printCommandSummary(w, &flagsCmd{}) + printCommandSummary(w, subcommands.FlagsCommand()) printCommandSummary(w, subcommands.CommandsCommand()) fmt.Fprintln(w) } @@ -338,7 +292,7 @@ func main() { subcommands.DefaultCommander.ExplainCommand = explainCommand subcommands.Register(subcommands.HelpCommand(), "") - subcommands.Register(&flagsCmd{}, "") + subcommands.Register(subcommands.FlagsCommand(), "") subcommands.Register(subcommands.CommandsCommand(), "") subcommands.Register(&downloadCmd{}, "") subcommands.Register(&progressCmd{}, "") From e74664ea574d1ec64ee69aa7f58bca81fb17f02c Mon Sep 17 00:00:00 2001 From: Jan Cerman Date: Fri, 15 May 2026 12:50:53 +0200 Subject: [PATCH 4/4] DOCS-2791 Mention DNAnexus Platform --- cmd/dx-download-agent/dx-download-agent.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/dx-download-agent/dx-download-agent.go b/cmd/dx-download-agent/dx-download-agent.go index aaee1ac..4b1cb4b 100644 --- a/cmd/dx-download-agent/dx-download-agent.go +++ b/cmd/dx-download-agent/dx-download-agent.go @@ -23,7 +23,7 @@ type downloadCmd struct { var err error -const rootDescription = "CLI tool to manage the download of files from DNAnexus" +const rootDescription = "CLI tool to manage the download of files from the DNAnexus Platform" const downloadUsage = "dx-download-agent download [-num_threads=N] " const inspectSynopsis = "Inspect files downloaded in a manifest and validate their integrity" const versionUsage = "dx-download-agent version"