Skip to content

Commit

Permalink
rewrite parse submodule
Browse files Browse the repository at this point in the history
  • Loading branch information
lunny committed Nov 20, 2024
1 parent f96ddce commit 2932f07
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 32 deletions.
25 changes: 4 additions & 21 deletions modules/git/commit.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,13 @@ import (
"bytes"
"context"
"errors"
"fmt"
"io"
"os/exec"
"strconv"
"strings"

"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/util"

"github.com/go-git/go-git/v5/config"
)

// Commit represents a git commit.
Expand Down Expand Up @@ -373,34 +370,20 @@ func (c *Commit) GetSubModules() (*ObjectCache, error) {
return nil, err
}

content, err := entry.Blob().GetBlobContent(10 * 1024)
rd, err := entry.Blob().DataAsync()
if err != nil {
return nil, err
}
defer rd.Close()

c.submoduleCache, err = parseSubmoduleContent([]byte(content))
r := io.LimitReader(rd, 100*1024) // limit to 100KB
c.submoduleCache, err = parseSubmoduleContent(r)
if err != nil {
return nil, err
}
return c.submoduleCache, nil
}

func parseSubmoduleContent(bs []byte) (*ObjectCache, error) {
cfg := config.NewModules()
if err := cfg.Unmarshal(bs); err != nil {
return nil, err
}
submoduleCache := newObjectCache()
if len(cfg.Submodules) == 0 {
return nil, fmt.Errorf("no submodules found")
}
for _, subModule := range cfg.Submodules {
submoduleCache.Set(subModule.Path, subModule.URL)
}

return submoduleCache, nil
}

// GetSubModule get the sub module according entryname
func (c *Commit) GetSubModule(entryname string) (*SubModule, error) {
modules, err := c.GetSubModules()
Expand Down
33 changes: 24 additions & 9 deletions modules/git/commit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -365,30 +365,45 @@ func Test_GetCommitBranchStart(t *testing.T) {

func Test_parseSubmoduleContent(t *testing.T) {
submoduleFiles := []struct {
fileContent string
expectedPath string
expectedURL string
fileContent string
expectedPath string
expectedURL string
expectedBranch string
}{
{
fileContent: `[submodule "jakarta-servlet"]
url = ../../ALP-pool/jakarta-servlet
path = jakarta-servlet`,
expectedPath: "jakarta-servlet",
expectedURL: "../../ALP-pool/jakarta-servlet",
expectedPath: "jakarta-servlet",
expectedURL: "../../ALP-pool/jakarta-servlet",
expectedBranch: "",
},
{
fileContent: `[submodule "jakarta-servlet"]
path = jakarta-servlet
url = ../../ALP-pool/jakarta-servlet`,
expectedPath: "jakarta-servlet",
expectedURL: "../../ALP-pool/jakarta-servlet",
expectedPath: "jakarta-servlet",
expectedURL: "../../ALP-pool/jakarta-servlet",
expectedBranch: "",
},
{
fileContent: `[submodule "jakarta-servlet"]
path = jakarta-servlet
url = ../../ALP-pool/jakarta-servlet
branch = stable`,
expectedPath: "jakarta-servlet",
expectedURL: "../../ALP-pool/jakarta-servlet",
expectedBranch: "stable",
},
}
for _, kase := range submoduleFiles {
submodule, err := parseSubmoduleContent([]byte(kase.fileContent))
submodule, err := parseSubmoduleContent(strings.NewReader(kase.fileContent))
assert.NoError(t, err)
v, ok := submodule.Get(kase.expectedPath)
assert.True(t, ok)
assert.Equal(t, kase.expectedURL, v)
subModule := v.(*SubModule)
assert.Equal(t, kase.expectedPath, subModule.Path)
assert.Equal(t, kase.expectedURL, subModule.URL)
assert.Equal(t, kase.expectedBranch, subModule.Branch)
}
}
70 changes: 68 additions & 2 deletions modules/git/submodule.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
package git

import (
"bufio"
"fmt"
"io"
"net"
"net/url"
"path"
Expand All @@ -17,8 +19,72 @@ var scpSyntax = regexp.MustCompile(`^([a-zA-Z0-9_]+@)?([a-zA-Z0-9._-]+):(.*)$`)

// SubModule submodule is a reference on git repository
type SubModule struct {
Name string
URL string
Path string
URL string
Branch string
}

// parseSubmoduleContent this is not a complete parse for gitmodules file, it only
// parses the url and path of submodules
func parseSubmoduleContent(r io.Reader) (*ObjectCache, error) {
var path, url, branch string
var state int // 0: find section, 1: find path and url
subModules := newObjectCache()
scanner := bufio.NewScanner(r)
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())

// Skip empty lines and comments
if line == "" || strings.HasPrefix(line, "#") || strings.HasPrefix(line, ";") {
continue
}

// Section header [section]
if strings.HasPrefix(line, "[submodule") && strings.HasSuffix(line, "]") {
subModules.Set(path, &SubModule{
Path: path,
URL: url,
Branch: branch,
})
state = 1
path = ""
url = ""
branch = ""
continue
}

if state != 1 {
continue
}

parts := strings.SplitN(line, "=", 2)
if len(parts) != 2 {
continue
}
key := strings.TrimSpace(parts[0])
value := strings.TrimSpace(parts[1])
switch key {
case "path":
path = value
case "url":
url = value
case "branch":
branch = value
}
}

if err := scanner.Err(); err != nil {
return nil, fmt.Errorf("error reading file: %w", err)
}
if path != "" && url != "" {
subModules.Set(path, &SubModule{
Path: path,
URL: url,
Branch: branch,
})
}

return subModules, nil
}

// SubModuleFile represents a file with submodule type.
Expand Down

0 comments on commit 2932f07

Please sign in to comment.