When project is advanced, and we have other package changes to same project, the project git changes need to be rebased. The simplest way of doing this is to skip all the submodule conflicts and re-create them. This allows the submodules changes to be mergeable again.
598 lines
22 KiB
Go
598 lines
22 KiB
Go
package common
|
|
|
|
/*
|
|
* This file is part of Autogits.
|
|
*
|
|
* Copyright © 2024 SUSE LLC
|
|
*
|
|
* Autogits is free software: you can redistribute it and/or modify it under
|
|
* the terms of the GNU General Public License as published by the Free Software
|
|
* Foundation, either version 2 of the License, or (at your option) any later
|
|
* version.
|
|
*
|
|
* Autogits is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
|
* PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along with
|
|
* Foobar. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
import (
|
|
"bufio"
|
|
"bytes"
|
|
"os"
|
|
"os/exec"
|
|
"path"
|
|
"slices"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestGitClone(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
|
|
repo string
|
|
branch string
|
|
remoteName string
|
|
remoteUrl string
|
|
}{
|
|
{
|
|
name: "Basic clone",
|
|
repo: "pkgAclone",
|
|
branch: "main",
|
|
remoteName: "pkgA_main",
|
|
remoteUrl: "/pkgA",
|
|
},
|
|
{
|
|
name: "Remote branch is non-existent",
|
|
repo: "pkgAclone",
|
|
branch: "main_not_here",
|
|
remoteName: "pkgA_main",
|
|
remoteUrl: "/pkgA",
|
|
},
|
|
}
|
|
|
|
return
|
|
|
|
execPath, err := os.Getwd()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
d := t.TempDir()
|
|
os.Chdir(d)
|
|
defer os.Chdir(execPath)
|
|
cmd := exec.Command(path.Join(execPath, "test_clone_setup.sh"))
|
|
if _, err := cmd.Output(); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
gh, err := AllocateGitWorkTree(d, "Test", "test@example.com")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
g, err := gh.CreateGitHandler("org")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if _, err := g.GitClone(test.repo, test.branch, "file://"+d+test.remoteUrl); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
id, err := g.GitBranchHead(test.repo, test.branch)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
t.Fatal(id)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestGitMsgParsing(t *testing.T) {
|
|
t.Run("tree message with size 56", func(t *testing.T) {
|
|
const hdr = "f40888ea4515fe2e8eea617a16f5f50a45f652d894de3ad181d58de3aafb8f98 tree 56\x00"
|
|
|
|
data := make(chan byte, 500)
|
|
for _, b := range []byte(hdr) {
|
|
data <- b
|
|
}
|
|
gitHdr, err := parseGitMsg(data)
|
|
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
|
|
if gitHdr.hash != "f40888ea4515fe2e8eea617a16f5f50a45f652d894de3ad181d58de3aafb8f98" {
|
|
t.Errorf("Invalid hash %s", gitHdr.hash)
|
|
}
|
|
|
|
if gitHdr.size != 56 {
|
|
t.Errorf("Invalid msg size: %d", gitHdr.size)
|
|
}
|
|
|
|
if gitHdr.itemType != "tree" {
|
|
t.Errorf("Invalid msg type: %s", gitHdr.itemType)
|
|
}
|
|
})
|
|
t.Run("commit message with size 256", func(t *testing.T) {
|
|
const hdr = "f40888ea4515fe2e8eea617a16f5f50a45f652d894de3ad181d58de3aafb8f99 commit 256\x00"
|
|
|
|
data := make(chan byte, 500)
|
|
for _, b := range []byte(hdr) {
|
|
data <- b
|
|
}
|
|
gitHdr, err := parseGitMsg(data)
|
|
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
|
|
if gitHdr.hash != "f40888ea4515fe2e8eea617a16f5f50a45f652d894de3ad181d58de3aafb8f99" {
|
|
t.Errorf("Invalid hash %s", gitHdr.hash)
|
|
}
|
|
|
|
if gitHdr.size != 256 {
|
|
t.Errorf("Invalid msg size: %d", gitHdr.size)
|
|
}
|
|
|
|
if gitHdr.itemType != "commit" {
|
|
t.Errorf("Invalid msg type: %s", gitHdr.itemType)
|
|
}
|
|
})
|
|
t.Run("invalid tree message with size 56", func(t *testing.T) {
|
|
const hdr = "f408r8ea4515fe2e8eea617a16f5f50a45f652d894de3ad181d58de3aafb8f98 tree 56\x00"
|
|
|
|
data := make(chan byte, 500)
|
|
for _, b := range []byte(hdr) {
|
|
data <- b
|
|
}
|
|
gitHdr, err := parseGitMsg(data)
|
|
|
|
if err.Error() != "Invalid character during object hash parse 'r' at 4" {
|
|
t.Error(err)
|
|
}
|
|
|
|
if gitHdr.hash != "" {
|
|
t.Errorf("Invalid hash %s", gitHdr.hash)
|
|
}
|
|
|
|
if gitHdr.size != 0 {
|
|
t.Errorf("Invalid msg size: %d", gitHdr.size)
|
|
}
|
|
|
|
if gitHdr.itemType != "" {
|
|
t.Errorf("Invalid msg type: %s", gitHdr.itemType)
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestGitCommitParsing(t *testing.T) {
|
|
t.Run("parse valid commit message", func(t *testing.T) {
|
|
const commitData = "f40888ea4515fe2e8eea617a16f5f50a45f652d894de3ad181d58de3aafb8f99 commit 253\000" +
|
|
`tree e20033df9f18780756ba4a96dbc7eb1a626253961039cb674156f266ba7a4e53
|
|
parent 429cc2fe02170ca5668f0461928c7e7430c7a17cd64ac298286d7162572a7703
|
|
author Adam Majer <amajer@suse.com> 1720709149 +0200
|
|
committer Adam Majer <amajer@suse.com> 1720709149 +0200
|
|
|
|
.` + "\000"
|
|
ch := make(chan byte, 5000)
|
|
for _, b := range []byte(commitData) {
|
|
ch <- b
|
|
}
|
|
commit, err := parseGitCommit(ch)
|
|
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
|
|
if commit.Tree != "e20033df9f18780756ba4a96dbc7eb1a626253961039cb674156f266ba7a4e53" {
|
|
t.Errorf("Invalid commit object: %#v", commit)
|
|
}
|
|
|
|
if commit.Msg != "." {
|
|
t.Errorf("Invalid commit msg: '%s'", commit.Msg)
|
|
}
|
|
})
|
|
|
|
t.Run("parse multiline headers", func(t *testing.T) {
|
|
const commitData = "cae5831ab48470ff060a5aaa12eb6e5a7acaf91e commit 1492\000" +
|
|
`tree 1f9c8fe8099615d6d3921528402ac53f09213b02
|
|
parent e08a654fae0ecc91678819e0b62a2e014bad3339
|
|
author Yagiz Nizipli <yagiz@nizipli.com> 1720967314 -0400
|
|
committer GitHub <noreply@github.com> 1720967314 +0200
|
|
gpgsig -----BEGIN PGP SIGNATURE-----
|
|
|
|
wsFcBAABCAAQBQJmk+CSCRC1aQ7uu5UhlAAAQIYQAEQXCl3bUUuegiz5/oitIIF7
|
|
6xhndcjQIuqY4dONIeOARrGwbKh8OtMHpfJhMRUmvWvXrsTA6P1PWl0YcyyIMzHZ
|
|
a4sBsWyxA0uSztVywpvksvk6EdMoEXeXrHS3cBxePsH8bI+Pwnsv27PsevEwpyIT
|
|
reB4zZsoGySFVqf2lnXxG5hSRMYw++BDXSDMZk2BP9BvueRXasJ0lT1c7HlbHepF
|
|
TWzwyHZ91OhXjrdPY7qLQEEV/frwuM+UrxOPb2e83ZTg81vXFuugURfhHNx4Iu+F
|
|
LCMvOeaF2vO5yJtMe8+tY1l0Wb8S1aWcGCECN2XCXmmnWxt+yYh2gjqxq3y0DMcz
|
|
zvg6arQIepDFLkQPZMDlUCIjIJQn4FbAaQAvoyMF8Pi5YmxhRqgo3iOB5SBE8eES
|
|
63ifZ311izuSdD+o3ObFpzLoTgq62kglwfegZN/X8CzTSIqrT1norYJEbSwkWID1
|
|
WeRHUHfC7f6N3XK8zeb83zmhBU58ghW9sp5/LcefGMRJmVhBWhjBCpeMUaFHdKhl
|
|
/dfgPl5gJrrJ+wM3O6iaay0R1Iv4Upe/yXrbQnIgGj/qqgMLEPBY8lzNYimVTLxd
|
|
2ObrcXnERo3wwxeUgWaAARbEGQjC51DK/2SXxVGUh+IokicsBNRKU7lVWwwFFely
|
|
ntjtge6Gs9pA5rSIilPH
|
|
=V1bK
|
|
-----END PGP SIGNATURE-----
|
|
|
|
|
|
meta: change email address of anonrig
|
|
|
|
PR-URL: https://github.com/nodejs/node/pull/53829
|
|
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
|
|
Reviewed-By: James M Snell <jasnell@gmail.com>
|
|
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
|
|
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
|
|
Reviewed-By: Ulises Gascón <ulisesgascongonzalez@gmail.com>
|
|
Reviewed-By: Richard Lau <rlau@redhat.com>
|
|
Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com>` + "\000"
|
|
|
|
ch := make(chan byte, 5000)
|
|
for _, b := range []byte(commitData) {
|
|
ch <- b
|
|
}
|
|
commit, err := parseGitCommit(ch)
|
|
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
|
|
if commit.Tree != "1f9c8fe8099615d6d3921528402ac53f09213b02" {
|
|
t.Errorf("Invalid commit object: %#v", commit)
|
|
}
|
|
|
|
if commit.Msg[len(commit.Msg)-55:] != "Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com>" {
|
|
t.Errorf("Invalid commit msg: '%s'", commit.Msg[len(commit.Msg)-55:])
|
|
}
|
|
})
|
|
|
|
t.Run("parse multiline headers", func(t *testing.T) {
|
|
const commitData = "c07c52c57a10fb355956df3caad2986613838f149274fbe312ad76560764829d commit 1150\000" + `tree 3e06b280ea056141ed5e8af9794a41ae5281930c45321803eab53a240cb60044
|
|
parent 19362a2cecb1fd25a89e03611d08ac68dcb1732f9dc0a68a40926356787fa4ca
|
|
author Adrian Schröter <adrian@suse.de> 1746600403 +0200
|
|
committer Adrian Schröter <adrian@suse.de> 1746600403 +0200
|
|
gpgsig-sha256 -----BEGIN PGP SIGNATURE-----
|
|
|
|
iQIzBAABCgAdFiEE1QF1zm/pNbvyhgLFkY2MlUwI22cFAmgbAd0ACgkQkY2MlUwI
|
|
22dxtA//eUCzIqxVdaEnOrFeTyxKig/mCOjaAyctmwr0vXUyElRtjXe4TzVG3QtR
|
|
uDfhIrKYLZ2tU/0TewTW/4XopWxLuqEzVQLrjuYl7K5P3GoYk52W1yGT0szzm7/i
|
|
87j4UdRL9YGU/gYO7nSzstcfTP6AcmYzVUoOnwYR0K2vyOVjO4niL3mFXxLkIgIt
|
|
jd82xcE4JpQz9Yjyq2nDdz4A55kLAwsqY+dOct4oC6bZmj1/JeoGQfPvUsvsQgcI
|
|
syCHVh0GBxjvSv50V/VPzxQTFMal/TdtvAD4kmP/9RDi/5THzus8Peam8pV0gEIC
|
|
Q15ZcuLwIsC9i7ifUDYgzLgBBRdpSI0qji4Y6clWULPVjsyghgyfQw1trBSySpC8
|
|
O1XfajUM+rXyrBLP6kzY+zl/zyzRdJ8JhljmC+SmNuyyEB77Hkn83k0f+aBhhqC2
|
|
4b3fIsKtwJZ1w6gr6SSz1BottiT9ShQzRaL8iRoF/2l5MkHPR+QFg2J7EIBqCbCQ
|
|
hFUjdvWAXQBWkkTQlJmLmJBXDOLQg3o6xCbnZM0gPFjZWE7e3Mpky7H0+xPnoeg9
|
|
ukuvkexXQ6yrdiekA7HRLc76Te/I0m7KDOOWZ3rbJV6uH/3ps4FbLQTZO12AtZ6J
|
|
n8hYdYfw9yjCxiKUjnEtXtDRe8DJpqv+hO0Wj4MI5gIA2JE2lzY=
|
|
=Keg5
|
|
-----END PGP SIGNATURE-----
|
|
|
|
dummy change, don't merge
|
|
` + "\000"
|
|
ch := make(chan byte)
|
|
go func() {
|
|
for _, b := range []byte(commitData) {
|
|
ch <- b
|
|
}
|
|
}()
|
|
commit, err := parseGitCommit(ch)
|
|
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
|
|
if commit.Tree != "3e06b280ea056141ed5e8af9794a41ae5281930c45321803eab53a240cb60044" {
|
|
t.Errorf("Invalid commit object: %#v", commit)
|
|
}
|
|
|
|
if commit.Msg != "dummy change, don't merge\n" {
|
|
t.Errorf("Invalid commit msg: '%s'", commit.Msg)
|
|
}
|
|
})
|
|
|
|
t.Run("parse tree object", func(t *testing.T) {
|
|
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) {
|
|
ch <- b
|
|
}
|
|
|
|
tree, err := parseGitTree(ch)
|
|
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
|
|
found := false
|
|
t.Log(tree.items)
|
|
for _, item := range tree.items {
|
|
if item.name == "bots-common" && item.hash == "9317aa47f6ea37e8bce280775790f4a801d7e3702f84fbe1b00e4a2c1c752c2b" && item.isTree() {
|
|
found = true
|
|
t.Log("found")
|
|
break
|
|
}
|
|
}
|
|
if !found {
|
|
t.Error("expected sub-tree not found")
|
|
}
|
|
})
|
|
|
|
t.Run("parse tree object with submodules", func(t *testing.T) {
|
|
const treeData = "\x34\x38\x34\x66\x31\x62\x65\x65\x63\x39\x35\x63\x61\x36\x62\x38\x36\x30\x64\x30\x64\x37\x63\x35\x65\x34\x38\x37\x31\x36\x36\x62\x30\x38\x65\x31\x61\x34\x35\x36\x37\x36\x62\x31\x37\x64\x39\x65\x65\x66\x32\x39\x39\x39\x65\x39\x64\x37\x34\x63\x62\x63\x64\x36\x20\x74\x72\x65\x65\x20\x33\x34\x39\x00\x31\x30\x30\x36\x34\x34\x20\x2e\x67\x69\x74\x6d\x6f\x64\x75\x6c\x65\x73\x00\xc8\x1e\x14\x29\xc5\xd4\x07\xfc\x32\xf1\xd7\xe2\x64\xee\x88\xfc\xce\xfc\x44\xf7\xae\x2e\xc4\x6e\x2c\x15\x27\x26\x65\xd4\xb8\x78\x31\x30\x30\x36\x34\x34\x20\x52\x45\x41\x44\x4d\x45\x2e\x6d\x64\x00\x90\x22\x84\x13\xbf\xd3\x5c\xfb\x1e\x27\x6b\xd6\x17\x3e\x89\xed\x0f\xc6\x31\x85\x24\x58\x6d\x9d\xf0\x6a\x1e\x17\x57\x19\x8d\xc2\x31\x36\x30\x30\x30\x30\x20\x6d\x69\x6e\x67\x77\x33\x32\x2d\x67\x63\x63\x00\xdc\x55\xb8\x28\x32\x8c\x8e\x49\x4f\x67\x87\x4a\x7d\x8c\x03\xdd\x1c\x6b\x4e\x02\xd1\x6b\x86\xe0\x8e\x47\xd7\x0e\xcd\x79\x96\x80\x31\x36\x30\x30\x30\x30\x20\x6e\x6f\x64\x65\x6a\x73\x2d\x63\x6f\x6d\x6d\x6f\x6e\x00\xd6\xa7\x4c\x08\x40\x6c\xe4\x0c\xc8\xf7\xbf\xf2\xd5\xcf\x30\x90\x87\xa8\x72\x83\x61\xcc\x75\x35\x4b\x08\x62\xba\x50\x81\x93\xb8\x31\x36\x30\x30\x30\x30\x20\x6e\x6f\x64\x65\x6a\x73\x32\x31\x00\x24\xee\x6b\xee\x74\x59\xa3\x86\xda\xda\xbf\x8a\x9f\x6a\xe4\xfa\x15\xc3\xf8\x10\xbf\xa0\x1c\xee\x52\x38\x13\x8a\xa2\x14\xd1\x80\x31\x36\x30\x30\x30\x30\x20\x6e\x6f\x64\x65\x6a\x73\x32\x32\x00\x87\x3a\x32\x3b\x26\x2e\xbb\x3b\xd7\x7b\x25\x92\xb2\xe1\x1b\xdd\x08\xdb\xc7\x21\xcb\xf4\xac\x9f\x97\x63\x7e\x58\xe1\xff\xfc\xe7\x31\x36\x30\x30\x30\x30\x20\x70\x79\x74\x68\x6f\x6e\x33\x31\x31\x00\x35\xc7\x02\xe8\x50\x1e\xed\xeb\x5c\xe4\x3d\x6f\x34\x60\xd1\x1c\x79\x1c\xfe\xfa\xa7\x72\x48\xf0\x8c\xad\x55\xd0\x0c\x37\xe7\x3a\x00"
|
|
|
|
ch := make(chan byte, 1000)
|
|
for _, b := range []byte(treeData) {
|
|
ch <- b
|
|
}
|
|
|
|
tree, err := parseGitTree(ch)
|
|
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
|
|
found := false
|
|
for _, item := range tree.items {
|
|
t.Log(item)
|
|
if item.name == "nodejs22" && item.hash == "873a323b262ebb3bd77b2592b2e11bdd08dbc721cbf4ac9f97637e58e1fffce7" && item.isSubmodule() {
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
if !found {
|
|
t.Error("expected submodule not found")
|
|
}
|
|
})
|
|
|
|
t.Run("parse nested trees with subtrees", func(t *testing.T) {
|
|
const data = "873a323b262ebb3bd77b2592b2e11bdd08dbc721cbf4ac9f97637e58e1fffce7 tree 1083\x00100644\x20\x2Egitattributes\x00\xD8v\xA95\x87\xC1\xA9\xFCPn\xDD\xD4\x13\x9B\x8E\xD2\xCFs\xBD\x11q\x8A\xAE\x8A\x7Cg\xE2C\x14J\x01\xB0100644\x20\x2Egitignore\x00\xC3\xCD\x8En\x887\x3AJ\xA0P\xEEL\xD4\xF5\xD2v\x9C\xA6v\xC5D\x60\x40\x95\xD1\x0B\xA4\xB8\x86\xD4rE100644\x20COPYING\x00\x12\x2A\x28\xC8\xB9\x5D\x9B\x8A\x23\x1F\xE96\x07\x3F\xA9D\x90\xFD\xCE\x2Bi\x2D\x031\x5C\xCC\xC4fx\x00\xC22100644\x20README\x2Emd\x00\x92D\xF7\xFF\x0E0\x5C\xF2\xAC\x0DA\x06\x92\x0B\xD6z\x3CGh\x00y\x7EW1\xB9a\x8Ch\x215Fa100644\x20_service\x00\xC51\xF2\x12\xF3\x24\x9C\xD9\x9F\x0A\x93Mp\x12\xC1\xF7i\x05\x95\xC5Z\x06\x95i\x3Az\xC3\xF59\x7E\xF8\x1B100644\x20autogits\x2Echanges\x00\xF7\x8D\xBF\x0A\xCB\x5D\xB7y\x8C\xA9\x9C\xEB\x92\xAFd\x2C\x98\x23\x0C\x13\x13\xED\xDE\x5D\xBALD6\x3BR\x5B\xCA100644\x20autogits\x2Espec\x00\xD2\xBC\x20v\xD3\xE5F\xCA\xEE\xEA\x18\xC84\x0D\xA7\xCA\xD8O\xF2\x0A\xAB\x40\x2A\xFAL\x3B\xB4\xE6\x11\xE7o\xD140000\x20common\x00\xE2\xC9dg\xD0\x5D\xD1\xF1\x8ARW\xF0\x96\xD6\x29\x2F\x8F\xD9\xC7\x82\x1A\xB7\xAAw\xB0\xCE\xA8\xFE\xC8\xD7D\xF2100755\x20dev_test_helper\x2Esh\x00\xECY\xDD\xB3rz\x9Fh\xD4\x2E\x85\x02\x13\xF8\xFE\xB57\x8B\x1B6\x8E\x09dC\x1E\xE0\x90\x09\x08\xED\xBD_40000\x20devel\x2Dimporter\x00v\x98\x9B\x92\xD8\x24lu\xFC\xB2d\xC9\xCENb\xEE\x0F\x21\x8B\x92\x88\xDBs\xF8\x2E\xA8\xC8W\x1C\x20\xCF\xD440000\x20doc\x00\x8Akyq\xD0\xCF\xB8\x2F\x80Y\x2F\x11\xF0\x14\xA9\xFE\x96\x14\xE0W\x2C\xCF\xB9\x86\x7E\xFDi\xD7\x1F\x08Q\xFB40000\x20gitea\x2Devents\x2Drabbitmq\x2Dpublisher\x00\x5Cb\x3Fh\xA2\x06\x06\x0Cd\x09\xA5\xD9\xF7\x23\x5C\xF85\xF5\xB8\xBE\x7F\xD4O\x25t\xEF\xCC\xAB\x18\x7C\x0C\xF3100644\x20go\x2Emod\x00j\x85\x0B\x03\xC8\x9F\x9F\x0F\xC8\xE0\x8C\xF7\x3D\xC19\xF7\x12gk\xD6\x18JN\x24\xC0\x1C\xBE\x97oY\x02\x8D100644\x20go\x2Esum\x00h\x88\x2E\x27\xED\xD39\x8D\x12\x0F\x7D\x97\xA2\x5DE\xB9\x82o\x0Cu\xF4l\xA17s\x28\x2BQT\xE6\x12\x9040000\x20group\x2Dreview\x00\x7E\x7B\xB42\x0F\x3B\xC9o\x2C\xE79\x1DR\xE2\xE4i\xAE\xF6u\x90\x09\xD8\xC9c\xE7\xF7\xC7\x92\xFB\xD7\xDD140000\x20obs\x2Dstaging\x2Dbot\x00\x12\xE8\xAF\x09\xD4\x5D\x13\x8D\xC9\x0AvPDc\xB6\x7C\xAC4\xD9\xC5\xD4_\x98i\xBE2\xA7\x25aj\xE2k40000\x20obs\x2Dstatus\x2Dservice\x00MATY\xA3\xFA\xED\x05\xBE\xEB\x2B\x07\x9CN\xA9\xF3SB\x22MlV\xA4\x5D\xDA\x0B\x0F\x23\xA1\xA8z\xD740000\x20systemd\x00\x2D\xE2\x03\x7E\xBD\xEB6\x8F\xC5\x0E\x12\xD4\xBD\x97P\xDD\xA2\x92\xCE6n\x08Q\xCA\xE4\x15\x97\x8F\x26V\x3DW100644\x20vendor\x2Etar\x2Ezst\x00\xD9\x2Es\x03I\x91\x22\x24\xC86q\x91\x95\xEF\xA3\xC9\x3C\x06D\x90w\xAD\xCB\xAE\xEEu2i\xCE\x05\x09u40000\x20workflow\x2Ddirect\x00\x94\xDB\xDFc\xB5A\xD5\x16\xB3\xC3ng\x94J\xE7\x101jYF\x15Q\xE97\xCFg\x14\x12\x28\x3A\xFC\xDB40000\x20workflow\x2Dpr\x00\xC1\xD8Z9\x18\x60\xA2\xE2\xEF\xB0\xFC\xD7\x2Ah\xF07\x0D\xEC\x8A7\x7E\x1A\xAAn\x13\x9C\xEC\x05s\xE8\xBDf\x00"
|
|
|
|
ch := make(chan byte, 2000)
|
|
for _, b := range []byte(data) {
|
|
ch <- b
|
|
}
|
|
|
|
tree, err := parseGitTree(ch)
|
|
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
|
|
found := false
|
|
for _, item := range tree.items {
|
|
t.Log(item)
|
|
if item.name == "workflow-pr" && item.hash == "c1d85a391860a2e2efb0fcd72a68f0370dec8a377e1aaa6e139cec0573e8bd66" && item.isTree() {
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
if !found {
|
|
t.Error("expected submodule not found")
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestCommitTreeParsing(t *testing.T) {
|
|
gitDir := t.TempDir()
|
|
testDir, _ := os.Getwd()
|
|
var commitId string
|
|
|
|
cmd := exec.Command("/usr/bin/bash", path.Join(testDir, "tsetup.sh"))
|
|
cmd.Dir = gitDir
|
|
cmd.Stdout = writeFunc(func(data []byte) (int, error) {
|
|
commitId = commitId + strings.TrimSpace(string(data))
|
|
return len(data), nil
|
|
})
|
|
if err := cmd.Run(); err != nil {
|
|
t.Fatal(err.Error())
|
|
}
|
|
|
|
gh, err := AllocateGitWorkTree(gitDir, "", "")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
t.Run("GitCatFile commit", func(t *testing.T) {
|
|
h, _ := gh.ReadExistingPath(".")
|
|
defer h.Close()
|
|
|
|
file, err := h.GitCatFile("", commitId, "help")
|
|
if err != nil {
|
|
t.Error("failed", err)
|
|
}
|
|
|
|
if string(file) != "help\n" {
|
|
t.Error("expected 'help\\n' but got", string(file))
|
|
}
|
|
})
|
|
|
|
t.Run("GitCatFile commit", func(t *testing.T) {
|
|
h, _ := gh.ReadExistingPath(".")
|
|
defer h.Close()
|
|
|
|
file, err := h.GitCatFile("", "HEAD", "help")
|
|
if err != nil {
|
|
t.Error("failed", err)
|
|
}
|
|
|
|
if string(file) != "help\n" {
|
|
t.Error("expected 'help\\n' but got", string(file))
|
|
}
|
|
})
|
|
|
|
t.Run("GitCatFile bad commit", func(t *testing.T) {
|
|
h, _ := gh.ReadExistingPath(".")
|
|
defer h.Close()
|
|
|
|
file, err := h.GitCatFile("", "518b468f391bf01d5d76d497d7cbecfa8b46d185714cf8745800ae18afb21afd", "help")
|
|
if err == nil {
|
|
t.Error("expected error, but not nothing")
|
|
}
|
|
|
|
if string(file) != "" {
|
|
t.Error("expected 'help\\n' but got", file)
|
|
}
|
|
})
|
|
|
|
t.Run("reads HEAD and parses the tree", func(t *testing.T) {
|
|
const nodejs21 = "c678c57007d496a98bec668ae38f2c26a695f94af78012f15d044ccf066ccb41"
|
|
h, _ := gh.ReadExistingPath(".")
|
|
defer h.Close()
|
|
|
|
id, ok := h.GitSubmoduleCommitId("", "nodejs21", commitId)
|
|
if !ok {
|
|
t.Error("failed parse")
|
|
}
|
|
if id != nodejs21 {
|
|
t.Errorf("hash doesn't match: %s vs. expected %s", id, nodejs21)
|
|
}
|
|
})
|
|
|
|
t.Run("reads README.md", func(t *testing.T) {
|
|
h, _ := gh.ReadExistingPath(".")
|
|
defer h.Close()
|
|
|
|
data, err := h.GitCatFile("", commitId, "README.md")
|
|
if err != nil {
|
|
t.Errorf("failed parse: %v", err)
|
|
}
|
|
if string(data) != "foo\n" || len(data) != 4 {
|
|
t.Errorf("Wrong data of len: %d", len(data))
|
|
}
|
|
})
|
|
|
|
t.Run("read HEAD", func(t *testing.T) {
|
|
h, _ := gh.ReadExistingPath(".")
|
|
defer h.Close()
|
|
|
|
data, err := h.GitSubmoduleList("", "HEAD")
|
|
if err != nil {
|
|
t.Error("failed to get submodule list", err)
|
|
}
|
|
|
|
if len(data) != 5 {
|
|
t.Error("Invalid len of submodules", len(data))
|
|
}
|
|
})
|
|
|
|
t.Run("try to parse unknown item", func(t *testing.T) {
|
|
})
|
|
}
|
|
|
|
func TestGitStatusParse(t *testing.T) {
|
|
testData := []struct {
|
|
name string
|
|
data []byte
|
|
res []GitStatusData
|
|
}{
|
|
{
|
|
name: "Single modified line",
|
|
data: []byte("1 .M N... 100644 100644 100644 dbe4b3d5a0a2e385f78fd41d726baa20e9190f7b5a2e78cbd4885586832f39e7 dbe4b3d5a0a2e385f78fd41d726baa20e9190f7b5a2e78cbd4885586832f39e7 bots-common/git_utils.go\x00"),
|
|
res: []GitStatusData{
|
|
{
|
|
Path: "bots-common/git_utils.go",
|
|
Status: GitStatus_Modified,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "Untracked entries",
|
|
data: []byte("1 .M N... 100644 100644 100644 dbe4b3d5a0a2e385f78fd41d726baa20e9190f7b5a2e78cbd4885586832f39e7 dbe4b3d5a0a2e385f78fd41d726baa20e9190f7b5a2e78cbd4885586832f39e7 bots-common/git_utils.go\x00? bots-common/c.out\x00? doc/Makefile\x00"),
|
|
res: []GitStatusData{
|
|
{
|
|
Path: "bots-common/git_utils.go",
|
|
Status: GitStatus_Modified,
|
|
},
|
|
{
|
|
Path: "bots-common/c.out",
|
|
Status: GitStatus_Untracked,
|
|
},
|
|
{
|
|
Path: "doc/Makefile",
|
|
Status: GitStatus_Untracked,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "Untracked entries",
|
|
data: []byte("1 .M N... 100644 100644 100644 dbe4b3d5a0a2e385f78fd41d726baa20e9190f7b5a2e78cbd4885586832f39e7 dbe4b3d5a0a2e385f78fd41d726baa20e9190f7b5a2e78cbd4885586832f39e7 bots-common/git_utils.go\x00? bots-common/c.out\x00! doc/Makefile\x00"),
|
|
res: []GitStatusData{
|
|
{
|
|
Path: "bots-common/git_utils.go",
|
|
Status: GitStatus_Modified,
|
|
},
|
|
{
|
|
Path: "bots-common/c.out",
|
|
Status: GitStatus_Untracked,
|
|
},
|
|
{
|
|
Path: "doc/Makefile",
|
|
Status: GitStatus_Ignored,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "Nothing",
|
|
},
|
|
{
|
|
name: "Unmerged .gitmodules during a merge",
|
|
data: []byte("1 A. S... 000000 160000 160000 0000000000000000000000000000000000000000000000000000000000000000 ed07665aea0522096c88a7555f1fa9009ed0e0bac92de4613c3479516dd3d147 pkgB2\x00u UU N... 100644 100644 100644 100644 587ec403f01113f2629da538f6e14b84781f70ac59c41aeedd978ea8b1253a76 d23eb05d9ca92883ab9f4d28f3ec90c05f667f3a5c8c8e291bd65e03bac9ae3c 087b1d5f22dbf0aa4a879fff27fff03568b334c90daa5f2653f4a7961e24ea33 .gitmodules\x00"),
|
|
res: []GitStatusData{
|
|
{
|
|
Path: "pkgB2",
|
|
Status: GitStatus_Modified,
|
|
},
|
|
{
|
|
Path: ".gitmodules",
|
|
Status: GitStatus_Unmerged,
|
|
States: [3]string{"587ec403f01113f2629da538f6e14b84781f70ac59c41aeedd978ea8b1253a76", "d23eb05d9ca92883ab9f4d28f3ec90c05f667f3a5c8c8e291bd65e03bac9ae3c", "087b1d5f22dbf0aa4a879fff27fff03568b334c90daa5f2653f4a7961e24ea33"},
|
|
|
|
SubmoduleChanges: "N...",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "Renamed file",
|
|
data: []byte("1 M. N... 100644 100644 100644 d23eb05d9ca92883ab9f4d28f3ec90c05f667f3a5c8c8e291bd65e03bac9ae3c 896cd09f36d39e782d66ae32dd5614d4f4d83fc689f132aab2dfc019a9f5b6f3 .gitmodules\x002 R. S... 160000 160000 160000 3befe051a34612530acfa84c736d2454278453ec0f78ec028f25d2980f8c3559 3befe051a34612530acfa84c736d2454278453ec0f78ec028f25d2980f8c3559 R100 pkgQ\x00pkgC\x00"),
|
|
res: []GitStatusData{
|
|
{
|
|
Path: "pkgQ",
|
|
Status: GitStatus_Renamed,
|
|
States: [3]string{"pkgC"},
|
|
},
|
|
{
|
|
Path: ".gitmodules",
|
|
Status: GitStatus_Modified,
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, test := range testData {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
r, err := parseGitStatusData(bufio.NewReader(bytes.NewReader(test.data)))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(r) != len(test.res) {
|
|
t.Fatal("len(r):", len(r), "is not expected", len(test.res))
|
|
}
|
|
|
|
for _, expected := range test.res {
|
|
if !slices.Contains(r, expected) {
|
|
t.Fatal("result", r, "doesn't contains expected", expected)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|