Loading cli.go +17 −2 Changes for cli.go: 17 added lines, 2 removed lines. Original line number Diff line number Diff line Loading @@ -163,15 +163,30 @@ func newBundlesListCmd() *cobra.Command { func newBundlesAddCmd() *cobra.Command { directory := cwd() yes := false cmd := &cobra.Command{ Use: "bundles-add <bundle-name>", Use: "bundles-add <bundle-name-or-zip>", Short: T("cmd.bundles_add.short"), Long: T("cmd.bundles_add.long"), Example: strings.TrimSpace(` ` + T("cmd.bundles_add.example_core") + ` climax bundles-add max-dev ` + T("cmd.bundles_add.example_local") + ` climax bundles-add ./local-bundle.zip ` + T("cmd.bundles_add.example_remote") + ` climax bundles-add https://example.org/local-bundle.zip ` + T("cmd.bundles_add.example_remote_yes") + ` climax bundles-add https://example.org/local-bundle.zip --yes`), Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { return runBundlesAdd(args[0], directory) return runBundlesAdd(args[0], directory, yes) }, } cmd.Flags().StringVar(&directory, "directory", directory, T("flag.common.directory")) cmd.Flags().BoolVarP(&yes, "yes", "y", false, T("flag.bundles_add.yes")) return cmd } Loading cli_commands_test.go +30 −1 Changes for cli_commands_test.go: 30 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -61,7 +61,7 @@ func TestCLICommandsExposeExpectedFlags(t *testing.T) { "info": {"directory", "json-out"}, "freeze": {"output", "directory", "debug"}, "bundles-list": {"directory"}, "bundles-add": {"directory"}, "bundles-add": {"directory", "yes"}, "bundles-remove": {"directory"}, "feed": {"directory", "verbose", "yes"}, "sync": {"directory"}, Loading Loading @@ -210,6 +210,35 @@ func TestCommandHelpShowsPositionalArgsInUsage(t *testing.T) { } } func TestBundlesAddHelpDocumentsInputKinds(t *testing.T) { previous := currentLocale setLocale(localeEN) t.Cleanup(func() { setLocale(previous) }) out := captureStdout(t, func() { root := newRootCmd() root.SetArgs([]string{"bundles-add", "--help"}) if err := root.Execute(); err != nil { t.Fatalf("help execution failed for bundles-add --help: %v", err) } }) for _, expected := range []string{ "MaX-provided bundle", "local zip bundle archive", "HTTPS URL to a remote zip bundle archive", "climax bundles-add max-dev", "climax bundles-add ./local-bundle.zip", "climax bundles-add https://example.org/local-bundle.zip --yes", } { if !strings.Contains(out, expected) { t.Fatalf("expected bundles-add help to contain %q, got:\n%s", expected, out) } } } func findSubCommand(t *testing.T, root *cobra.Command, name string) *cobra.Command { t.Helper() cmd, _, err := root.Find([]string{name}) Loading commandes.md +13 −0 Changes for commandes.md: 13 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -229,9 +229,22 @@ climax bundles-add max-dev --directory /path/to/project climax bundles-add ./local-bundle.zip ``` - Ajoute une archive de bundle distante HTTPS après confirmation : ```sh climax bundles-add https://example.org/local-bundle.zip ``` - Ajoute une archive de bundle distante HTTPS sans confirmation : ```sh climax bundles-add https://example.org/local-bundle.zip --yes ``` Options : - `--directory <path>` : dossier du projet MaX. - `--yes` : confirme l'ajout d'une archive de bundle distante HTTPS. ## bundles-remove Loading commands.go +43 −1 Changes for commands.go: 43 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -6,8 +6,10 @@ import ( "errors" "fmt" "io/fs" "net/url" "os" "os/exec" "path" "path/filepath" "sort" "strings" Loading Loading @@ -192,7 +194,7 @@ func runBundlesList(directory string) error { return nil } func runBundlesAdd(bundleName, directory string) error { func runBundlesAdd(bundleName, directory string, yes bool) error { abs, config, err := prepareProject(directory) if err != nil { return err Loading @@ -205,6 +207,30 @@ func runBundlesAdd(bundleName, directory string) error { bundleName = strings.TrimSuffix(filepath.Base(bundleName), filepath.Ext(bundleName)) } if remoteName, remoteURL, ok, err := remoteBundleArchive(bundleName); ok || err != nil { if err != nil { return err } if !yes { confirmed, err := confirm(T("question.bundle_remote_add", remoteURL), false) if err != nil { return err } if !confirmed { return nil } } current[remoteName] = bundleConfig{Name: remoteName, URL: remoteURL} config.setBundlesMap(current) if err := config.write(); err != nil { return err } if err := syncMaxInstance(abs, false); err != nil { return err } return runBundlesList(abs) } if fromArchive != "" { if !fileExists(fromArchive) { return fmt.Errorf(T("err.invalid_path"), fromArchive) Loading Loading @@ -255,6 +281,22 @@ func runBundlesAdd(bundleName, directory string) error { return runBundlesList(abs) } func remoteBundleArchive(input string) (string, string, bool, error) { trimmed := strings.TrimSpace(input) parsed, err := url.Parse(trimmed) if err != nil || parsed.Scheme == "" { return "", "", false, nil } if parsed.Scheme != "https" || parsed.Host == "" || !strings.EqualFold(path.Ext(parsed.Path), ".zip") { return "", "", true, fmt.Errorf(T("err.remote_bundle_archive"), input) } name := strings.TrimSuffix(path.Base(parsed.Path), path.Ext(parsed.Path)) if name == "" || name == "." || name == ".." { return "", "", true, fmt.Errorf(T("err.remote_bundle_archive"), input) } return name, trimmed, true, nil } func runBundlesRemove(bundleName, directory string) error { abs, config, err := prepareProject(directory) if err != nil { Loading commands.md +13 −0 Changes for commands.md: 13 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -225,9 +225,22 @@ climax bundles-add max-dev --directory /path/to/project climax bundles-add ./local-bundle.zip ``` - Add a remote HTTPS bundle archive after confirmation: ```sh climax bundles-add https://example.org/local-bundle.zip ``` - Add a remote HTTPS bundle archive without the confirmation prompt: ```sh climax bundles-add https://example.org/local-bundle.zip --yes ``` Options: - `--directory <path>`: MaX project directory. - `--yes`: confirm adding a remote HTTPS bundle archive. ## bundles-remove Loading Loading
cli.go +17 −2 Changes for cli.go: 17 added lines, 2 removed lines. Original line number Diff line number Diff line Loading @@ -163,15 +163,30 @@ func newBundlesListCmd() *cobra.Command { func newBundlesAddCmd() *cobra.Command { directory := cwd() yes := false cmd := &cobra.Command{ Use: "bundles-add <bundle-name>", Use: "bundles-add <bundle-name-or-zip>", Short: T("cmd.bundles_add.short"), Long: T("cmd.bundles_add.long"), Example: strings.TrimSpace(` ` + T("cmd.bundles_add.example_core") + ` climax bundles-add max-dev ` + T("cmd.bundles_add.example_local") + ` climax bundles-add ./local-bundle.zip ` + T("cmd.bundles_add.example_remote") + ` climax bundles-add https://example.org/local-bundle.zip ` + T("cmd.bundles_add.example_remote_yes") + ` climax bundles-add https://example.org/local-bundle.zip --yes`), Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { return runBundlesAdd(args[0], directory) return runBundlesAdd(args[0], directory, yes) }, } cmd.Flags().StringVar(&directory, "directory", directory, T("flag.common.directory")) cmd.Flags().BoolVarP(&yes, "yes", "y", false, T("flag.bundles_add.yes")) return cmd } Loading
cli_commands_test.go +30 −1 Changes for cli_commands_test.go: 30 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -61,7 +61,7 @@ func TestCLICommandsExposeExpectedFlags(t *testing.T) { "info": {"directory", "json-out"}, "freeze": {"output", "directory", "debug"}, "bundles-list": {"directory"}, "bundles-add": {"directory"}, "bundles-add": {"directory", "yes"}, "bundles-remove": {"directory"}, "feed": {"directory", "verbose", "yes"}, "sync": {"directory"}, Loading Loading @@ -210,6 +210,35 @@ func TestCommandHelpShowsPositionalArgsInUsage(t *testing.T) { } } func TestBundlesAddHelpDocumentsInputKinds(t *testing.T) { previous := currentLocale setLocale(localeEN) t.Cleanup(func() { setLocale(previous) }) out := captureStdout(t, func() { root := newRootCmd() root.SetArgs([]string{"bundles-add", "--help"}) if err := root.Execute(); err != nil { t.Fatalf("help execution failed for bundles-add --help: %v", err) } }) for _, expected := range []string{ "MaX-provided bundle", "local zip bundle archive", "HTTPS URL to a remote zip bundle archive", "climax bundles-add max-dev", "climax bundles-add ./local-bundle.zip", "climax bundles-add https://example.org/local-bundle.zip --yes", } { if !strings.Contains(out, expected) { t.Fatalf("expected bundles-add help to contain %q, got:\n%s", expected, out) } } } func findSubCommand(t *testing.T, root *cobra.Command, name string) *cobra.Command { t.Helper() cmd, _, err := root.Find([]string{name}) Loading
commandes.md +13 −0 Changes for commandes.md: 13 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -229,9 +229,22 @@ climax bundles-add max-dev --directory /path/to/project climax bundles-add ./local-bundle.zip ``` - Ajoute une archive de bundle distante HTTPS après confirmation : ```sh climax bundles-add https://example.org/local-bundle.zip ``` - Ajoute une archive de bundle distante HTTPS sans confirmation : ```sh climax bundles-add https://example.org/local-bundle.zip --yes ``` Options : - `--directory <path>` : dossier du projet MaX. - `--yes` : confirme l'ajout d'une archive de bundle distante HTTPS. ## bundles-remove Loading
commands.go +43 −1 Changes for commands.go: 43 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -6,8 +6,10 @@ import ( "errors" "fmt" "io/fs" "net/url" "os" "os/exec" "path" "path/filepath" "sort" "strings" Loading Loading @@ -192,7 +194,7 @@ func runBundlesList(directory string) error { return nil } func runBundlesAdd(bundleName, directory string) error { func runBundlesAdd(bundleName, directory string, yes bool) error { abs, config, err := prepareProject(directory) if err != nil { return err Loading @@ -205,6 +207,30 @@ func runBundlesAdd(bundleName, directory string) error { bundleName = strings.TrimSuffix(filepath.Base(bundleName), filepath.Ext(bundleName)) } if remoteName, remoteURL, ok, err := remoteBundleArchive(bundleName); ok || err != nil { if err != nil { return err } if !yes { confirmed, err := confirm(T("question.bundle_remote_add", remoteURL), false) if err != nil { return err } if !confirmed { return nil } } current[remoteName] = bundleConfig{Name: remoteName, URL: remoteURL} config.setBundlesMap(current) if err := config.write(); err != nil { return err } if err := syncMaxInstance(abs, false); err != nil { return err } return runBundlesList(abs) } if fromArchive != "" { if !fileExists(fromArchive) { return fmt.Errorf(T("err.invalid_path"), fromArchive) Loading Loading @@ -255,6 +281,22 @@ func runBundlesAdd(bundleName, directory string) error { return runBundlesList(abs) } func remoteBundleArchive(input string) (string, string, bool, error) { trimmed := strings.TrimSpace(input) parsed, err := url.Parse(trimmed) if err != nil || parsed.Scheme == "" { return "", "", false, nil } if parsed.Scheme != "https" || parsed.Host == "" || !strings.EqualFold(path.Ext(parsed.Path), ".zip") { return "", "", true, fmt.Errorf(T("err.remote_bundle_archive"), input) } name := strings.TrimSuffix(path.Base(parsed.Path), path.Ext(parsed.Path)) if name == "" || name == "." || name == ".." { return "", "", true, fmt.Errorf(T("err.remote_bundle_archive"), input) } return name, trimmed, true, nil } func runBundlesRemove(bundleName, directory string) error { abs, config, err := prepareProject(directory) if err != nil { Loading
commands.md +13 −0 Changes for commands.md: 13 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -225,9 +225,22 @@ climax bundles-add max-dev --directory /path/to/project climax bundles-add ./local-bundle.zip ``` - Add a remote HTTPS bundle archive after confirmation: ```sh climax bundles-add https://example.org/local-bundle.zip ``` - Add a remote HTTPS bundle archive without the confirmation prompt: ```sh climax bundles-add https://example.org/local-bundle.zip --yes ``` Options: - `--directory <path>`: MaX project directory. - `--yes`: confirm adding a remote HTTPS bundle archive. ## bundles-remove Loading