From 229e8eb9da694b389b5e7434ce348f1f9619401f Mon Sep 17 00:00:00 2001 From: decentral1se Date: Tue, 22 Apr 2025 08:58:35 +0200 Subject: [PATCH] feat: --ssh/--force for recipe fetch See https://git.coopcloud.tech/toolshed/organising/issues/546 --- cli/recipe/fetch.go | 66 +++++++++++++++++++++- tests/integration/recipe_fetch.bats | 88 +++++++++++++++++++++++++++++ 2 files changed, 151 insertions(+), 3 deletions(-) diff --git a/cli/recipe/fetch.go b/cli/recipe/fetch.go index b1eeb5d2..2a31e8b2 100644 --- a/cli/recipe/fetch.go +++ b/cli/recipe/fetch.go @@ -1,11 +1,15 @@ package recipe import ( + "os" + "coopcloud.tech/abra/cli/internal" "coopcloud.tech/abra/pkg/autocomplete" "coopcloud.tech/abra/pkg/formatter" "coopcloud.tech/abra/pkg/log" "coopcloud.tech/abra/pkg/recipe" + "github.com/go-git/go-git/v5" + gitCfg "github.com/go-git/go-git/v5/config" "github.com/spf13/cobra" ) @@ -13,7 +17,16 @@ var RecipeFetchCommand = &cobra.Command{ Use: "fetch [recipe | --all] [flags]", Aliases: []string{"f"}, Short: "Clone recipe(s) locally", + Long: `Using "--force/-f" Git syncs an existing recipe. It does not erase unstaged changes.`, Args: cobra.RangeArgs(0, 1), + Example: ` # fetch from recipe catalogue + abra recipe fetch gitea + + # fetch from remote recipe + abra recipe fetch git.foo.org/recipes/myrecipe + + # fetch with ssh remote for hacking + abra recipe fetch gitea --ssh`, ValidArgsFunction: func( cmd *cobra.Command, args []string, @@ -36,10 +49,39 @@ var RecipeFetchCommand = &cobra.Command{ ensureCtx := internal.GetEnsureContext() if recipeName != "" { - r := internal.ValidateRecipe(args, cmd.Name()) - if err := r.Ensure(ensureCtx); err != nil { - log.Fatal(err) + r := recipe.Get(recipeName) + if _, err := os.Stat(r.Dir); !os.IsNotExist(err) { + if !force { + log.Warnf("%s is already fetched", r.Name) + return + } } + + r = internal.ValidateRecipe(args, cmd.Name()) + + if sshRemote { + if r.SSHURL == "" { + log.Warnf("unable to discover SSH remote for %s", r.Name) + return + } + + repo, err := git.PlainOpen(r.Dir) + if err != nil { + log.Fatalf("unable to open %s: %s", r.Dir, err) + } + + if err = repo.DeleteRemote("origin"); err != nil { + log.Fatalf("unable to remove default remote in %s: %s", r.Dir, err) + } + + if _, err := repo.CreateRemote(&gitCfg.RemoteConfig{ + Name: "origin", + URLs: []string{r.SSHURL}, + }); err != nil { + log.Fatalf("unable to set SSH remote in %s: %s", r.Dir, err) + } + } + return } @@ -61,6 +103,8 @@ var RecipeFetchCommand = &cobra.Command{ var ( fetchAllRecipes bool + sshRemote bool + force bool ) func init() { @@ -71,4 +115,20 @@ func init() { false, "fetch all recipes", ) + + RecipeFetchCommand.Flags().BoolVarP( + &sshRemote, + "ssh", + "s", + false, + "automatically set ssh remote", + ) + + RecipeFetchCommand.Flags().BoolVarP( + &force, + "force", + "f", + false, + "force re-fetch", + ) } diff --git a/tests/integration/recipe_fetch.bats b/tests/integration/recipe_fetch.bats index 8e296760..c212517f 100644 --- a/tests/integration/recipe_fetch.bats +++ b/tests/integration/recipe_fetch.bats @@ -5,6 +5,16 @@ setup() { _common_setup } +teardown(){ + run rm -rf "$ABRA_DIR/recipes/matrix-synapse" + assert_success + assert_not_exists "$ABRA_DIR/recipes/$TEST_RECIPE" + + run rm -rf "$ABRA_DIR/recipes/git_coopcloud_tech_coop-cloud_matrix-synapse" + assert_success + assert_not_exists "$ABRA_DIR/recipes/git_coopcloud_tech_coop-cloud_matrix-synapse" +} + # bats test_tags=slow @test "recipe fetch all" { run rm -rf "$ABRA_DIR/recipes/matrix-synapse" @@ -35,3 +45,81 @@ setup() { run $ABRA recipe fetch matrix-synapse --all assert_failure } + +@test "do not refetch without --force" { + run $ABRA recipe fetch matrix-synapse + assert_success + assert_exists "$ABRA_DIR/recipes/matrix-synapse" + + run $ABRA recipe fetch matrix-synapse + assert_output --partial "already fetched" +} + +@test "refetch with --force" { + run $ABRA recipe fetch matrix-synapse + assert_success + assert_exists "$ABRA_DIR/recipes/matrix-synapse" + + run $ABRA recipe fetch matrix-synapse --force + assert_success + refute_output --partial "already fetched" +} + +@test "refetch with --force does not erase unstaged changes" { + run $ABRA recipe fetch matrix-synapse + assert_success + assert_exists "$ABRA_DIR/recipes/matrix-synapse" + + run bash -c "echo foo >> $ABRA_DIR/recipes/matrix-synapse/foo" + assert_success + assert_exists "$ABRA_DIR/recipes/matrix-synapse/foo" + + run $ABRA recipe fetch matrix-synapse --force + assert_success + assert_exists "$ABRA_DIR/recipes/matrix-synapse" + assert_exists "$ABRA_DIR/recipes/matrix-synapse/foo" +} + +@test "fetch with --ssh" { + run $ABRA recipe fetch matrix-synapse --ssh + assert_success + assert_exists "$ABRA_DIR/recipes/matrix-synapse" + + run git -C "$ABRA_DIR/recipes/matrix-synapse" remote -v + assert_success + assert_output --partial "ssh://" +} + +@test "re-fetch with --ssh/--force" { + run $ABRA recipe fetch matrix-synapse + assert_success + assert_exists "$ABRA_DIR/recipes/matrix-synapse" + + run git -C "$ABRA_DIR/recipes/matrix-synapse" remote -v + assert_success + assert_output --partial "https://" + + run $ABRA recipe fetch matrix-synapse --ssh --force + assert_success + assert_exists "$ABRA_DIR/recipes/matrix-synapse" + + run git -C "$ABRA_DIR/recipes/matrix-synapse" remote -v + assert_success + assert_output --partial "ssh://" +} + +@test "fetch remote recipe" { + run $ABRA recipe fetch git.coopcloud.tech/coop-cloud/matrix-synapse + assert_success + assert_exists "$ABRA_DIR/recipes/git_coopcloud_tech_coop-cloud_matrix-synapse" +} + +@test "remote recipe do not refetch without --force" { + run $ABRA recipe fetch git.coopcloud.tech/coop-cloud/matrix-synapse + assert_success + assert_exists "$ABRA_DIR/recipes/git_coopcloud_tech_coop-cloud_matrix-synapse" + + run $ABRA recipe fetch git.coopcloud.tech/coop-cloud/matrix-synapse + assert_success + assert_output --partial "already fetched" +}