diff --git a/cmd/publisher/commands/requirements.go b/cmd/publisher/commands/requirements.go index 6acfe5f4f..c12c37ce7 100644 --- a/cmd/publisher/commands/requirements.go +++ b/cmd/publisher/commands/requirements.go @@ -2,51 +2,7 @@ package commands // Copyright (C) 2023 by Posit Software, PBC. -import ( - "errors" - "fmt" - "os" - - "github.com/rstudio/connect-client/internal/cli_types" - "github.com/rstudio/connect-client/internal/inspect" - "github.com/rstudio/connect-client/internal/util" -) - -type RequirementsCommand struct { - Path util.Path `help:"Path to project directory containing files to publish." arg:"" default:"."` - Python util.Path `help:"Path to Python interpreter for this content, if it is Python-based. Default is the Python 3 on your PATH."` - Output string `short:"o" help:"Name of output file." default:"requirements.txt"` - Force bool `short:"f" help:"Overwrite the output file, if it exists."` -} - -var errRequirementsFileExists = errors.New("the requirements file already exists; use the -f option to overwrite it") - -func (cmd *RequirementsCommand) Run(args *cli_types.CommonArgs, ctx *cli_types.CLIContext) error { - absPath, err := cmd.Path.Abs() - if err != nil { - return err - } - reqPath := absPath.Join(cmd.Output) - exists, err := reqPath.Exists() - if err != nil { - return err - } - if exists && !cmd.Force { - return errRequirementsFileExists - } - inspector := inspect.NewPythonInspector(cmd.Python, ctx.Logger) - err = inspector.CreateRequirementsFile(absPath, reqPath) - if err != nil { - return err - } - fmt.Fprintf(os.Stderr, "Wrote file %s:\n", cmd.Output) - content, err := reqPath.ReadFile() - if err != nil { - return err - } - _, err = os.Stdout.Write(content) - if err != nil { - return err - } - return nil +type RequirementsCommands struct { + Create CreateRequirementsCommand `kong:"cmd" help:"Create a requirements.txt file from your project's dependencies and a Python installation containing the packages."` + Show ShowRequirementsCommand `kong:"cmd" help:"Show your project's dependencies."` } diff --git a/cmd/publisher/commands/requirements_create.go b/cmd/publisher/commands/requirements_create.go new file mode 100644 index 000000000..a945a8024 --- /dev/null +++ b/cmd/publisher/commands/requirements_create.go @@ -0,0 +1,52 @@ +package commands + +// Copyright (C) 2023 by Posit Software, PBC. + +import ( + "errors" + "fmt" + "os" + + "github.com/rstudio/connect-client/internal/cli_types" + "github.com/rstudio/connect-client/internal/inspect" + "github.com/rstudio/connect-client/internal/util" +) + +type CreateRequirementsCommand struct { + Path util.Path `help:"Path to project directory containing files to publish." arg:"" default:"."` + Python util.Path `help:"Path to Python interpreter for this content, if it is Python-based. Default is the Python 3 on your PATH."` + Output string `short:"o" help:"Name of output file." default:"requirements.txt"` + Force bool `short:"f" help:"Overwrite the output file, if it exists."` +} + +var errRequirementsFileExists = errors.New("the requirements file already exists; use the -f option to overwrite it") + +func (cmd *CreateRequirementsCommand) Run(args *cli_types.CommonArgs, ctx *cli_types.CLIContext) error { + absPath, err := cmd.Path.Abs() + if err != nil { + return err + } + reqPath := absPath.Join(cmd.Output) + exists, err := reqPath.Exists() + if err != nil { + return err + } + if exists && !cmd.Force { + return errRequirementsFileExists + } + inspector := inspect.NewPythonInspector(cmd.Python, ctx.Logger) + err = inspector.CreateRequirementsFile(absPath, reqPath) + if err != nil { + return err + } + fmt.Fprintf(os.Stderr, "Wrote file %s:\n", cmd.Output) + content, err := reqPath.ReadFile() + if err != nil { + return err + } + _, err = os.Stdout.Write(content) + if err != nil { + return err + } + return nil +} diff --git a/cmd/publisher/commands/requirements_show.go b/cmd/publisher/commands/requirements_show.go new file mode 100644 index 000000000..306234201 --- /dev/null +++ b/cmd/publisher/commands/requirements_show.go @@ -0,0 +1,33 @@ +package commands + +// Copyright (C) 2023 by Posit Software, PBC. + +import ( + "fmt" + "strings" + + "github.com/rstudio/connect-client/internal/cli_types" + "github.com/rstudio/connect-client/internal/inspect" + "github.com/rstudio/connect-client/internal/util" +) + +type ShowRequirementsCommand struct { + Path util.Path `help:"Path to project directory containing files to publish." arg:"" default:"."` + Python util.Path `help:"Path to Python interpreter for this content, if it is Python-based. Default is the Python 3 on your PATH."` +} + +func (cmd *ShowRequirementsCommand) Run(args *cli_types.CommonArgs, ctx *cli_types.CLIContext) error { + absPath, err := cmd.Path.Abs() + if err != nil { + return err + } + inspector := inspect.NewPythonInspector(cmd.Python, ctx.Logger) + reqs, pythonExecutable, err := inspector.GetRequirements(absPath) + if err != nil { + return err + } + fmt.Println("# Project dependencies for", absPath) + fmt.Println("# Using package information from", pythonExecutable) + fmt.Println(strings.Join(reqs, "\n")) + return nil +} diff --git a/cmd/publisher/main.go b/cmd/publisher/main.go index e5fa11e27..cadd53e30 100644 --- a/cmd/publisher/main.go +++ b/cmd/publisher/main.go @@ -22,12 +22,12 @@ type cliSpec struct { cli_types.CommonArgs commands.AccountCommands `group:"Accounts"` - Init commands.InitCommand `kong:"cmd" help:"Create a configuration file based on the contents of the project directory."` - Deploy commands.DeployCmd `kong:"cmd" help:"Create a new deployment."` - Redeploy commands.RedeployCmd `kong:"cmd" help:"Update an existing deployment."` - UI commands.UICmd `kong:"cmd" help:"Serve the publisher UI."` - Requirements commands.RequirementsCommand `kong:"cmd" help:"Create a Python requirements.txt file."` - Version commands.VersionCmd `kong:"cmd" help:"Show the client software version and exit."` + Init commands.InitCommand `kong:"cmd" help:"Create a configuration file based on the contents of the project directory."` + Deploy commands.DeployCmd `kong:"cmd" help:"Create a new deployment."` + Redeploy commands.RedeployCmd `kong:"cmd" help:"Update an existing deployment."` + UI commands.UICmd `kong:"cmd" help:"Serve the publisher UI."` + Requirements commands.RequirementsCommands `kong:"cmd" help:"Create a Python requirements.txt file."` + Version commands.VersionCmd `kong:"cmd" help:"Show the client software version and exit."` } func logVersion(log logging.Logger) {