From e0882cc4c8ccfd2e0eed5cdf81cf4796737924b3 Mon Sep 17 00:00:00 2001 From: Ayman Bagabas Date: Tue, 18 Jul 2023 07:30:51 -0700 Subject: [PATCH] feat: store repo meta data in repo directory (#338) * feat: store repo meta data in repo directory - Store auth'd user in context. - Write description, owner, and git-daemon-export-ok files. Fixes: https://github.com/charmbracelet/soft-serve/issues/255 Fixes: https://github.com/charmbracelet/soft-serve/issues/256 * fix: add tests --- server/backend/repo.go | 51 ++++++++++++++++++++++----- testscript/script_test.go | 6 ++++ testscript/testdata/mirror.txtar | 6 ++++ testscript/testdata/repo-create.txtar | 2 ++ 4 files changed, 57 insertions(+), 8 deletions(-) diff --git a/server/backend/repo.go b/server/backend/repo.go index 5f07e61f175140795062d954ce67e04897d6e06f..ebd846f4e9328ea71fa10ca1b56d592f5a62b2b4 100644 --- a/server/backend/repo.go +++ b/server/backend/repo.go @@ -5,6 +5,7 @@ import ( "context" "errors" "fmt" + "io/fs" "os" "path/filepath" "time" @@ -53,6 +54,18 @@ func (d *Backend) CreateRepository(ctx context.Context, name string, opts proto. return err } + if err := os.WriteFile(filepath.Join(rp, "description"), []byte(opts.Description), fs.ModePerm); err != nil { + d.logger.Error("failed to write description", "repo", name, "err", err) + return err + } + + if !opts.Private { + if err := os.WriteFile(filepath.Join(rp, "git-daemon-export-ok"), []byte{}, fs.ModePerm); err != nil { + d.logger.Error("failed to write git-daemon-export-ok", "repo", name, "err", err) + return err + } + } + return hooks.GenerateHooks(ctx, d.cfg, repo) }); err != nil { d.logger.Debug("failed to create repository in database", "err", err) @@ -341,29 +354,51 @@ func (d *Backend) SetHidden(ctx context.Context, name string, hidden bool) error // SetDescription sets the description of a repository. // // It implements backend.Backend. -func (d *Backend) SetDescription(ctx context.Context, repo string, desc string) error { - repo = utils.SanitizeRepo(repo) +func (d *Backend) SetDescription(ctx context.Context, name string, desc string) error { + name = utils.SanitizeRepo(name) + rp := filepath.Join(d.reposPath(), name+".git") // Delete cache - d.cache.Delete(repo) + d.cache.Delete(name) return d.db.TransactionContext(ctx, func(tx *db.Tx) error { - return d.store.SetRepoDescriptionByName(ctx, tx, repo, desc) + if err := os.WriteFile(filepath.Join(rp, "description"), []byte(desc), fs.ModePerm); err != nil { + d.logger.Error("failed to write description", "repo", name, "err", err) + return err + } + + return d.store.SetRepoDescriptionByName(ctx, tx, name, desc) }) } // SetPrivate sets the private flag of a repository. // // It implements backend.Backend. -func (d *Backend) SetPrivate(ctx context.Context, repo string, private bool) error { - repo = utils.SanitizeRepo(repo) +func (d *Backend) SetPrivate(ctx context.Context, name string, private bool) error { + name = utils.SanitizeRepo(name) + rp := filepath.Join(d.reposPath(), name+".git") // Delete cache - d.cache.Delete(repo) + d.cache.Delete(name) return db.WrapError( d.db.TransactionContext(ctx, func(tx *db.Tx) error { - return d.store.SetRepoIsPrivateByName(ctx, tx, repo, private) + fp := filepath.Join(rp, "git-daemon-export-ok") + if !private { + if err := os.WriteFile(fp, []byte{}, fs.ModePerm); err != nil { + d.logger.Error("failed to write git-daemon-export-ok", "repo", name, "err", err) + return err + } + } else { + if _, err := os.Stat(fp); err == nil { + if err := os.Remove(fp); err != nil { + d.logger.Error("failed to remove git-daemon-export-ok", "repo", name, "err", err) + return err + } + } + } + + return d.store.SetRepoIsPrivateByName(ctx, tx, name, private) }), ) } diff --git a/testscript/script_test.go b/testscript/script_test.go index 032bd47eb2be04bb400925a9f589eac1766e429a..dbb8b956f53b173c38df509acfb379bb600bca23 100644 --- a/testscript/script_test.go +++ b/testscript/script_test.go @@ -52,6 +52,7 @@ func TestScript(t *testing.T) { "usoft": cmdSoft(user1.Signer()), "git": cmdGit(key), "mkfile": cmdMkfile, + "readfile": cmdReadfile, "dos2unix": cmdDos2Unix, }, Setup: func(e *testscript.Env) error { @@ -67,6 +68,7 @@ func TestScript(t *testing.T) { statsListen := fmt.Sprintf("localhost:%d", statsPort) serverName := "Test Soft Serve" + e.Setenv("DATA_PATH", data) e.Setenv("SSH_PORT", fmt.Sprintf("%d", sshPort)) e.Setenv("ADMIN1_AUTHORIZED_KEY", admin1.AuthorizedKey()) e.Setenv("ADMIN2_AUTHORIZED_KEY", admin2.AuthorizedKey()) @@ -250,3 +252,7 @@ func check(ts *testscript.TestScript, err error, neg bool) { ts.Check(err) } } + +func cmdReadfile(ts *testscript.TestScript, neg bool, args []string) { + ts.Stdout().Write([]byte(ts.ReadFile(args[0]))) +} diff --git a/testscript/testdata/mirror.txtar b/testscript/testdata/mirror.txtar index 7dcdb6c59b40aa11edc15f6d7f90d1414f4aabc5..77b4bc281414c98620f0ba3b34cfc5e6447baa68 100644 --- a/testscript/testdata/mirror.txtar +++ b/testscript/testdata/mirror.txtar @@ -6,6 +6,9 @@ # import a repo soft repo import --mirror charmbracelet/catwalk https://github.com/charmbracelet/catwalk.git +# check empty description file +readfile $DATA_PATH/repos/charmbracelet/catwalk.git/description '' + # check repo info soft repo info charmbracelet/catwalk cmp stdout info1.txt @@ -32,6 +35,7 @@ soft repo description charmbracelet/catwalk soft repo description charmbracelet/catwalk "testing repo" soft repo description charmbracelet/catwalk stdout 'testing repo' +readfile $DATA_PATH/repos/charmbracelet/catwalk.git/description 'testing repo' # rename soft repo rename charmbracelet/catwalk charmbracelet/test @@ -41,11 +45,13 @@ stdout charmbracelet/test # TODO: shouldn't this still show the project-name? # check its not private soft repo private charmbracelet/test stdout false +exists $DATA_PATH/repos/charmbracelet/test.git/git-daemon-export-ok # make it private soft repo private charmbracelet/test true soft repo private charmbracelet/test stdout true +! exists $DATA_PATH/repos/charmbracelet/test.git/git-daemon-export-ok # check its not hidden soft repo hidden charmbracelet/test diff --git a/testscript/testdata/repo-create.txtar b/testscript/testdata/repo-create.txtar index 633142202c19dae41e0878d1431a1a66027a4e31..31c7028b8faaea888e34fad9f2b6f2211b08dfbf 100644 --- a/testscript/testdata/repo-create.txtar +++ b/testscript/testdata/repo-create.txtar @@ -9,8 +9,10 @@ soft repo hidden repo1 stdout true soft repo private repo1 stdout true +! exists $DATA_PATH/repos/repo1.git/git-daemon-export-ok soft repo description repo1 stdout 'description' +readfile $DATA_PATH/repos/repo1.git/description 'description' soft repo project-name repo1 stdout 'repo1'