git.status
This commit is contained in:
parent
5108019db0
commit
d5dbb37e18
@ -19,6 +19,9 @@ package common
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
@ -549,7 +552,7 @@ func (e *GitHandlerImpl) GitParseCommits(cwd string, commitIDs []string) (parsed
|
|||||||
cmd.Stdin = &data_out
|
cmd.Stdin = &data_out
|
||||||
cmd.Stderr = writeFunc(func(data []byte) (int, error) {
|
cmd.Stderr = writeFunc(func(data []byte) (int, error) {
|
||||||
if e.DebugLogger {
|
if e.DebugLogger {
|
||||||
log.Printf(string(data))
|
log.Println(string(data))
|
||||||
}
|
}
|
||||||
return len(data), nil
|
return len(data), nil
|
||||||
})
|
})
|
||||||
@ -613,7 +616,7 @@ func (e *GitHandlerImpl) GitCatFile(cwd, commitId, filename string) (data []byte
|
|||||||
cmd.Stdin = &data_out
|
cmd.Stdin = &data_out
|
||||||
cmd.Stderr = writeFunc(func(data []byte) (int, error) {
|
cmd.Stderr = writeFunc(func(data []byte) (int, error) {
|
||||||
if e.DebugLogger {
|
if e.DebugLogger {
|
||||||
log.Printf(string(data))
|
log.Println(string(data))
|
||||||
}
|
}
|
||||||
return len(data), nil
|
return len(data), nil
|
||||||
})
|
})
|
||||||
@ -753,3 +756,166 @@ func (e *GitHandlerImpl) GitSubmoduleCommitId(cwd, packageName, commitId string)
|
|||||||
wg.Wait()
|
wg.Wait()
|
||||||
return subCommitId, len(subCommitId) == len(commitId)
|
return subCommitId, len(subCommitId) == len(commitId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
GitStatus_Untracked = 0
|
||||||
|
GitStatus_Modified = 1
|
||||||
|
GitStatus_Ignored = 2
|
||||||
|
GitStatus_Unmerged = 3
|
||||||
|
)
|
||||||
|
|
||||||
|
type GitStatusData struct {
|
||||||
|
Path string
|
||||||
|
Status int
|
||||||
|
States [3]string
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseGitStatusHexString(data io.ByteReader) (string, error) {
|
||||||
|
str := make([]byte, 0, 32)
|
||||||
|
for {
|
||||||
|
c, err := data.ReadByte()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
switch {
|
||||||
|
case c == 0 || c == ' ':
|
||||||
|
return string(str), nil
|
||||||
|
case c >= 'a' && c <= 'f':
|
||||||
|
case c >= 'A' && c <= 'F':
|
||||||
|
case c >= '0' && c <= '9':
|
||||||
|
default:
|
||||||
|
return "", errors.New("Invalid character in hex string:" + string(c))
|
||||||
|
}
|
||||||
|
str = append(str, c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func parseGitStatusString(data io.ByteReader) (string, error) {
|
||||||
|
str := make([]byte, 0, 100)
|
||||||
|
for {
|
||||||
|
c, err := data.ReadByte()
|
||||||
|
if err != nil {
|
||||||
|
return "", errors.New("Unexpected EOF. Expected NUL string term")
|
||||||
|
}
|
||||||
|
if c == 0 {
|
||||||
|
return string(str), nil
|
||||||
|
}
|
||||||
|
str = append(str, c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func skipGitStatusEntry(data io.ByteReader, skipSpaceLen int) error {
|
||||||
|
for skipSpaceLen > 0 {
|
||||||
|
c, err := data.ReadByte()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if c == ' ' {
|
||||||
|
skipSpaceLen--
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseSingleStatusEntry(data io.ByteReader) (*GitStatusData, error) {
|
||||||
|
ret := GitStatusData{}
|
||||||
|
statusType, err := data.ReadByte()
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
switch statusType {
|
||||||
|
case '1':
|
||||||
|
var err error
|
||||||
|
if err = skipGitStatusEntry(data, 8); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ret.Status = GitStatus_Modified
|
||||||
|
ret.Path, err = parseGitStatusString(data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
case '?':
|
||||||
|
var err error
|
||||||
|
if err = skipGitStatusEntry(data, 1); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ret.Status = GitStatus_Untracked
|
||||||
|
ret.Path, err = parseGitStatusString(data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
case '!':
|
||||||
|
var err error
|
||||||
|
if err = skipGitStatusEntry(data, 1); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ret.Status = GitStatus_Ignored
|
||||||
|
ret.Path, err = parseGitStatusString(data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
case 'u':
|
||||||
|
var err error
|
||||||
|
if err = skipGitStatusEntry(data, 7); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if ret.States[0], err = parseGitStatusHexString(data); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if ret.States[1], err = parseGitStatusHexString(data); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if ret.States[2], err = parseGitStatusHexString(data); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ret.Status = GitStatus_Unmerged
|
||||||
|
ret.Path, err = parseGitStatusString(data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return nil, errors.New("Invalid status type" + string(statusType))
|
||||||
|
}
|
||||||
|
return &ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseGitStatusData(data io.ByteReader) ([]GitStatusData, error) {
|
||||||
|
ret := make([]GitStatusData, 0, 10)
|
||||||
|
for {
|
||||||
|
data, err := parseSingleStatusEntry(data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else if data == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = append(ret, *data)
|
||||||
|
}
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *GitHandlerImpl) Status(cwd string) (ret []GitStatusData, err error) {
|
||||||
|
if e.DebugLogger {
|
||||||
|
log.Println("getting git-status()")
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd := exec.Command("/usr/bin/git", "status", "--porcelain=2", "-z")
|
||||||
|
cmd.Env = []string{
|
||||||
|
"GIT_CEILING_DIRECTORIES=" + e.GitPath,
|
||||||
|
"GIT_CONFIG_GLOBAL=/dev/null",
|
||||||
|
}
|
||||||
|
cmd.Dir = filepath.Join(e.GitPath, cwd)
|
||||||
|
cmd.Stderr = writeFunc(func(data []byte) (int, error) {
|
||||||
|
log.Println(string(data))
|
||||||
|
return len(data), nil
|
||||||
|
})
|
||||||
|
if e.DebugLogger {
|
||||||
|
log.Printf("command run: %v\n", cmd.Args)
|
||||||
|
}
|
||||||
|
out, err := cmd.Output()
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error running command %v, err: %v", cmd.Args, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return parseGitStatusData(bufio.NewReader(bytes.NewReader(out)))
|
||||||
|
}
|
||||||
|
@ -19,9 +19,12 @@ package common
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
|
"bytes"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path"
|
"path"
|
||||||
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
@ -302,3 +305,94 @@ func TestCommitTreeParsingOfHead(t *testing.T) {
|
|||||||
t.Run("try to parse unknown item", func(t *testing.T) {
|
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"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -3,6 +3,7 @@ package main
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"slices"
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@ -124,17 +125,25 @@ func (rs *PRSet) Merge() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
git.GitExecOrPanic("", "clone", "--depth", "1", prjgit.Base.Repo.SSHURL, common.DefaultGitPrj)
|
git.GitExecOrPanic("", "clone", "--depth", "1", prjgit.Base.Repo.SSHURL, common.DefaultGitPrj)
|
||||||
git.GitExecOrPanic(common.DefaultGitPrj, "fetch", common.DefaultGitPrj, "origin", prjgit.Base.Sha, prjgit.Head.Sha)
|
git.GitExecOrPanic(common.DefaultGitPrj, "fetch", "origin", prjgit.Base.Sha, prjgit.Head.Sha)
|
||||||
|
|
||||||
// if other changes merged, check if we have conflicts
|
// if other changes merged, check if we have conflicts
|
||||||
|
rev := strings.TrimSpace(git.GitExecWithOutputOrPanic(common.DefaultGitPrj, "merge-base", "HEAD", prjgit.Base.Sha, prjgit.Head.Sha))
|
||||||
|
if rev != prjgit.Base.Sha {
|
||||||
|
return fmt.Errorf("Base.Sha (%s) not yet merged into project-git. Aborting merge.", prjgit.Base.Sha)
|
||||||
|
}
|
||||||
|
/*
|
||||||
rev := git.GitExecWithOutputOrPanic(common.DefaultGitPrj, "rev-list", "-1", "HEAD")
|
rev := git.GitExecWithOutputOrPanic(common.DefaultGitPrj, "rev-list", "-1", "HEAD")
|
||||||
if rev != prjgit.Base.Sha {
|
if rev != prjgit.Base.Sha {
|
||||||
panic("FIXME")
|
panic("FIXME")
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
msg := "haha"
|
msg := "haha"
|
||||||
|
|
||||||
git.GitExecOrPanic(common.DefaultGitPrj, "merge", "--no-ff", "-m", msg, prjgit.Head.Sha)
|
err = git.GitExec(common.DefaultGitPrj, "merge", "--no-ff", "-m", msg, prjgit.Head.Sha)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
git.GitExecOrPanic(common.DefaultGitPrj, "push", "origin")
|
git.GitExecOrPanic(common.DefaultGitPrj, "push", "origin")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path"
|
"path"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"go.uber.org/mock/gomock"
|
"go.uber.org/mock/gomock"
|
||||||
@ -227,20 +228,85 @@ func TestPRMerge(t *testing.T) {
|
|||||||
t.Fatal(string(out))
|
t.Fatal(string(out))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
common.ExtraGitParams = []string{
|
||||||
|
"GIT_CONFIG_COUNT=1",
|
||||||
|
"GIT_CONFIG_KEY_0=protocol.file.allow",
|
||||||
|
"GIT_CONFIG_VALUE_0=always",
|
||||||
|
|
||||||
|
"GIT_AUTHOR_NAME=testname",
|
||||||
|
"GIT_AUTHOR_EMAIL=test@suse.com",
|
||||||
|
"GIT_AUTHOR_DATE='2005-04-07T22:13:13'",
|
||||||
|
"GIT_COMMITTER_NAME=testname",
|
||||||
|
"GIT_COMMITTER_EMAIL=test@suse.com",
|
||||||
|
"GIT_COMMITTER_DATE='2005-04-07T22:13:13'",
|
||||||
|
}
|
||||||
|
|
||||||
|
config := &common.AutogitConfig{
|
||||||
|
Organization: "org",
|
||||||
|
GitProjectName: "prj",
|
||||||
|
}
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
prjgit_base, prjgit_head string
|
pr *models.PullRequest
|
||||||
|
mergeError string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "Merge conflicts in submodules",
|
name: "Merge base not merged in main",
|
||||||
prjgit_base: "base_add_b1",
|
|
||||||
prjgit_head: "base_add_b2",
|
pr: &models.PullRequest{
|
||||||
|
Base: &models.PRBranchInfo{
|
||||||
|
Sha: "e8b0de43d757c96a9d2c7101f4bff404e322f53a1fa4041fb85d646110c38ad4", // "base_add_b1"
|
||||||
|
Repo: &models.Repository{
|
||||||
|
Name: "prj",
|
||||||
|
Owner: &models.User{
|
||||||
|
UserName: "org",
|
||||||
|
},
|
||||||
|
SSHURL: path.Join(cmd.Dir, "prjgit"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Head: &models.PRBranchInfo {
|
||||||
|
Sha: "88584433de1c917c1d773f62b82381848d882491940b5e9b427a540aa9057d9a", // "base_add_b2"
|
||||||
|
},
|
||||||
|
},
|
||||||
|
mergeError: "Aborting merge",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Merge conflict in modules",
|
||||||
|
|
||||||
|
pr: &models.PullRequest{
|
||||||
|
Base: &models.PRBranchInfo{
|
||||||
|
Sha: "4fbd1026b2d7462ebe9229a49100c11f1ad6555520a21ba515122d8bc41328a8",
|
||||||
|
Repo: &models.Repository{
|
||||||
|
Name: "prj",
|
||||||
|
Owner: &models.User{
|
||||||
|
UserName: "org",
|
||||||
|
},
|
||||||
|
SSHURL: path.Join(cmd.Dir, "prjgit"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Head: &models.PRBranchInfo {
|
||||||
|
Sha: "88584433de1c917c1d773f62b82381848d882491940b5e9b427a540aa9057d9a", // "base_add_b2"
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
ctl := gomock.NewController(t)
|
||||||
|
mock := mock_common.NewMockGiteaPRFetcher(ctl)
|
||||||
|
|
||||||
|
mock.EXPECT().GetPullRequest("org", "prj", int64(1)).Return(test.pr, nil)
|
||||||
|
|
||||||
|
set, err := FetchPRSet(mock, "org", "prj", 1, config)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = set.Merge(); err != nil && (test.mergeError == "" || (len(test.mergeError) > 0 && !strings.Contains(err.Error(), test.mergeError))) {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,15 +20,14 @@ create_prjgit_sample() {
|
|||||||
mkdir prjgit
|
mkdir prjgit
|
||||||
pushd prjgit
|
pushd prjgit
|
||||||
|
|
||||||
git init -q --object-format=sha256
|
git init -q --object-format=sha256 -b main
|
||||||
echo Project git is here > README.md
|
echo Project git is here > README.md
|
||||||
git add README.md
|
git add README.md
|
||||||
|
|
||||||
git submodule init -b main
|
git submodule init
|
||||||
git submodule -q add ../pkgA pkgA
|
git submodule -q add ../pkgA pkgA
|
||||||
git submodule -q add ../pkgB pkgB
|
git submodule -q add ../pkgB pkgB
|
||||||
git submodule -q add ../pkgC pkgC
|
git submodule -q add ../pkgC pkgC
|
||||||
|
|
||||||
git commit -q -m 'first commit'
|
git commit -q -m 'first commit'
|
||||||
|
|
||||||
git checkout -b base_add_b1 main
|
git checkout -b base_add_b1 main
|
||||||
@ -36,9 +35,15 @@ create_prjgit_sample() {
|
|||||||
git commit -q -m "pkgB1 added"
|
git commit -q -m "pkgB1 added"
|
||||||
|
|
||||||
git checkout -b base_add_b2 main
|
git checkout -b base_add_b2 main
|
||||||
|
git clean -ffxd
|
||||||
git submodule -q add ../pkgB2 pkgB2
|
git submodule -q add ../pkgB2 pkgB2
|
||||||
git commit -q -m "pkgB2 added"
|
git commit -q -m "pkgB2 added"
|
||||||
|
|
||||||
|
git checkout main
|
||||||
|
git clean -ffxd
|
||||||
|
git submodule -q add -f ../pkgB1 pkgB1
|
||||||
|
git commit -q -m "main adding pkgB1"
|
||||||
|
|
||||||
popd
|
popd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user