This commit is contained in:
Adam Majer 2024-12-15 13:00:20 +01:00
parent 044241c71e
commit 8c6180a8cf
14 changed files with 81 additions and 47 deletions

View File

@ -32,7 +32,27 @@ import (
//go:generate mockgen -source=git_utils.go -destination=mock/git_utils.go -typed //go:generate mockgen -source=git_utils.go -destination=mock/git_utils.go -typed
type GitHandler struct { type GitSubmoduleLister interface {
GitSubmoduleList(gitPath, commitId string) (submoduleList map[string]string, err error)
GitSubmoduleCommitId(cwd, packageName, commitId string) (subCommitId string, valid bool)
}
type Git interface {
GetPath() string
CloneDevel(gitDir, outName, urlString string) error
GitBranchHead(gitDir, branchName string) (string, error)
io.Closer
GitSubmoduleLister
GitExecWithOutputOrPanic(cwd string, params ...string) string
GitExecOrPanic(cwd string, params ...string)
GitExec(cwd string, params ...string) error
GitExecWithOutput(cwd string, params ...string) (string, error)
}
type GitHandlerImpl struct {
DebugLogger bool DebugLogger bool
GitPath string GitPath string
@ -40,26 +60,36 @@ type GitHandler struct {
GitEmail string GitEmail string
} }
type GitHandlerGenerator interface { func (s *GitHandlerImpl) GetPath() string {
CreateGitHandler(git_author, email, prj_name string) (*GitHandler, error) return s.GitPath
} }
type GitHandlerImpl struct{} type GitHandlerGenerator interface {
CreateGitHandler(git_author, email, prjName string) (Git, error)
ReadExistingPath(git_author, email, gitPath string) (Git, error)
}
func (*GitHandlerImpl) CreateGitHandler(git_author, email, prj_name string) (*GitHandler, error) { type GitHandlerGeneratorImpl struct{}
var err error
git := new(GitHandler) func (s *GitHandlerGeneratorImpl) CreateGitHandler(git_author, email, prj_name string) (Git, error) {
git.GitCommiter = git_author gitPath, err := os.MkdirTemp("", prj_name)
git.GitPath, err = os.MkdirTemp("", prj_name)
if err != nil { if err != nil {
return nil, fmt.Errorf("Cannot create temp dir: %w", err) return nil, fmt.Errorf("Cannot create temp dir: %w", err)
} }
if err = os.Chmod(git.GitPath, 0700); err != nil { if err = os.Chmod(gitPath, 0700); err != nil {
return nil, fmt.Errorf("Cannot fix permissions of temp dir: %w", err) return nil, fmt.Errorf("Cannot fix permissions of temp dir: %w", err)
} }
return s.ReadExistingPath(git_author, email, gitPath)
}
func (*GitHandlerGeneratorImpl) ReadExistingPath(git_author, email, gitPath string) (Git, error) {
git := &GitHandlerImpl{
GitCommiter: git_author,
GitPath: gitPath,
}
return git, nil return git, nil
} }
@ -101,7 +131,7 @@ func (refs *GitReferences) addReference(id, branch string) {
refs.refs = append(refs.refs, GitReference{Branch: branch, Id: id}) refs.refs = append(refs.refs, GitReference{Branch: branch, Id: id})
} }
func (e *GitHandler) CloneDevel(gitDir, outName, urlString string) error { func (e *GitHandlerImpl) CloneDevel(gitDir, outName, urlString string) error {
url, err := url.Parse(urlString) url, err := url.Parse(urlString)
branch := url.Fragment branch := url.Fragment
url.Fragment = "" url.Fragment = ""
@ -122,7 +152,7 @@ func (e *GitHandler) CloneDevel(gitDir, outName, urlString string) error {
return nil return nil
} }
func (e *GitHandler) GitBranchHead(gitDir, branchName string) (string, error) { func (e *GitHandlerImpl) GitBranchHead(gitDir, branchName string) (string, error) {
id, err := e.GitExecWithOutput(gitDir, "rev-list", "-1", branchName) id, err := e.GitExecWithOutput(gitDir, "rev-list", "-1", branchName)
if err != nil { if err != nil {
return "", fmt.Errorf("Can't find default remote branch: %s", branchName) return "", fmt.Errorf("Can't find default remote branch: %s", branchName)
@ -131,7 +161,7 @@ func (e *GitHandler) GitBranchHead(gitDir, branchName string) (string, error) {
return strings.TrimSpace(id), nil return strings.TrimSpace(id), nil
} }
func (e *GitHandler) Close() error { func (e *GitHandlerImpl) Close() error {
if err := os.RemoveAll(e.GitPath); err != nil { if err := os.RemoveAll(e.GitPath); err != nil {
return err return err
} }
@ -155,7 +185,7 @@ func (h writeFunc) Close() error {
return err return err
} }
func (e *GitHandler) GitExecWithOutputOrPanic(cwd string, params ...string) string { func (e *GitHandlerImpl) GitExecWithOutputOrPanic(cwd string, params ...string) string {
out, err := e.GitExecWithOutput(cwd, params...) out, err := e.GitExecWithOutput(cwd, params...)
if err != nil { if err != nil {
log.Panicln("git command failed:", params, "@", cwd, "err:", err) log.Panicln("git command failed:", params, "@", cwd, "err:", err)
@ -163,20 +193,20 @@ func (e *GitHandler) GitExecWithOutputOrPanic(cwd string, params ...string) stri
return out return out
} }
func (e *GitHandler) GitExecOrPanic(cwd string, params ...string) { func (e *GitHandlerImpl) GitExecOrPanic(cwd string, params ...string) {
if err := e.GitExec(cwd, params...); err != nil { if err := e.GitExec(cwd, params...); err != nil {
log.Panicln("git command failed:", params, "@", cwd, "err:", err) log.Panicln("git command failed:", params, "@", cwd, "err:", err)
} }
} }
func (e *GitHandler) GitExec(cwd string, params ...string) error { func (e *GitHandlerImpl) GitExec(cwd string, params ...string) error {
_, err := e.GitExecWithOutput(cwd, params...) _, err := e.GitExecWithOutput(cwd, params...)
return err return err
} }
var ExtraGitParams []string var ExtraGitParams []string
func (e *GitHandler) GitExecWithOutput(cwd string, params ...string) (string, error) { func (e *GitHandlerImpl) GitExecWithOutput(cwd string, params ...string) (string, error) {
cmd := exec.Command("/usr/bin/git", params...) cmd := exec.Command("/usr/bin/git", params...)
cmd.Env = []string{ cmd.Env = []string{
"GIT_CEILING_DIRECTORIES=" + e.GitPath, "GIT_CEILING_DIRECTORIES=" + e.GitPath,
@ -485,7 +515,7 @@ func parseGitBlob(data <-chan byte) ([]byte, error) {
return d, nil return d, nil
} }
func (e *GitHandler) GitParseCommits(cwd string, commitIDs []string) (parsedCommits []commit, err error) { func (e *GitHandlerImpl) GitParseCommits(cwd string, commitIDs []string) (parsedCommits []commit, err error) {
var done sync.Mutex var done sync.Mutex
done.Lock() done.Lock()
@ -533,7 +563,7 @@ func (e *GitHandler) GitParseCommits(cwd string, commitIDs []string) (parsedComm
} }
// TODO: support sub-trees // TODO: support sub-trees
func (e *GitHandler) GitCatFile(cwd, commitId, filename string) (data []byte, err error) { func (e *GitHandlerImpl) GitCatFile(cwd, commitId, filename string) (data []byte, err error) {
var done sync.Mutex var done sync.Mutex
done.Lock() done.Lock()
@ -598,7 +628,7 @@ func (e *GitHandler) GitCatFile(cwd, commitId, filename string) (data []byte, er
// return (filename) -> (hash) map for all submodules // return (filename) -> (hash) map for all submodules
// TODO: recursive? map different orgs, not just assume '.' for path // TODO: recursive? map different orgs, not just assume '.' for path
func (e *GitHandler) GitSubmoduleList(cwd, commitId string) (submoduleList map[string]string, err error) { func (e *GitHandlerImpl) GitSubmoduleList(gitPath, commitId string) (submoduleList map[string]string, err error) {
var done sync.Mutex var done sync.Mutex
submoduleList = make(map[string]string) submoduleList = make(map[string]string)
@ -639,7 +669,7 @@ func (e *GitHandler) GitSubmoduleList(cwd, commitId string) (submoduleList map[s
"GIT_CEILING_DIRECTORIES=" + e.GitPath, "GIT_CEILING_DIRECTORIES=" + e.GitPath,
"GIT_CONFIG_GLOBAL=/dev/null", "GIT_CONFIG_GLOBAL=/dev/null",
} }
cmd.Dir = filepath.Join(e.GitPath, cwd) cmd.Dir = filepath.Join(e.GitPath, gitPath)
cmd.Stdout = &data_in cmd.Stdout = &data_in
cmd.Stdin = &data_out cmd.Stdin = &data_out
cmd.Stderr = writeFunc(func(data []byte) (int, error) { cmd.Stderr = writeFunc(func(data []byte) (int, error) {
@ -657,7 +687,7 @@ func (e *GitHandler) GitSubmoduleList(cwd, commitId string) (submoduleList map[s
return submoduleList, err return submoduleList, err
} }
func (e *GitHandler) GitSubmoduleCommitId(cwd, packageName, commitId string) (subCommitId string, valid bool) { func (e *GitHandlerImpl) GitSubmoduleCommitId(cwd, packageName, commitId string) (subCommitId string, valid bool) {
defer func() { defer func() {
if recover() != nil { if recover() != nil {
commitId = "" commitId = ""

View File

@ -259,7 +259,7 @@ func TestCommitTreeParsingOfHead(t *testing.T) {
t.Run("reads HEAD and parses the tree", func(t *testing.T) { t.Run("reads HEAD and parses the tree", func(t *testing.T) {
const nodejs21 = "c678c57007d496a98bec668ae38f2c26a695f94af78012f15d044ccf066ccb41" const nodejs21 = "c678c57007d496a98bec668ae38f2c26a695f94af78012f15d044ccf066ccb41"
h := GitHandler{ h := GitHandlerImpl{
GitPath: gitDir, GitPath: gitDir,
} }
id, ok := h.GitSubmoduleCommitId("", "nodejs21", commitId) id, ok := h.GitSubmoduleCommitId("", "nodejs21", commitId)
@ -272,7 +272,7 @@ func TestCommitTreeParsingOfHead(t *testing.T) {
}) })
t.Run("reads README.md", func(t *testing.T) { t.Run("reads README.md", func(t *testing.T) {
h := GitHandler{ h := GitHandlerImpl{
GitPath: gitDir, GitPath: gitDir,
} }
data, err := h.GitCatFile("", commitId, "README.md") data, err := h.GitCatFile("", commitId, "README.md")
@ -285,7 +285,7 @@ func TestCommitTreeParsingOfHead(t *testing.T) {
}) })
t.Run("read HEAD", func(t *testing.T) { t.Run("read HEAD", func(t *testing.T) {
h := GitHandler{ h := GitHandlerImpl{
GitPath: gitDir, GitPath: gitDir,
} }

View File

@ -70,7 +70,7 @@ type Gitea interface {
SetNotificationRead(notificationId int64) error SetNotificationRead(notificationId int64) error
GetOrganization(orgName string) (*models.Organization, error) GetOrganization(orgName string) (*models.Organization, error)
GetOrganizationRepositories(orgName string) ([]*models.Repository, error) GetOrganizationRepositories(orgName string) ([]*models.Repository, error)
CreateRepositoryIfNotExist(git *GitHandler, org Organization, repoName string) (*models.Repository, error) CreateRepositoryIfNotExist(git Git, org Organization, repoName string) (*models.Repository, error)
CreatePullRequestIfNotExist(repo *models.Repository, srcId, targetId, title, body string) (*models.PullRequest, error) CreatePullRequestIfNotExist(repo *models.Repository, srcId, targetId, title, body string) (*models.PullRequest, error)
RequestReviews(pr *models.PullRequest, reviewer string) ([]*models.PullReview, error) RequestReviews(pr *models.PullRequest, reviewer string) ([]*models.PullReview, error)
AddReviewComment(pr *models.PullRequest, state models.ReviewStateType, comment string) (*models.PullReview, error) AddReviewComment(pr *models.PullRequest, state models.ReviewStateType, comment string) (*models.PullReview, error)
@ -210,7 +210,7 @@ func (gitea *GiteaTransport) GetOrganizationRepositories(orgName string) ([]*mod
return repos, nil return repos, nil
} }
func (gitea *GiteaTransport) CreateRepositoryIfNotExist(git *GitHandler, org Organization, repoName string) (*models.Repository, error) { func (gitea *GiteaTransport) CreateRepositoryIfNotExist(git Git, org Organization, repoName string) (*models.Repository, error) {
repo, err := gitea.client.Repository.RepoGet( repo, err := gitea.client.Repository.RepoGet(
repository.NewRepoGetParams().WithDefaults().WithOwner(org.Username).WithRepo(repoName), repository.NewRepoGetParams().WithDefaults().WithOwner(org.Username).WithRepo(repoName),
gitea.transport.DefaultAuthentication) gitea.transport.DefaultAuthentication)
@ -239,7 +239,7 @@ func (gitea *GiteaTransport) CreateRepositoryIfNotExist(git *GitHandler, org Org
} }
// initialize repository // initialize repository
if err = os.Mkdir(filepath.Join(git.GitPath, DefaultGitPrj), 0700); err != nil { if err = os.Mkdir(filepath.Join(git.GetPath(), DefaultGitPrj), 0700); err != nil {
return nil, err return nil, err
} }
if err = git.GitExec(DefaultGitPrj, "init", "--object-format="+repo.Payload.ObjectFormatName); err != nil { if err = git.GitExec(DefaultGitPrj, "init", "--object-format="+repo.Payload.ObjectFormatName); err != nil {
@ -248,7 +248,7 @@ func (gitea *GiteaTransport) CreateRepositoryIfNotExist(git *GitHandler, org Org
if err = git.GitExec(DefaultGitPrj, "checkout", "-b", repo.Payload.DefaultBranch); err != nil { if err = git.GitExec(DefaultGitPrj, "checkout", "-b", repo.Payload.DefaultBranch); err != nil {
return nil, err return nil, err
} }
readmeFilename := filepath.Join(git.GitPath, DefaultGitPrj, "README.md") readmeFilename := filepath.Join(git.GetPath(), DefaultGitPrj, "README.md")
{ {
file, _ := os.Create(readmeFilename) file, _ := os.Create(readmeFilename)
defer file.Close() defer file.Close()

View File

@ -43,7 +43,7 @@ func TestProjctGitSync(t *testing.T) {
const LocalCMD = "---" const LocalCMD = "---"
func gitExecs(t *testing.T, git *common.GitHandler, cmds [][]string) { func gitExecs(t *testing.T, git *common.GitHandlerImpl, cmds [][]string) {
for _, cmd := range cmds { for _, cmd := range cmds {
if cmd[0] == LocalCMD { if cmd[0] == LocalCMD {
command := exec.Command(cmd[2], cmd[3:]...) command := exec.Command(cmd[2], cmd[3:]...)
@ -86,7 +86,7 @@ func commandsForPackages(dir, prefix string, startN, endN int) [][]string {
return commands return commands
} }
func setupGitForTests(t *testing.T, git *common.GitHandler) { func setupGitForTests(t *testing.T, git *common.GitHandlerImpl) {
common.ExtraGitParams = []string{ common.ExtraGitParams = []string{
"GIT_CONFIG_COUNT=1", "GIT_CONFIG_COUNT=1",
"GIT_CONFIG_KEY_0=protocol.file.allow", "GIT_CONFIG_KEY_0=protocol.file.allow",
@ -131,7 +131,7 @@ func TestUpdatePrBranch(t *testing.T) {
Pull_Request: &common.PullRequest{}, Pull_Request: &common.PullRequest{},
} }
git := &common.GitHandler{ git := &common.GitHandlerImpl{
DebugLogger: true, DebugLogger: true,
GitCommiter: "TestCommiter", GitCommiter: "TestCommiter",
GitEmail: "test@testing", GitEmail: "test@testing",
@ -167,7 +167,7 @@ func TestCreatePrBranch(t *testing.T) {
Pull_Request: &common.PullRequest{}, Pull_Request: &common.PullRequest{},
} }
git := &common.GitHandler{ git := &common.GitHandlerImpl{
DebugLogger: true, DebugLogger: true,
GitCommiter: "TestCommiter", GitCommiter: "TestCommiter",
GitEmail: "test@testing", GitEmail: "test@testing",

View File

@ -9,7 +9,7 @@ import (
) )
type PullRequestProcessor interface { type PullRequestProcessor interface {
Process(req *common.PullRequestWebhookEvent, git *common.GitHandler, config *common.AutogitConfig) error Process(req *common.PullRequestWebhookEvent, git common.Git, config *common.AutogitConfig) error
} }
type RequestProcessor struct { type RequestProcessor struct {

View File

@ -10,7 +10,7 @@ type PullRequestClosed struct {
gitea common.Gitea gitea common.Gitea
} }
func (*PullRequestClosed) Process(req *common.PullRequestWebhookEvent, git *common.GitHandler, config *common.AutogitConfig) error { func (*PullRequestClosed) Process(req *common.PullRequestWebhookEvent, git common.Git, config *common.AutogitConfig) error {
if req.Repository.Name != config.GitProjectName { if req.Repository.Name != config.GitProjectName {
return nil return nil
} }

View File

@ -47,7 +47,7 @@ func TestClosePR(t *testing.T) {
}, },
} }
git := &common.GitHandler{ git := &common.GitHandlerImpl{
GitCommiter: "tester", GitCommiter: "tester",
GitEmail: "test@suse.com", GitEmail: "test@suse.com",
} }

View File

@ -10,7 +10,7 @@ type PullRequestOpened struct {
gitea common.Gitea gitea common.Gitea
} }
func (o *PullRequestOpened) Process(req *common.PullRequestWebhookEvent, git *common.GitHandler, config *common.AutogitConfig) error { func (o *PullRequestOpened) Process(req *common.PullRequestWebhookEvent, git common.Git, config *common.AutogitConfig) error {
// requests against project are not handled here // requests against project are not handled here
if req.Repository.Name == config.GitProjectName { if req.Repository.Name == config.GitProjectName {
return nil return nil

View File

@ -49,7 +49,7 @@ func TestOpenPR(t *testing.T) {
}, },
} }
git := &common.GitHandler{ git := &common.GitHandlerImpl{
GitCommiter: "tester", GitCommiter: "tester",
GitEmail: "test@suse.com", GitEmail: "test@suse.com",
} }

View File

@ -12,7 +12,7 @@ func prGitBranchNameForPR(req *common.PullRequestWebhookEvent) string {
return fmt.Sprintf("PR_%s#%d", req.Repository.Name, req.Pull_Request.Number) return fmt.Sprintf("PR_%s#%d", req.Repository.Name, req.Pull_Request.Number)
} }
func updateOrCreatePRBranch(req *common.PullRequestWebhookEvent, git *common.GitHandler, commitMsg, branchName string) { func updateOrCreatePRBranch(req *common.PullRequestWebhookEvent, git common.Git, commitMsg, branchName string) {
common.PanicOnError(git.GitExec(common.DefaultGitPrj, "submodule", "update", "--init", "--checkout", "--depth", "1", req.Repository.Name)) common.PanicOnError(git.GitExec(common.DefaultGitPrj, "submodule", "update", "--init", "--checkout", "--depth", "1", req.Repository.Name))
common.PanicOnError(git.GitExec(path.Join(common.DefaultGitPrj, req.Repository.Name), "fetch", "--depth", "1", "origin", req.Pull_Request.Head.Sha)) common.PanicOnError(git.GitExec(path.Join(common.DefaultGitPrj, req.Repository.Name), "fetch", "--depth", "1", "origin", req.Pull_Request.Head.Sha))
common.PanicOnError(git.GitExec(path.Join(common.DefaultGitPrj, req.Repository.Name), "checkout", req.Pull_Request.Head.Sha)) common.PanicOnError(git.GitExec(path.Join(common.DefaultGitPrj, req.Repository.Name), "checkout", req.Pull_Request.Head.Sha))
@ -30,7 +30,7 @@ type PullRequestSynced struct {
gitea common.Gitea gitea common.Gitea
} }
func (o *PullRequestSynced) Process(req *common.PullRequestWebhookEvent, git *common.GitHandler, config *common.AutogitConfig) error { func (o *PullRequestSynced) Process(req *common.PullRequestWebhookEvent, git common.Git, config *common.AutogitConfig) error {
if req.Repository.Name == config.GitProjectName { if req.Repository.Name == config.GitProjectName {
return processPrjGitPullRequestSync(req) return processPrjGitPullRequestSync(req)
} }

View File

@ -65,7 +65,7 @@ func TestSyncPR(t *testing.T) {
}, },
} }
git := &common.GitHandler{ git := &common.GitHandlerImpl{
GitCommiter: "tester", GitCommiter: "tester",
GitEmail: "test@suse.com", GitEmail: "test@suse.com",
} }

View File

@ -28,7 +28,7 @@ func TestPRProcessor(t *testing.T) {
req := &RequestProcessor{ req := &RequestProcessor{
configuredRepos: testConfiguration, configuredRepos: testConfiguration,
git: &common.GitHandlerImpl{}, git: &common.GitHandlerGeneratorImpl{},
} }
event := &common.PullRequestWebhookEvent{ event := &common.PullRequestWebhookEvent{

View File

@ -33,7 +33,7 @@ type DefaultStateChecker struct {
func CreateDefaultStateChecker(checkOnStart bool, processor *RequestProcessor, gitea common.Gitea, interval time.Duration) *DefaultStateChecker { func CreateDefaultStateChecker(checkOnStart bool, processor *RequestProcessor, gitea common.Gitea, interval time.Duration) *DefaultStateChecker {
var s = &DefaultStateChecker{ var s = &DefaultStateChecker{
git: &common.GitHandlerImpl{}, git: &common.GitHandlerGeneratorImpl{},
gitea: gitea, gitea: gitea,
checkInterval: interval, checkInterval: interval,
checkOnStart: checkOnStart, checkOnStart: checkOnStart,

View File

@ -137,13 +137,17 @@ func TestRepoCheck(t *testing.T) {
} }
type testGit struct { type testGit struct {
git *common.GitHandler git *common.GitHandlerImpl
} }
func (s *testGit) CreateGitHandler(a, b, c string) (*common.GitHandler, error) { func (s *testGit) CreateGitHandler(a, b, c string) (common.Git, error) {
return s.git, nil return s.git, nil
} }
func (s *testGit) ReadExistingPath(a,b,c string) (common.Git, error) {
return nil, errors.New("should not be called")
}
func TestVerifyProjectState(t *testing.T) { func TestVerifyProjectState(t *testing.T) {
var logBuf bytes.Buffer var logBuf bytes.Buffer
oldOut := log.Writer() oldOut := log.Writer()
@ -154,7 +158,7 @@ func TestVerifyProjectState(t *testing.T) {
ctl := gomock.NewController(t) ctl := gomock.NewController(t)
gitea := mock_common.NewMockGitea(ctl) gitea := mock_common.NewMockGitea(ctl)
git := &common.GitHandler{ git := &common.GitHandlerImpl{
DebugLogger: true, DebugLogger: true,
GitCommiter: "TestCommiter", GitCommiter: "TestCommiter",
GitEmail: "test@testing", GitEmail: "test@testing",
@ -200,7 +204,7 @@ func TestVerifyProjectState(t *testing.T) {
gitea := mock_common.NewMockGitea(ctl) gitea := mock_common.NewMockGitea(ctl)
process := mock_main.NewMockPullRequestProcessor(ctl) process := mock_main.NewMockPullRequestProcessor(ctl)
git := &common.GitHandler{ git := &common.GitHandlerImpl{
DebugLogger: true, DebugLogger: true,
GitCommiter: "TestCommiter", GitCommiter: "TestCommiter",
GitEmail: "test@testing", GitEmail: "test@testing",