From b7ec9a9ffbf6dc09d1a77e57b53443a5e1edb1c7c766a63298f64899ff1a771c Mon Sep 17 00:00:00 2001 From: Adam Majer Date: Thu, 12 Sep 2024 16:25:22 +0200 Subject: [PATCH] Handle case when branch not exist Handle default branch name in push and branch create handlers Don't panic in this case in case the project has multiple configs --- bots-common/git_utils.go | 97 ++++--------------------------------- bots-common/gitea_utils.go | 1 + prjgit-updater/README.md | 3 +- prjgit-updater/example.json | 2 +- prjgit-updater/main.go | 51 ++++++++++++------- 5 files changed, 48 insertions(+), 106 deletions(-) diff --git a/bots-common/git_utils.go b/bots-common/git_utils.go index 4144711..580c439 100644 --- a/bots-common/git_utils.go +++ b/bots-common/git_utils.go @@ -24,7 +24,6 @@ import ( "log" "os" "os/exec" - "path" "path/filepath" "strings" "sync" @@ -93,94 +92,13 @@ func (refs *GitReferences) addReference(id, branch string) { refs.refs = append(refs.refs, GitReference{Branch: branch, Id: id}) } -func processRefs(gitDir string) ([]GitReference, error) { - packedRefsPath := path.Join(gitDir, "packed-refs") - stat, err := os.Stat(packedRefsPath) - if err != nil { - return nil, err - } - - if stat.Size() > 10000 || stat.IsDir() { - return nil, fmt.Errorf("Funny business with 'packed-refs' in '%s'", gitDir) - } - - data, err := os.ReadFile(packedRefsPath) - if err != nil { - return nil, err - } - - var references GitReferences - for _, line := range strings.Split(string(data), "\n") { - if len(line) < 1 || line[0] == '#' { - continue - } - - splitLine := strings.Split(line, " ") - if len(splitLine) != 2 { - return nil, fmt.Errorf("Unexpected packaged-refs entry '%#v' in '%s'", splitLine, packedRefsPath) - } - id, ref := splitLine[0], splitLine[1] - const remoteRefPrefix = "refs/remotes/origin/" - if ref[0:len(remoteRefPrefix)] != remoteRefPrefix { - continue - } - - references.addReference(id, ref[len(remoteRefPrefix):]) - } - - return references.refs, nil -} - -func findGitDir(p string) (string, error) { - gitFile := path.Join(p, ".git") - stat, err := os.Stat(gitFile) - if err != nil { - return "", err - } - - if stat.IsDir() { - return path.Join(p, ".git"), nil - } - - data, err := os.ReadFile(gitFile) - if err != nil { - return "", err - } - - for _, line := range strings.Split(string(data), "\n") { - refs := strings.Split(line, ":") - if len(refs) != 2 { - return "", fmt.Errorf("Unknown format of .git file: '%s'\n", line) - } - - if refs[0] != "gitdir" { - return "", fmt.Errorf("Unknown header of .git file: '%s'\n", refs[0]) - } - - return path.Join(p, strings.TrimSpace(refs[1])), nil - } - - return "", fmt.Errorf("Can't find git subdirectory in '%s'", p) -} - func (e *GitHandler) GitBranchHead(gitDir, branchName string) (string, error) { - path, err := findGitDir(path.Join(e.GitPath, gitDir)) + id, err := e.GitExecWithOutput(gitDir, "rev-list", "-1", branchName) if err != nil { - return "", fmt.Errorf("Error identifying gitdir in `%s`: %w", gitDir, err) + return "", fmt.Errorf("Can't find default remote branch: %s", branchName) } - refs, err := processRefs(path) - if err != nil { - return "", fmt.Errorf("Error finding branches (%s): %w\n", branchName, err) - } - - for _, ref := range refs { - if ref.Branch == branchName { - return ref.Id, nil - } - } - - return "", fmt.Errorf("Can't find default remote branch: %s", branchName) + return strings.TrimSpace(id), nil } func (e *GitHandler) Close() error { @@ -208,6 +126,11 @@ func (h writeFunc) Close() error { } func (e *GitHandler) GitExec(cwd string, params ...string) error { + _, err := e.GitExecWithOutput(cwd, params...) + return err +} + +func (e *GitHandler) GitExecWithOutput(cwd string, params ...string) (string, error) { cmd := exec.Command("/usr/bin/git", params...) cmd.Env = []string{ "GIT_CEILING_DIRECTORIES=" + e.GitPath, @@ -232,10 +155,10 @@ func (e *GitHandler) GitExec(cwd string, params ...string) error { if e.DebugLogger { log.Printf(" *** error: %v\n", err) } - return fmt.Errorf("error executing: git %#v \n%s\n err: %w", cmd.Args, out, err) + return "", fmt.Errorf("error executing: git %#v \n%s\n err: %w", cmd.Args, out, err) } - return nil + return string(out), nil } type ChanIO struct { diff --git a/bots-common/gitea_utils.go b/bots-common/gitea_utils.go index a30eb32..40ff94d 100644 --- a/bots-common/gitea_utils.go +++ b/bots-common/gitea_utils.go @@ -485,3 +485,4 @@ func (gitea *GiteaTransport) GetRecentCommits(org, repo, branch string, commitNo return commits.Payload, nil } + diff --git a/prjgit-updater/README.md b/prjgit-updater/README.md index d96c94f..8ad20d4 100644 --- a/prjgit-updater/README.md +++ b/prjgit-updater/README.md @@ -11,8 +11,9 @@ Areas of responsibility * on package removal, removes the submodule 2. Assumes: - * config.GitProjectName == project name (default: _ObsPrj) + * config.GitProjectName == project name (default: `_ObsPrj`) * Other repositories == packages (similar to OBS project) + * config.Branch == "" => default branch from Gitea Target Usage diff --git a/prjgit-updater/example.json b/prjgit-updater/example.json index 620cdc4..ae9a732 100644 --- a/prjgit-updater/example.json +++ b/prjgit-updater/example.json @@ -6,7 +6,7 @@ }, { "Workflows": ["direct"], - "Organization": "autogits", + "Organization": "autogits", "GitProjectName": "HiddenPrj", "Branch": "hidden" } diff --git a/prjgit-updater/main.go b/prjgit-updater/main.go index 92e45eb..4ecc7f2 100644 --- a/prjgit-updater/main.go +++ b/prjgit-updater/main.go @@ -88,29 +88,39 @@ func processConfiguredRepositoryAction(h *common.RequestHandler, action *common. defer git.Close() } + if len(config.Branch) == 0 { + config.Branch = action.Repository.Default_Branch + } + prjGitRepo, err := gitea.CreateRepositoryIfNotExist(git, *action.Organization, prjgit) if err != nil { return fmt.Errorf("Error accessing/creating prjgit: %s err: %w", prjgit, err) } - common.PanicOnError(git.GitExec("", "clone", "--depth", "1", prjGitRepo.SSHURL, common.DefaultGitPrj)) + common.PanicOnError(git.GitExec("", "clone", "--depth", "1", prjGitRepo.SSHURL, prjgit)) switch action.Action { case "created": - common.PanicOnError(git.GitExec(common.DefaultGitPrj, "submodule", "--quiet", "add", "--depth", "1", action.Repository.Clone_Url)) - common.PanicOnError(git.GitExec(common.DefaultGitPrj, "commit", "-m", "Automatic package inclusion via Direct Workflow")) - common.PanicOnError(git.GitExec(common.DefaultGitPrj, "push")) + common.PanicOnError(git.GitExec(prjgit, "submodule", "--quiet", "add", "--depth", "1", action.Repository.Clone_Url, action.Repository.Name)) + if _, err := git.GitBranchHead(path.Join(prjgit, action.Repository.Name), config.Branch); err != nil { + if err := git.GitExec(path.Join(prjgit, action.Repository.Name), "fetch", "--depth", "1", "origin", config.Branch+":"+config.Branch); err != nil { + return fmt.Errorf("error fetching branch %s. ignoring as non-existent. err: %w", config.Branch, err) // no branch? so ignore repo here + } + } + common.PanicOnError(git.GitExec(path.Join(prjgit, action.Repository.Name), "checkout", config.Branch)) + common.PanicOnError(git.GitExec(prjgit, "commit", "-m", "Automatic package inclusion via Direct Workflow")) + common.PanicOnError(git.GitExec(prjgit, "push")) case "deleted": - if stat, err := os.Stat(filepath.Join(git.GitPath, common.DefaultGitPrj, action.Repository.Name)); err != nil || !stat.IsDir() { + if stat, err := os.Stat(filepath.Join(git.GitPath, prjgit, action.Repository.Name)); err != nil || !stat.IsDir() { if git.DebugLogger { h.StdLogger.Printf("delete event for %s -- not in project. Ignoring\n", action.Repository.Name) } return nil } - common.PanicOnError(git.GitExec(common.DefaultGitPrj, "rm", action.Repository.Name)) - common.PanicOnError(git.GitExec(common.DefaultGitPrj, "commit", "-m", "Automatic package removal via Direct Workflow")) - common.PanicOnError(git.GitExec(common.DefaultGitPrj, "push")) + common.PanicOnError(git.GitExec(prjgit, "rm", action.Repository.Name)) + common.PanicOnError(git.GitExec(prjgit, "commit", "-m", "Automatic package removal via Direct Workflow")) + common.PanicOnError(git.GitExec(prjgit, "push")) default: return fmt.Errorf("%s: %s", "Unknown action type", action.Action) @@ -151,27 +161,34 @@ func processConfiguredPushAction(h *common.RequestHandler, action *common.PushWe defer git.Close() } + if len(config.Branch) == 0 { + config.Branch = action.Repository.Default_Branch + } + prjGitRepo, err := gitea.CreateRepositoryIfNotExist(git, *action.Repository.Owner, prjgit) if err != nil { return fmt.Errorf("Error accessing/creating prjgit: %s err: %w", prjgit, err) } - common.PanicOnError(git.GitExec("", "clone", "--depth", "1", prjGitRepo.SSHURL, common.DefaultGitPrj)) - if stat, err := os.Stat(filepath.Join(git.GitPath, common.DefaultGitPrj, action.Repository.Name)); err != nil || !stat.IsDir() { + common.PanicOnError(git.GitExec("", "clone", "--depth", "1", prjGitRepo.SSHURL, prjgit)) + if stat, err := os.Stat(filepath.Join(git.GitPath, prjgit, action.Repository.Name)); err != nil || !stat.IsDir() { if git.DebugLogger { - h.StdLogger.Printf("Pushed to package that is not part of the project. Ignoring: %v\n", err) + h.StdLogger.Println("Pushed to package that is not part of the project. Ignoring:", err) } return nil } - common.PanicOnError(git.GitExec(common.DefaultGitPrj, "submodule", "update", "--init", "--depth", "1", "--checkout", action.Repository.Name)) - id, err := git.GitBranchHead(filepath.Join(common.DefaultGitPrj, action.Repository.Name), action.Repository.Default_Branch) + common.PanicOnError(git.GitExec(prjgit, "submodule", "update", "--init", "--depth", "1", "--checkout", action.Repository.Name)) + if err := git.GitExec(filepath.Join(prjgit, action.Repository.Name), "fetch", "--depth", "1", "origin", config.Branch+":"+config.Branch); err != nil { + return fmt.Errorf("error fetching branch %s. ignoring as non-existent. err: %w", config.Branch, err) // no branch? so ignore repo here + } + id, err := git.GitBranchHead(filepath.Join(prjgit, action.Repository.Name), config.Branch) common.PanicOnError(err) for _, commitId := range action.Commits { if commitId.Id == id { - common.PanicOnError(git.GitExec(filepath.Join(common.DefaultGitPrj, action.Repository.Name), "fetch", "--depth", "1", "origin", id)) - common.PanicOnError(git.GitExec(filepath.Join(common.DefaultGitPrj, action.Repository.Name), "checkout", id)) - common.PanicOnError(git.GitExec(common.DefaultGitPrj, "commit", "-a", "-m", "Automatic update via push via Direct Workflow")) - common.PanicOnError(git.GitExec(common.DefaultGitPrj, "push")) + common.PanicOnError(git.GitExec(filepath.Join(prjgit, action.Repository.Name), "fetch", "--depth", "1", "origin", id)) + common.PanicOnError(git.GitExec(filepath.Join(prjgit, action.Repository.Name), "checkout", id)) + common.PanicOnError(git.GitExec(prjgit, "commit", "-a", "-m", "Automatic update via push via Direct Workflow")) + common.PanicOnError(git.GitExec(prjgit, "push")) return nil } }