From faa5ca8fab23176d390e9522f1485d467851545b Mon Sep 17 00:00:00 2001 From: Runxi Yu Date: Sun, 6 Apr 2025 01:55:21 +0800 Subject: Move stuff into internal/unsorted --- internal/unsorted/git_misc.go | 87 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 internal/unsorted/git_misc.go (limited to 'internal/unsorted/git_misc.go') diff --git a/internal/unsorted/git_misc.go b/internal/unsorted/git_misc.go new file mode 100644 index 0000000..ceda3d1 --- /dev/null +++ b/internal/unsorted/git_misc.go @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: AGPL-3.0-only +// SPDX-FileCopyrightText: Copyright (c) 2025 Runxi Yu + +package unsorted + +import ( + "context" + "errors" + "io" + "iter" + + "github.com/go-git/go-git/v5" + "github.com/go-git/go-git/v5/plumbing/object" + "github.com/jackc/pgx/v5/pgtype" +) + +// openRepo opens a git repository by group and repo name. +// +// TODO: This should be deprecated in favor of doing it in the relevant +// request/router context in the future, as it cannot cover the nuance of +// fields needed. +func (s *Server) openRepo(ctx context.Context, groupPath []string, repoName string) (repo *git.Repository, description string, repoID int, fsPath string, err error) { + err = s.database.QueryRow(ctx, ` +WITH RECURSIVE group_path_cte AS ( + -- Start: match the first name in the path where parent_group IS NULL + SELECT + id, + parent_group, + name, + 1 AS depth + FROM groups + WHERE name = ($1::text[])[1] + AND parent_group IS NULL + + UNION ALL + + -- Recurse: join next segment of the path + SELECT + g.id, + g.parent_group, + g.name, + group_path_cte.depth + 1 + FROM groups g + JOIN group_path_cte ON g.parent_group = group_path_cte.id + WHERE g.name = ($1::text[])[group_path_cte.depth + 1] + AND group_path_cte.depth + 1 <= cardinality($1::text[]) +) +SELECT + r.filesystem_path, + COALESCE(r.description, ''), + r.id +FROM group_path_cte g +JOIN repos r ON r.group_id = g.id +WHERE g.depth = cardinality($1::text[]) + AND r.name = $2 + `, pgtype.FlatArray[string](groupPath), repoName).Scan(&fsPath, &description, &repoID) + if err != nil { + return + } + + repo, err = git.PlainOpen(fsPath) + return +} + +// commitIterSeqErr creates an [iter.Seq[*object.Commit]] from an +// [object.CommitIter], and additionally returns a pointer to error. +// The pointer to error is guaranteed to be populated with either nil or the +// error returned by the commit iterator after the returned iterator is +// finished. +func commitIterSeqErr(commitIter object.CommitIter) (iter.Seq[*object.Commit], *error) { + var err error + return func(yield func(*object.Commit) bool) { + for { + commit, err2 := commitIter.Next() + if err2 != nil { + if errors.Is(err2, io.EOF) { + return + } + err = err2 + return + } + if !yield(commit) { + return + } + } + }, &err +} -- cgit v1.2.3