.
This commit is contained in:
parent
65d821d388
commit
249fbab882
@ -303,7 +303,8 @@ func parseGitMsg(data <-chan byte) (gitMsg, error) {
|
||||
id = id[:pos]
|
||||
|
||||
pos = 0
|
||||
for c := <-data; c != ' '; c = <-data {
|
||||
var c byte
|
||||
for c = <-data; c != ' ' && c != '\x00'; c = <-data {
|
||||
if c >= 'a' && c <= 'z' {
|
||||
msgType[pos] = c
|
||||
pos++
|
||||
@ -314,13 +315,22 @@ func parseGitMsg(data <-chan byte) (gitMsg, error) {
|
||||
msgType = msgType[:pos]
|
||||
|
||||
switch string(msgType) {
|
||||
case "commit", "tree":
|
||||
case "commit", "tree", "blob":
|
||||
break
|
||||
case "missing":
|
||||
if c != '\x00' {
|
||||
return gitMsg{}, fmt.Errorf("Missing format weird")
|
||||
}
|
||||
return gitMsg{
|
||||
hash: string(id[:]),
|
||||
itemType: "missing",
|
||||
size: 0,
|
||||
}, fmt.Errorf("Object not found: '%s'", string(id))
|
||||
default:
|
||||
return gitMsg{}, fmt.Errorf("Invalid object type: '%s'", string(msgType))
|
||||
}
|
||||
|
||||
for c := <-data; c != '\000'; c = <-data {
|
||||
for c = <-data; c != '\000'; c = <-data {
|
||||
if c >= '0' && c <= '9' {
|
||||
size = size*10 + (int(c) - '0')
|
||||
} else {
|
||||
@ -357,6 +367,12 @@ func parseGitCommitMsg(data <-chan byte, l int) (string, error) {
|
||||
|
||||
for c := <-data; c != '\x00'; c = <-data {
|
||||
msg = append(msg, c)
|
||||
l--
|
||||
}
|
||||
// l--
|
||||
|
||||
if l != 0 {
|
||||
return "", fmt.Errorf("Unexpected data in the git commit msg: l=%d", l)
|
||||
}
|
||||
|
||||
return string(msg), nil
|
||||
@ -434,7 +450,8 @@ func parseGitTree(data <-chan byte) (tree, error) {
|
||||
|
||||
// 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; {
|
||||
parsedLen := 0
|
||||
for parsedLen < hdr.size {
|
||||
entry, err := parseTreeEntry(data, len(hdr.hash)/2)
|
||||
if err != nil {
|
||||
return tree{}, nil
|
||||
@ -443,10 +460,103 @@ func parseGitTree(data <-chan byte) (tree, error) {
|
||||
t.items = append(t.items, entry)
|
||||
parsedLen += entry.size
|
||||
}
|
||||
c := <-data // \0 read
|
||||
|
||||
if c != '\x00' {
|
||||
return t, fmt.Errorf("Unexpected character during git tree data read")
|
||||
}
|
||||
|
||||
if parsedLen != hdr.size {
|
||||
return t, fmt.Errorf("Invalid size of git tree data")
|
||||
}
|
||||
|
||||
return t, nil
|
||||
}
|
||||
|
||||
func parseGitBlob(data <-chan byte) ([]byte, error) {
|
||||
hdr, err := parseGitMsg(data)
|
||||
if err != nil {
|
||||
return []byte{}, err
|
||||
}
|
||||
|
||||
d := make([]byte, hdr.size)
|
||||
for l:=0; l<hdr.size; l++ {
|
||||
d[l] = <-data
|
||||
}
|
||||
eob := <-data
|
||||
if eob != '\x00' {
|
||||
return d, fmt.Errorf("invalid byte read in parseGitBlob")
|
||||
}
|
||||
|
||||
return d, nil
|
||||
}
|
||||
|
||||
// TODO: support sub-trees
|
||||
func (e *RequestHandler) GitCatFile(cwd, commitId, filename string) []byte {
|
||||
var done sync.Mutex
|
||||
var data []byte
|
||||
|
||||
done.Lock()
|
||||
data_in, data_out := ChanIO{make(chan byte, 256)}, ChanIO{make(chan byte, 70)}
|
||||
|
||||
go func() {
|
||||
defer done.Unlock()
|
||||
defer close(data_out.ch)
|
||||
|
||||
data_out.Write([]byte(commitId))
|
||||
data_out.ch <- '\x00'
|
||||
c, err := parseGitCommit(data_in.ch)
|
||||
if err != nil {
|
||||
e.Error = err
|
||||
e.LogError("Error parsing git commit: %v", err)
|
||||
return
|
||||
}
|
||||
data_out.Write([]byte(c.Tree))
|
||||
data_out.ch <- '\x00'
|
||||
tree, err := parseGitTree(data_in.ch)
|
||||
|
||||
if err != nil {
|
||||
e.Error = err
|
||||
e.LogError("Error parsing git tree: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, te := range tree.items {
|
||||
if te.isBlob() && te.name == filename {
|
||||
data_out.Write([]byte(te.hash))
|
||||
data_out.ch <- '\x00'
|
||||
data, err = parseGitBlob(data_in.ch)
|
||||
if err != nil {
|
||||
e.Error = err
|
||||
e.LogError("Error reading blob data: %v", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
e.Error = fmt.Errorf("file not found: '%s'", filename)
|
||||
e.LogPlainError(e.Error)
|
||||
}()
|
||||
|
||||
cmd := exec.Command("/usr/bin/git", "cat-file", "--batch", "-Z")
|
||||
cmd.Env = []string{
|
||||
"GIT_CEILING_DIRECTORIES=" + e.GitPath,
|
||||
"GIT_CONFIG_GLOBAL=/dev/null",
|
||||
}
|
||||
cmd.Dir = filepath.Join(e.GitPath, cwd)
|
||||
cmd.Stdout = &data_in
|
||||
cmd.Stdin = &data_out
|
||||
cmd.Stderr = writeFunc(func(data []byte) (int, error) {
|
||||
e.Logger.LogError("%s", data)
|
||||
return len(data), nil
|
||||
})
|
||||
e.Log("command run: %v", cmd.Args)
|
||||
e.Error = cmd.Run()
|
||||
|
||||
done.Lock()
|
||||
return data
|
||||
}
|
||||
|
||||
func (e *RequestHandler) GitSubmoduleList(cwd, commitId string) map[string]string {
|
||||
var done sync.Mutex
|
||||
submoduleList := make(map[string]string)
|
||||
|
@ -88,7 +88,7 @@ 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" +
|
||||
const commitData = "f40888ea4515fe2e8eea617a16f5f50a45f652d894de3ad181d58de3aafb8f99 commit 253\000" +
|
||||
`tree e20033df9f18780756ba4a96dbc7eb1a626253961039cb674156f266ba7a4e53
|
||||
parent 429cc2fe02170ca5668f0461928c7e7430c7a17cd64ac298286d7162572a7703
|
||||
author Adam Majer <amajer@suse.com> 1720709149 +0200
|
||||
@ -115,7 +115,7 @@ committer Adam Majer <amajer@suse.com> 1720709149 +0200
|
||||
})
|
||||
|
||||
t.Run("parse multiline headers", func(t *testing.T) {
|
||||
const commitData = "cae5831ab48470ff060a5aaa12eb6e5a7acaf91e commit 1492\x00" +
|
||||
const commitData = "cae5831ab48470ff060a5aaa12eb6e5a7acaf91e commit 1491\x00" +
|
||||
`tree 1f9c8fe8099615d6d3921528402ac53f09213b02
|
||||
parent e08a654fae0ecc91678819e0b62a2e014bad3339
|
||||
author Yagiz Nizipli <yagiz@nizipli.com> 1720967314 -0400
|
||||
@ -253,4 +253,22 @@ func TestCommitTreeParsingOfHead(t *testing.T) {
|
||||
t.Errorf("hash doesn't match: %s vs. expected %s", id, nodejs21)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("reads README.md", func (t *testing.T) {
|
||||
h := RequestHandler{
|
||||
GitPath: gitDir,
|
||||
Logger: CreateTestLogger(t),
|
||||
}
|
||||
data := h.GitCatFile("", commitId, "README.md")
|
||||
if h.HasError() {
|
||||
t.Errorf("failed parse: %v", h.Error)
|
||||
}
|
||||
if string(data) != "foo\n" || len(data) != 4 {
|
||||
t.Errorf("Wrong data of len: %d", len(data))
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("try to parse unknown item", func(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,12 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
git init -q --bare --object-format=sha256
|
||||
|
||||
# 81aba862107f1e2f5312e165453955485f424612f313d6c2fb1b31fef9f82a14
|
||||
blobA=$(echo "help" | git hash-object --stdin -w)
|
||||
# 47d6aca82756ff2e61e53520bfdf1faa6c86d933be4854eb34840c57d12e0c85
|
||||
blobB=$(echo "foo" | git hash-object --stdin -w)
|
||||
|
||||
tree=$(printf "100644 blob $blobA help\n100644 blob $blobB README.md\n160000 commit dc55b828328c8e494f67874a7d8c03dd1c6b4e02d16b86e08e47d70ecd799680 mingw32-gcc\n160000 commit d6a74c08406ce40cc8f7bff2d5cf309087a8728361cc75354b0862ba508193b8 nodejs-common\n160000 commit c678c57007d496a98bec668ae38f2c26a695f94af78012f15d044ccf066ccb41 nodejs21\n160000 commit 873a323b262ebb3bd77b2592b2e11bdd08dbc721cbf4ac9f97637e58e1fffce7 nodejs22\n160000 commit 35c702e8501eedeb5ce43d6f3460d11c791cfefaa77248f08cad55d00c37e73a python311\n"|git mktree)
|
||||
commit=$(git commit-tree -m 'OK' $tree)
|
||||
git reset --soft $commit
|
||||
|
@ -45,6 +45,16 @@ func fetchPrGit(h *common.RequestHandler, pr *models.PullRequest) error {
|
||||
return h.Error
|
||||
}
|
||||
|
||||
func getObsProjectAssociatedWithPr(baseProject string, pr *models.PullRequest) string {
|
||||
return fmt.Sprintf(
|
||||
"%s:%s:%s:PR:%d",
|
||||
baseProject,
|
||||
common.ObsSafeProjectName(pr.Base.Repo.Owner.UserName),
|
||||
common.ObsSafeProjectName(pr.Base.Repo.Name),
|
||||
pr.Index,
|
||||
)
|
||||
}
|
||||
|
||||
func processPullNotification(h *common.RequestHandler, notification *models.NotificationSubject) {
|
||||
rx := regexp.MustCompile(`^https://src\.(?:open)?suse\.(?:org|de)/api/v\d+/repos/(?<org>[a-zA-Z0-9]+)/(?<project>[_a-zA-Z0-9]+)/issues/(?<num>[0-9]+)$`)
|
||||
match := rx.FindStringSubmatch(notification.URL)
|
||||
@ -104,38 +114,40 @@ func processPullNotification(h *common.RequestHandler, notification *models.Noti
|
||||
continue
|
||||
}
|
||||
|
||||
err := fetchPrGit(h, pr)
|
||||
if err != nil {
|
||||
h.LogError("Cannot fetch PR git: %s", pr.URL)
|
||||
return
|
||||
}
|
||||
|
||||
dir := pr.Head.Sha
|
||||
headSubmodules := h.GitSubmoduleList(dir, pr.Head.Sha)
|
||||
baseSubmodules := h.GitSubmoduleList(dir, pr.Base.Sha)
|
||||
|
||||
modifiedOrNew := make([]string, 0, 16)
|
||||
for pkg, headOid := range headSubmodules {
|
||||
if baseOid, exists := baseSubmodules[pkg]; !exists || baseOid != headOid {
|
||||
modifiedOrNew = append(modifiedOrNew, pkg)
|
||||
}
|
||||
}
|
||||
|
||||
// find modified submodules and new submodules -- build them
|
||||
|
||||
h.Log("processing state...")
|
||||
|
||||
switch review.State {
|
||||
// create build project, if doesn't exist, and add it to pending requests
|
||||
case common.ReviewStateUnknown, common.ReviewStateRequestReview:
|
||||
h.Log("repo content fetching ...")
|
||||
buildPrjBytes, err := h.GetPullRequestFileContent(pr, "project.build")
|
||||
err := fetchPrGit(h, pr)
|
||||
if err != nil {
|
||||
h.LogPlainError(err)
|
||||
h.LogError("Cannot fetch PR git: %s", pr.URL)
|
||||
return
|
||||
}
|
||||
|
||||
// find modified submodules and new submodules -- build them
|
||||
dir := pr.Head.Sha
|
||||
headSubmodules := h.GitSubmoduleList(dir, pr.Head.Sha)
|
||||
baseSubmodules := h.GitSubmoduleList(dir, pr.Base.Sha)
|
||||
|
||||
modifiedOrNew := make([]string, 0, 16)
|
||||
for pkg, headOid := range headSubmodules {
|
||||
if baseOid, exists := baseSubmodules[pkg]; !exists || baseOid != headOid {
|
||||
modifiedOrNew = append(modifiedOrNew, pkg)
|
||||
}
|
||||
}
|
||||
|
||||
h.Log("repo content fetching ...")
|
||||
buildPrjBytes := h.GitCatFile(dir, pr.Head.Sha, "project.build")
|
||||
// buildPrjBytes, err := h.GetPullRequestFileContent(pr, "project.build")
|
||||
if h.HasError() {
|
||||
h.LogPlainError(h.Error)
|
||||
/*
|
||||
_, err := h.AddReviewComment(pr, common.ReviewStateRequestChanges, "Cannot find reference project")
|
||||
if err != nil {
|
||||
h.LogPlainError(err)
|
||||
}
|
||||
*/
|
||||
return
|
||||
}
|
||||
|
||||
@ -150,12 +162,7 @@ func processPullNotification(h *common.RequestHandler, notification *models.Noti
|
||||
// disable publishing
|
||||
|
||||
// TODO: escape things here
|
||||
meta.Name = fmt.Sprintf("%s:%s:%s:PR:%d",
|
||||
obsClient.HomeProject,
|
||||
common.ObsSafeProjectName(pr.Base.Repo.Owner.UserName),
|
||||
common.ObsSafeProjectName(pr.Base.Repo.Name),
|
||||
pr.Index,
|
||||
)
|
||||
meta.Name = getObsProjectAssociatedWithPr(obsClient.HomeProject, pr)
|
||||
meta.Description = fmt.Sprintf(`Pull request build job: %s%s PR#%d`,
|
||||
"https://src.opensuse.org", pr.Base.Repo.Name, pr.Index)
|
||||
urlPkg := make([]string, 0, len(modifiedOrNew))
|
||||
@ -185,12 +192,14 @@ func processPullNotification(h *common.RequestHandler, notification *models.Noti
|
||||
// set the review state to pending
|
||||
|
||||
case common.ReviewStatePending:
|
||||
// waiting for build results
|
||||
// waiting for build results
|
||||
// project := getObsProjectAssociatedWithPr(obsClient.HomeProject, pr)
|
||||
case common.ReviewStateApproved:
|
||||
// done, mark notification as read
|
||||
// done, mark notification as read
|
||||
h.Log("processing request for success build ...")
|
||||
case common.ReviewStateRequestChanges:
|
||||
h.Log("processing request for failed request changes...")
|
||||
// build failures, nothing to do here, mark notification as read
|
||||
h.Log("processing request for failed request changes...")
|
||||
}
|
||||
|
||||
break
|
||||
|
Loading…
Reference in New Issue
Block a user