Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
## [Unreleased]

### Added

- `--version` global flag prints the Factorix version (#210)

### Removed

- `version` subcommand, replaced by the `--version` flag (#210)

## [0.23.0] - 2026-08-29

### Changed
Expand Down
5 changes: 3 additions & 2 deletions doc/factorix.1
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,10 @@ Suppress non-essential output.
.TP
.BR \-h ", " \-\-help
Print help information.
.TP
.B \-\-version
Print the Factorix version and exit. Root command only.
.SH COMMANDS
.SS factorix version
Display Factorix version.
.SS factorix man
Display this manual page using the system's man command.
.SS factorix path
Expand Down
2 changes: 1 addition & 1 deletion e2e/cases/config/legacy-migration/case.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
command: [version]
command: [man]
files:
- {from: files/config.rb, to: xdg-config/factorix/config.rb}
expect:
Expand Down
2 changes: 1 addition & 1 deletion e2e/cases/version/default/case.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
command: [version]
command: [--version]
expect:
status: 0
stdout:
Expand Down
16 changes: 3 additions & 13 deletions internal/cli/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ func NewRootCommand() (root *cobra.Command, reportError func(error)) {
root = &cobra.Command{
Use: "factorix",
Short: "Manage Factorio MODs, settings, and game control",
Version: Version,
SilenceUsage: true,
SilenceErrors: true,
// Ruby validates --log-level values at option-parse time for every
Expand All @@ -88,12 +89,13 @@ func NewRootCommand() (root *cobra.Command, reportError func(error)) {
},
}

root.SetVersionTemplate("{{.Version}}\n")

root.PersistentFlags().StringVarP(&c.configPath, "config-path", "c", "", "Path to configuration file")
root.PersistentFlags().StringVar(&c.logLevel, "log-level", "", "Set log level (debug, info, warn, error, fatal)")
root.PersistentFlags().BoolVarP(&c.quiet, "quiet", "q", false, "Suppress non-essential output")

root.AddCommand(
newVersionCommand(),
newPathCommand(c),
newDownloadCommand(c),
newLaunchCommand(c),
Expand Down Expand Up @@ -127,15 +129,3 @@ type bootError struct{ err error }

func (b bootError) Error() string { return b.err.Error() }
func (b bootError) Unwrap() error { return b.err }

func newVersionCommand() *cobra.Command {
return &cobra.Command{
Use: "version",
Short: "Display Factorix version",
RunE: func(cmd *cobra.Command, _ []string) error {
// Not cmd.Println, which writes to stderr by cobra default.
fmt.Fprintln(cmd.OutOrStdout(), Version)
return nil
},
}
}
22 changes: 11 additions & 11 deletions internal/cli/cli_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,36 +187,36 @@ func runCLIWithStdin(t *testing.T, stdin string, args ...string) (string, error)
return out.String(), err
}

func TestVersionCommand(t *testing.T) {
out, err := runCLI(t, "version")
func TestVersionFlag(t *testing.T) {
out, err := runCLI(t, "--version")
require.NoError(t, err)
assert.Equal(t, "dev\n", out)
}

// TestVersionCommandNeverBuildsApp guards against PersistentPostRun's
// TestVersionFlagNeverBuildsApp guards against PersistentPostRun's
// Close() forcing application construction (config load, log file
// creation) for a command that never calls c.App() itself.
func TestVersionCommandNeverBuildsApp(t *testing.T) {
// creation) for a flag that never calls c.App() itself.
func TestVersionFlagNeverBuildsApp(t *testing.T) {
s := newSandbox(t)

_, err := runCLI(t, "version")
_, err := runCLI(t, "--version")
require.NoError(t, err)

logPath := filepath.Join(s.root, "xdg-state", "factorix", "factorix.log")
_, statErr := os.Stat(logPath)
assert.ErrorIs(t, statErr, os.ErrNotExist, "version must not trigger app construction")
assert.ErrorIs(t, statErr, os.ErrNotExist, "--version must not trigger app construction")
}

// Invalid --log-level values must fail at parse time on every command,
// including ones like version that never build the application.
// including ones like man that never build the application.
func TestInvalidLogLevelRejectedAtParseTime(t *testing.T) {
_, err := runCLI(t, "version", "--log-level", "bogus")
_, err := runCLI(t, "man", "--log-level", "bogus")
require.Error(t, err)
assert.Contains(t, err.Error(), "invalid log level")

out, err := runCLI(t, "version", "--log-level", "debug")
out, err := runCLI(t, "man", "--log-level", "debug")
require.NoError(t, err)
assert.Equal(t, "dev\n", out)
assert.Contains(t, out, "factorix")
}

func TestPathCommand(t *testing.T) {
Expand Down