Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions modules/git/commit_submodule_file.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import (
"path"
"regexp"
"strings"

"code.gitea.io/gitea/modules/setting"
)

var scpSyntax = regexp.MustCompile(`^([a-zA-Z0-9_]+@)?([a-zA-Z0-9._-]+):(.*)$`)
Expand Down Expand Up @@ -101,8 +103,8 @@ func getRefURL(refURL, urlPrefix, repoFullName, sshDomain string) string {

// RefURL guesses and returns reference URL.
// FIXME: template passes AppURL as urlPrefix, it needs to figure out the correct approach (no hard-coded AppURL anymore)
func (sf *CommitSubModuleFile) RefURL(urlPrefix, repoFullName, sshDomain string) string {
return getRefURL(sf.refURL, urlPrefix, repoFullName, sshDomain)
func (sf *CommitSubModuleFile) RefURL(repoFullName string) string {
return getRefURL(sf.refURL, setting.AppURL, repoFullName, setting.SSH.Domain)
}

// RefID returns reference ID.
Expand Down
3 changes: 3 additions & 0 deletions options/locale/locale_en-US.ini
Original file line number Diff line number Diff line change
Expand Up @@ -2627,6 +2627,9 @@ diff.image.overlay = Overlay
diff.has_escaped = This line has hidden Unicode characters
diff.show_file_tree = Show file tree
diff.hide_file_tree = Hide file tree
diff.submodule_added = Submodule %s added at %s
diff.submodule_deleted = Submodule %s deleted from %s
diff.submodule_updated = Submodule %s updated from %s to %s

releases.desc = Track project versions and downloads.
release.releases = Releases
Expand Down
1 change: 0 additions & 1 deletion routers/web/repo/view.go
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,6 @@ func renderDirectoryFiles(ctx *context.Context, timeout time.Duration) git.Entri
}

ctx.Data["TreeLink"] = treeLink
ctx.Data["SSHDomain"] = setting.SSH.Domain

return allEntries
}
Expand Down
35 changes: 29 additions & 6 deletions services/gitdiff/gitdiff.go
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,6 @@ type DiffFile struct {
IsLFSFile bool
IsRenamed bool
IsAmbiguous bool
IsSubmodule bool
Sections []*DiffSection
IsIncomplete bool
IsIncompleteLineTooLong bool
Expand All @@ -372,6 +371,9 @@ type DiffFile struct {
Language string
Mode string
OldMode string

IsSubmodule bool // if IsSubmodule==true, then there must be a SubmoduleInfo
SubmoduleInfo *SubmoduleInfo
}

// GetType returns type of diff file.
Expand Down Expand Up @@ -609,9 +611,8 @@ parsingLoop:
if strings.HasPrefix(line, "new mode ") {
curFile.Mode = prepareValue(line, "new mode ")
}

if strings.HasSuffix(line, " 160000\n") {
curFile.IsSubmodule = true
curFile.IsSubmodule, curFile.SubmoduleInfo = true, &SubmoduleInfo{}
}
case strings.HasPrefix(line, "rename from "):
curFile.IsRenamed = true
Expand Down Expand Up @@ -646,17 +647,17 @@ parsingLoop:
curFile.Mode = prepareValue(line, "new file mode ")
}
if strings.HasSuffix(line, " 160000\n") {
curFile.IsSubmodule = true
curFile.IsSubmodule, curFile.SubmoduleInfo = true, &SubmoduleInfo{}
}
case strings.HasPrefix(line, "deleted"):
curFile.Type = DiffFileDel
curFile.IsDeleted = true
if strings.HasSuffix(line, " 160000\n") {
curFile.IsSubmodule = true
curFile.IsSubmodule, curFile.SubmoduleInfo = true, &SubmoduleInfo{}
}
case strings.HasPrefix(line, "index"):
if strings.HasSuffix(line, " 160000\n") {
curFile.IsSubmodule = true
curFile.IsSubmodule, curFile.SubmoduleInfo = true, &SubmoduleInfo{}
}
case strings.HasPrefix(line, "similarity index 100%"):
curFile.Type = DiffFileRename
Expand Down Expand Up @@ -915,6 +916,13 @@ func parseHunks(ctx context.Context, curFile *DiffFile, maxLines, maxLineCharact
}
}
curSection.Lines = append(curSection.Lines, diffLine)

// Parse submodule additions
if curFile.SubmoduleInfo != nil {
if ref, found := bytes.CutPrefix(lineBytes, []byte("+Subproject commit ")); found {
curFile.SubmoduleInfo.NewRefID = string(bytes.TrimSpace(ref))
}
}
case '-':
curFileLinesCount++
curFile.Deletion++
Expand All @@ -936,6 +944,13 @@ func parseHunks(ctx context.Context, curFile *DiffFile, maxLines, maxLineCharact
lastLeftIdx = len(curSection.Lines)
}
curSection.Lines = append(curSection.Lines, diffLine)

// Parse submodule deletion
if curFile.SubmoduleInfo != nil {
if ref, found := bytes.CutPrefix(lineBytes, []byte("-Subproject commit ")); found {
curFile.SubmoduleInfo.PreviousRefID = string(bytes.TrimSpace(ref))
}
}
case ' ':
curFileLinesCount++
if maxLines > -1 && curFileLinesCount >= maxLines {
Expand Down Expand Up @@ -1195,6 +1210,14 @@ func GetDiff(ctx context.Context, gitRepo *git.Repository, opts *DiffOptions, fi
}
}

// Populate Submodule URLs
if diffFile.SubmoduleInfo != nil {
err := diffFile.SubmoduleInfo.PopulateURL(diffFile, beforeCommit, commit)
if err != nil {
return nil, err
}
}

if !isVendored.Has() {
isVendored = optional.Some(analyze.IsVendor(diffFile.Name))
}
Expand Down
55 changes: 55 additions & 0 deletions services/gitdiff/submodule.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Copyright 2025 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT

package gitdiff

import "code.gitea.io/gitea/modules/git"

type SubmoduleInfo struct {
SubmoduleURL string
NewRefID string
PreviousRefID string
}

func (si *SubmoduleInfo) PopulateURL(diffFile *DiffFile, leftCommit, rightCommit *git.Commit) error {
// If the submodule is removed, we need to check it at the left commit
if diffFile.IsDeleted {
if leftCommit == nil {
return nil
}

submodule, err := leftCommit.GetSubModule(diffFile.GetDiffFileName())
if err != nil {
return err
}

if submodule != nil {
si.SubmoduleURL = submodule.URL
}

return nil
}

// Even if the submodule path is updated, we check this at the right commit
submodule, err := rightCommit.GetSubModule(diffFile.Name)
if err != nil {
return err
}

if submodule != nil {
si.SubmoduleURL = submodule.URL
}
return nil
}

func (si *SubmoduleInfo) RefID() string {
if si.NewRefID != "" {
return si.NewRefID
}
return si.PreviousRefID
}

// RefURL guesses and returns reference URL.
func (si *SubmoduleInfo) RefURL(repoFullName string) string {
return git.NewCommitSubModuleFile(si.SubmoduleURL, si.RefID()).RefURL(repoFullName)
}
Loading
Loading