This commit is contained in:
Adam Majer 2024-07-15 19:19:34 +02:00
parent 3c4f1d103c
commit fb8e5d5e03
3 changed files with 112 additions and 33 deletions

View File

@ -251,12 +251,26 @@ type tree_entry struct {
name string
mode int
hash string
size int
}
type tree struct {
items []tree_entry
}
func (t *tree_entry) isSubmodule() bool {
return (t.mode & 0170000) == 0160000
}
func (t *tree_entry) isTree() bool {
return (t.mode & 0170000) == 0040000
}
func (t *tree_entry) isBlob() bool {
return !t.isTree() && !t.isSubmodule()
}
func parseGitMsg(data <-chan byte) (gitMsg, error) {
var id []byte = make([]byte, 64)
var msgType []byte = make([]byte, 16)
@ -295,7 +309,7 @@ func parseGitMsg(data <-chan byte) (gitMsg, error) {
if c >= '0' && c <= '9' {
size = size*10 + (int(c) - '0')
} else {
return gitMsg{}, errors.New("Invalid character during commit size parse")
return gitMsg{}, fmt.Errorf("Invalid character during object size parse: '%c'", c)
}
}
@ -366,31 +380,65 @@ func parseGitCommit(data <-chan byte) (commit, error) {
return c, err
}
func parseTreeEntry(data <-chan byte) (tree_entry, error) {
func parseTreeEntry(data <-chan byte, hashLen int) (tree_entry, error) {
var e tree_entry
for c:=<-data; c != ' '; c=<-data {
e.mode = e.mode * 8 + (c - '0')
for c := <-data; c != ' '; c = <-data {
e.mode = e.mode*8 + int(c-'0')
e.size++
}
for c:=<-data; c != '\x00'; c=<-data {
e.name = append(e.name, c)
e.size++
name := make([]byte, 0, 128)
for c := <-data; c != '\x00'; c = <-data {
name = append(name, c)
e.size++
}
e.size++
e.name = string(name)
const hexBinToAscii = "0123456789abcdef"
hash := make([]byte, 0, hashLen*2)
for range hashLen {
c := <-data
hash = append(hash, hexBinToAscii[((c&0xF0)>>4)], hexBinToAscii[c&0xF])
}
e.hash = string(hash)
e.size += hashLen
return e, nil
}
func parseGitTree(data <-chan byte) (tree, error) {
hdr, err := parseGitMsg(data)
if err != nil {
return tree{}, err
}
// max capacity to length of hash
t := tree{items: make([]tree_entry, 0, hdr.size/len(hdr.hash))}
for parsedLen := 0; parsedLen+1 < hdr.size; {
entry, err := parseTreeEntry(data, len(hdr.hash)/2)
if err != nil {
return tree{}, nil
}
t.items = append(t.items, entry)
parsedLen += entry.size
}
return t, nil
}
func (e *RequestHandler) GitSubmoduleCommitId(cwd, packageName, headId string) (string, bool) {
func (e *RequestHandler) GitSubmoduleCommitId(cwd, packageName, commitId string) (string, bool) {
if e.Error != nil {
return "", false
}
data_in, data_out := ChanIO{make(chan byte, 256)}, ChanIO{make(chan byte, 70)}
var commitId string
var subCommitId string
var foundLock sync.Mutex
foundLock.Lock()
@ -399,7 +447,8 @@ func (e *RequestHandler) GitSubmoduleCommitId(cwd, packageName, headId string) (
defer foundLock.Unlock()
defer close(data_out.ch)
data_out.Write([]byte("HEAD\n"))
data_out.Write([]byte(commitId))
data_out.ch <- '\x00'
c, err := parseGitCommit(data_in.ch)
if err != nil {
e.Error = err
@ -407,7 +456,7 @@ func (e *RequestHandler) GitSubmoduleCommitId(cwd, packageName, headId string) (
return
}
data_out.Write([]byte(c.Tree))
data_out.ch <- '\n'
data_out.ch <- '\x00'
tree, err := parseGitTree(data_in.ch)
if err != nil {
@ -417,8 +466,8 @@ func (e *RequestHandler) GitSubmoduleCommitId(cwd, packageName, headId string) (
}
for _, te := range tree.items {
if te.name == packageName {
commitId = te.hash
if te.name == packageName && te.isSubmodule() {
subCommitId = te.hash
return
}
}
@ -431,5 +480,5 @@ func (e *RequestHandler) GitSubmoduleCommitId(cwd, packageName, headId string) (
e.Log("command run: %v", cmd.Run())
foundLock.Lock()
return commitId, len(commitId) == len(headId)
return subCommitId, len(subCommitId) == len(commitId)
}

View File

@ -84,13 +84,13 @@ func TestGitMsgParsing(t *testing.T) {
func TestGitCommitParsing(t *testing.T) {
t.Run("parse valid commit message", func(t *testing.T) {
const commitData = "f40888ea4515fe2e8eea617a16f5f50a45f652d894de3ad181d58de3aafb8f99 commit 254\000"+
`tree e20033df9f18780756ba4a96dbc7eb1a626253961039cb674156f266ba7a4e53
const commitData = "f40888ea4515fe2e8eea617a16f5f50a45f652d894de3ad181d58de3aafb8f99 commit 254\000" +
`tree e20033df9f18780756ba4a96dbc7eb1a626253961039cb674156f266ba7a4e53
parent 429cc2fe02170ca5668f0461928c7e7430c7a17cd64ac298286d7162572a7703
author Adam Majer <amajer@suse.com> 1720709149 +0200
committer Adam Majer <amajer@suse.com> 1720709149 +0200
.`+"\000"
.` + "\000"
ch := make(chan byte, 5000)
for _, b := range []byte(commitData) {
ch <- b
@ -112,7 +112,7 @@ committer Adam Majer <amajer@suse.com> 1720709149 +0200
t.Run("parse multiline headers", func(t *testing.T) {
const commitData = "cae5831ab48470ff060a5aaa12eb6e5a7acaf91e commit 1492\x00" +
`tree 1f9c8fe8099615d6d3921528402ac53f09213b02
`tree 1f9c8fe8099615d6d3921528402ac53f09213b02
parent e08a654fae0ecc91678819e0b62a2e014bad3339
author Yagiz Nizipli <yagiz@nizipli.com> 1720967314 -0400
committer GitHub <noreply@github.com> 1720967314 +0200
@ -165,7 +165,7 @@ Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com>` + "\x00"
})
t.Run("parse tree object", func(t *testing.T) {
const treeData = "\x31\x31\x34\x31\x32\x39\x32\x30\x34\x38\x36\x38\x62\x30\x38\x65\x35\x36\x65\x39\x61\x66\x30\x64\x32\x39\x66\x37\x38\x36\x33\x34\x34\x37\x64\x32\x31\x36\x61\x62\x31\x35\x37\x32\x31\x30\x66\x65\x64\x37\x63\x36\x32\x37\x31\x64\x64\x35\x31\x30\x66\x35\x36\x62\x20\x74\x72\x65\x65\x20\x32\x30\x35\x0a\x34\x30\x30\x30\x30\x20\x62\x6f\x74\x73\x2d\x63\x6f\x6d\x6d\x6f\x6e\x00\x81\xac\x2e\xbd\x40\x77\xcb\x63\xbf\x40\x8c\xf8\xbc\xcd\x6f\xbe\x06\x0d\xfa\xd7\x45\x16\x85\x4f\xd0\xa0\x67\xb4\x21\x39\x11\x84\x34\x30\x30\x30\x30\x20\x6f\x62\x73\x2d\x73\x74\x61\x67\x69\x6e\x67\x2d\x62\x6f\x74\x00\x79\x77\x8b\x28\x7d\x37\x10\x59\xb9\x71\x28\x36\xed\x20\x31\x5f\xfb\xe1\xed\xb5\xba\x4f\x5e\xbb\x65\x65\x68\x23\x77\x32\x58\xfe\x34\x30\x30\x30\x30\x20\x70\x72\x2d\x72\x65\x76\x69\x65\x77\x00\x31\x6a\x4a\x1e\x67\xbb\xdd\x21\x89\xa4\x46\xf7\x62\x75\x60\x84\x73\x28\x6f\xb7\x3c\x51\x7f\x4a\x14\xa2\x28\xf9\x6e\x0b\xa7\x95\x34\x30\x30\x30\x30\x20\x70\x72\x6a\x67\x69\x74\x2d\x75\x70\x64\x61\x74\x65\x72\x00\xb4\x0b\x1c\xf5\xfb\xec\x9a\xb2\x9f\x48\x3e\x21\x18\x0d\x51\xb7\x98\x6e\x21\x99\x74\x84\x67\x71\x41\x24\x42\xfc\xc9\x04\x12\x99\x0a"
const treeData = "\x31\x61\x30\x35\x64\x62\x37\x33\x36\x39\x33\x37\x34\x33\x30\x65\x31\x38\x64\x66\x34\x33\x61\x32\x37\x61\x39\x38\x30\x30\x31\x30\x31\x32\x65\x31\x65\x64\x32\x30\x34\x38\x32\x39\x38\x36\x37\x31\x32\x38\x66\x32\x63\x65\x38\x34\x30\x36\x62\x35\x63\x66\x63\x39\x20\x74\x72\x65\x65\x20\x32\x30\x35\x00\x34\x30\x30\x30\x30\x20\x62\x6f\x74\x73\x2d\x63\x6f\x6d\x6d\x6f\x6e\x00\x93\x17\xaa\x47\xf6\xea\x37\xe8\xbc\xe2\x80\x77\x57\x90\xf4\xa8\x01\xd7\xe3\x70\x2f\x84\xfb\xe1\xb0\x0e\x4a\x2c\x1c\x75\x2c\x2b\x34\x30\x30\x30\x30\x20\x6f\x62\x73\x2d\x73\x74\x61\x67\x69\x6e\x67\x2d\x62\x6f\x74\x00\x79\x77\x8b\x28\x7d\x37\x10\x59\xb9\x71\x28\x36\xed\x20\x31\x5f\xfb\xe1\xed\xb5\xba\x4f\x5e\xbb\x65\x65\x68\x23\x77\x32\x58\xfe\x34\x30\x30\x30\x30\x20\x70\x72\x2d\x72\x65\x76\x69\x65\x77\x00\x36\x0d\x45\xcb\x76\xb8\x93\xb3\x21\xba\xfa\xd5\x00\x9d\xfc\x59\xab\x88\xc1\x3c\x81\xcb\x48\x5a\xe0\x29\x29\x0f\xe3\x6b\x3c\x5e\x34\x30\x30\x30\x30\x20\x70\x72\x6a\x67\x69\x74\x2d\x75\x70\x64\x61\x74\x65\x72\x00\xb4\x0b\x1c\xf5\xfb\xec\x9a\xb2\x9f\x48\x3e\x21\x18\x0d\x51\xb7\x98\x6e\x21\x99\x74\x84\x67\x71\x41\x24\x42\xfc\xc9\x04\x12\x99\x00"
ch := make(chan byte, 1000)
for _, b := range []byte(treeData) {
@ -179,9 +179,11 @@ Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com>` + "\x00"
}
found := false
t.Log(tree.items)
for _, item := range tree.items {
if item.name == "bots-common" && item.hash == "81ac2ebd4077cb63bf408cf8bccd6fbe060dfad74516854fd0a067b421391184" && item.mode == 0o40000 {
if item.name == "bots-common" && item.hash == "9317aa47f6ea37e8bce280775790f4a801d7e3702f84fbe1b00e4a2c1c752c2b" && item.isTree() {
found = true
t.Log("found")
break
}
}
@ -207,7 +209,7 @@ Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com>` + "\x00"
found := false
for _, item := range tree.items {
t.Log(item)
if item.name == "nodejs22" && item.hash == "873a323b262ebb3bd77b2592b2e11bdd08dbc721cbf4ac9f97637e58e1fffce7" {
if item.name == "nodejs22" && item.hash == "873a323b262ebb3bd77b2592b2e11bdd08dbc721cbf4ac9f97637e58e1fffce7" && item.isSubmodule() {
found = true
break
}

View File

@ -5,6 +5,7 @@ import (
"path"
"src.opensuse.org/autogits/common"
"src.opensuse.org/autogits/common/gitea-generated/models"
)
const (
@ -24,6 +25,22 @@ func processPrjGitPullRequestSync(h *common.RequestHandler) error {
return nil
}
func prGitBranchNameForPR(req *common.PullRequestAction) string {
return fmt.Sprintf("PR_%s#%d", req.Repository.Name, req.Pull_Request.Number)
}
func updateOrCreatePRBranch(h *common.RequestHandler, prjGit *models.Repository, commitMsg, branchName string) {
req := h.Data.(*common.PullRequestAction)
h.GitExec("", "clone", "--depth", "1", prjGit.SSHURL, common.DefaultGitPrj)
h.GitExec(common.DefaultGitPrj, "checkout", "-B", branchName, prjGit.DefaultBranch)
h.GitExec(common.DefaultGitPrj, "submodule", "update", "--init", "--checkout", "--depth", "1", req.Repository.Name)
h.GitExec(path.Join(common.DefaultGitPrj, req.Repository.Name), "fetch", "--depth", "1", "origin", req.Pull_Request.Head.Sha)
h.GitExec(path.Join(common.DefaultGitPrj, req.Repository.Name), "checkout", req.Pull_Request.Head.Sha)
h.GitExec(common.DefaultGitPrj, "commit", "-a", "-m", commitMsg)
h.GitExec(common.DefaultGitPrj, "push", "-f", "origin", branchName)
}
func processPullRequestSync(h *common.RequestHandler) error {
req := h.Data.(*common.PullRequestAction)
@ -36,9 +53,26 @@ func processPullRequestSync(h *common.RequestHandler) error {
prjPr := h.GetAssociatedPrjGitPR(req)
h.GitExec("", "clone", "--branch", prjPr.Head.Name, "--depth", "1", prjPr.Head.Repo.SSHURL, common.DefaultGitPrj)
commitId := h.GitSubmoduleCommitId(common.DefaultGitPrj, req.Repository.Name)
commitId, ok := h.GitSubmoduleCommitId(common.DefaultGitPrj, req.Repository.Name, prjPr.Head.Ref)
if !ok {
return fmt.Errorf("Cannot fetch submodule commit id in prjgit for '%s'", req.Repository.Name)
}
// nothing changed, still in sync
if commitId == req.Pull_Request.Head.Ref {
return nil
}
commitMsg := fmt.Sprintf(`Sync PR
Update to %s`, req.Pull_Request.Head.Sha)
// we need to update prjgit PR with the new head hash
branchName := prGitBranchNameForPR(req)
updateOrCreatePRBranch(h, prjPr.Base.Repo, commitMsg, branchName)
return h.Error
}
func processPullRequestOpened(h *common.RequestHandler) error {
@ -50,7 +84,7 @@ func processPullRequestOpened(h *common.RequestHandler) error {
}
// create PrjGit branch for buidling the pull request
branchName := fmt.Sprintf("PR_%s#%d", req.Repository.Name, req.Pull_Request.Number)
branchName := prGitBranchNameForPR(req)
commitMsg := fmt.Sprintf(`auto-created for %s
This commit was autocreated by %s
@ -64,13 +98,7 @@ PullRequest: %s/%s#%d`, req.Repository.Owner.Username,
return h.Error
}
h.GitExec("", "clone", "--depth", "1", prjGit.SSHURL, common.DefaultGitPrj)
h.GitExec(common.DefaultGitPrj, "checkout", "-B", branchName, prjGit.DefaultBranch)
h.GitExec(common.DefaultGitPrj, "submodule", "update", "--init", "--checkout", "--depth", "1", req.Repository.Name)
h.GitExec(path.Join(common.DefaultGitPrj, req.Repository.Name), "fetch", "--depth", "1", "origin", req.Pull_Request.Head.Sha)
h.GitExec(path.Join(common.DefaultGitPrj, req.Repository.Name), "checkout", req.Pull_Request.Head.Sha)
h.GitExec(common.DefaultGitPrj, "commit", "-a", "-m", commitMsg)
h.GitExec(common.DefaultGitPrj, "push", "-f", "origin", branchName)
updateOrCreatePRBranch(h, prjGit, commitMsg, branchName)
PR := h.CreatePullRequest(prjGit, branchName, prjGit.DefaultBranch,
fmt.Sprintf("Forwarded PR: %s", req.Repository.Name),
@ -88,7 +116,7 @@ referencing the following pull request:
// request build review
h.RequestReviews(PR, common.Bot_BuildReview)
return nil
return h.Error
}
func processPullRequest(h *common.RequestHandler) error {