Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use the type RefName for all the needed places and fix pull mirror sync bugs #24634

Merged
merged 33 commits into from
May 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
93ef964
Use the type RefName for all the needed places
lunny May 10, 2023
3cba605
Fix fmt
lunny May 10, 2023
4346019
revert some changes and fix tests
lunny May 10, 2023
a3bfbdb
Apply suggestions from code review
lunny May 10, 2023
13e683b
Fix lint
lunny May 10, 2023
aa99907
Merge branch 'lunny/ref_name' of github.com:lunny/gitea into lunny/re…
lunny May 10, 2023
1d1107a
Merge branch 'main' into lunny/ref_name
lunny May 10, 2023
ce9207c
Fix test
lunny May 10, 2023
40e37a4
revert some change
lunny May 10, 2023
3b61f56
handle more situation
lunny May 11, 2023
5517ec9
Merge branch 'main' into lunny/ref_name
lunny May 11, 2023
4261cc7
fetch tags when migrating a mirror repository
lunny May 11, 2023
6faac1e
make code simple
lunny May 11, 2023
4f4a538
Merge branch 'main' into lunny/ref_name
lunny May 11, 2023
5b31c36
Fix the problem
lunny May 11, 2023
b3b0728
Merge branch 'main' into lunny/ref_name
lunny May 11, 2023
8dcd65f
merge main branch
lunny May 25, 2023
87e1564
Use branch name when necessary
lunny May 25, 2023
c23a65d
Merge branch 'main' into lunny/ref_name
lunny May 25, 2023
82f60cb
refactor
lunny May 25, 2023
fb468ee
Add comment for using git fetch instead of git remote update when mir…
lunny May 25, 2023
a75fc99
merge main branch
lunny May 25, 2023
9dc05ca
Merge branch 'main' into lunny/ref_name
GiteaBot May 25, 2023
416d7cf
move variable
lunny May 25, 2023
09dd3b4
Merge branch 'main' into lunny/ref_name
GiteaBot May 25, 2023
21ad2ef
Merge branch 'main' into lunny/ref_name
GiteaBot May 25, 2023
59abc55
Merge branch 'main' into lunny/ref_name
GiteaBot May 25, 2023
70f619c
Fix test
lunny May 26, 2023
45323b1
Merge branch 'main' into lunny/ref_name
lunny May 26, 2023
666d0d0
Merge branch 'lunny/ref_name' of github.com:lunny/gitea into lunny/re…
lunny May 26, 2023
49d9813
Merge branch 'main' into lunny/ref_name
GiteaBot May 26, 2023
92e4ff8
More improvements
lunny May 26, 2023
c7ce833
Merge branch 'lunny/ref_name' of github.com:lunny/gitea into lunny/re…
lunny May 26, 2023
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
18 changes: 9 additions & 9 deletions cmd/hook.go
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ Gitea or set your environment appropriately.`, "")

oldCommitIDs := make([]string, hookBatchSize)
newCommitIDs := make([]string, hookBatchSize)
refFullNames := make([]string, hookBatchSize)
refFullNames := make([]git.RefName, hookBatchSize)
count := 0
total := 0
lastline := 0
Expand Down Expand Up @@ -236,14 +236,14 @@ Gitea or set your environment appropriately.`, "")

oldCommitID := string(fields[0])
newCommitID := string(fields[1])
refFullName := string(fields[2])
refFullName := git.RefName(fields[2])
total++
lastline++

// If the ref is a branch or tag, check if it's protected
// if supportProcReceive all ref should be checked because
// permission check was delayed
if supportProcReceive || strings.HasPrefix(refFullName, git.BranchPrefix) || strings.HasPrefix(refFullName, git.TagPrefix) {
if supportProcReceive || refFullName.IsBranch() || refFullName.IsTag() {
oldCommitIDs[count] = oldCommitID
newCommitIDs[count] = newCommitID
refFullNames[count] = refFullName
Expand Down Expand Up @@ -351,7 +351,7 @@ Gitea or set your environment appropriately.`, "")
}
oldCommitIDs := make([]string, hookBatchSize)
newCommitIDs := make([]string, hookBatchSize)
refFullNames := make([]string, hookBatchSize)
refFullNames := make([]git.RefName, hookBatchSize)
count := 0
total := 0
wasEmpty := false
Expand All @@ -373,7 +373,7 @@ Gitea or set your environment appropriately.`, "")
fmt.Fprintf(out, ".")
oldCommitIDs[count] = string(fields[0])
newCommitIDs[count] = string(fields[1])
refFullNames[count] = string(fields[2])
refFullNames[count] = git.RefName(fields[2])
if refFullNames[count] == git.BranchPrefix+"master" && newCommitIDs[count] != git.EmptySHA && count == total {
masterPushed = true
}
Expand Down Expand Up @@ -575,7 +575,7 @@ Gitea or set your environment appropriately.`, "")
}
hookOptions.OldCommitIDs = make([]string, 0, hookBatchSize)
hookOptions.NewCommitIDs = make([]string, 0, hookBatchSize)
hookOptions.RefFullNames = make([]string, 0, hookBatchSize)
hookOptions.RefFullNames = make([]git.RefName, 0, hookBatchSize)

for {
// note: pktLineTypeUnknow means pktLineTypeFlush and pktLineTypeData all allowed
Expand All @@ -593,7 +593,7 @@ Gitea or set your environment appropriately.`, "")
}
hookOptions.OldCommitIDs = append(hookOptions.OldCommitIDs, t[0])
hookOptions.NewCommitIDs = append(hookOptions.NewCommitIDs, t[1])
hookOptions.RefFullNames = append(hookOptions.RefFullNames, t[2])
hookOptions.RefFullNames = append(hookOptions.RefFullNames, git.RefName(t[2]))
}

hookOptions.GitPushOptions = make(map[string]string)
Expand Down Expand Up @@ -640,15 +640,15 @@ Gitea or set your environment appropriately.`, "")

for _, rs := range resp.Results {
if len(rs.Err) > 0 {
err = writeDataPktLine(ctx, os.Stdout, []byte("ng "+rs.OriginalRef+" "+rs.Err))
err = writeDataPktLine(ctx, os.Stdout, []byte("ng "+rs.OriginalRef.String()+" "+rs.Err))
if err != nil {
return err
}
continue
}

if rs.IsNotMatched {
err = writeDataPktLine(ctx, os.Stdout, []byte("ok "+rs.OriginalRef))
err = writeDataPktLine(ctx, os.Stdout, []byte("ok "+rs.OriginalRef.String()))
if err != nil {
return err
}
Expand Down
4 changes: 2 additions & 2 deletions models/actions/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ func (run *ActionRun) Link() string {
// RefLink return the url of run's ref
func (run *ActionRun) RefLink() string {
refName := git.RefName(run.Ref)
if refName.RefGroup() == "pull" {
if refName.IsPull() {
return run.Repo.Link() + "/pulls/" + refName.ShortName()
}
return git.RefURL(run.Repo.Link(), run.Ref)
Expand All @@ -79,7 +79,7 @@ func (run *ActionRun) RefLink() string {
// PrettyRef return #id for pull ref or ShortName for others
func (run *ActionRun) PrettyRef() string {
refName := git.RefName(run.Ref)
if refName.RefGroup() == "pull" {
if refName.IsPull() {
return "#" + strings.TrimSuffix(strings.TrimPrefix(run.Ref, git.PullPrefix), "/head")
}
return refName.ShortName()
Expand Down
13 changes: 1 addition & 12 deletions models/activities/action.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import (
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/util"

"xorm.io/builder"
"xorm.io/xorm/schemas"
Expand Down Expand Up @@ -367,17 +366,7 @@ func (a *Action) GetBranch() string {

// GetRefLink returns the action's ref link.
func (a *Action) GetRefLink() string {
switch {
case strings.HasPrefix(a.RefName, git.BranchPrefix):
return a.GetRepoLink() + "/src/branch/" + util.PathEscapeSegments(strings.TrimPrefix(a.RefName, git.BranchPrefix))
case strings.HasPrefix(a.RefName, git.TagPrefix):
return a.GetRepoLink() + "/src/tag/" + util.PathEscapeSegments(strings.TrimPrefix(a.RefName, git.TagPrefix))
case len(a.RefName) == git.SHAFullLength && git.IsValidSHAPattern(a.RefName):
return a.GetRepoLink() + "/src/commit/" + a.RefName
default:
// FIXME: we will just assume it's a branch - this was the old way - at some point we may want to enforce that there is always a ref here.
return a.GetRepoLink() + "/src/branch/" + util.PathEscapeSegments(strings.TrimPrefix(a.RefName, git.BranchPrefix))
}
return git.RefURL(a.GetRepoLink(), a.RefName)
}

// GetTag returns the action's repository tag.
Expand Down
8 changes: 4 additions & 4 deletions modules/actions/workflows.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ func matchPushEvent(commit *git.Commit, pushPayload *api.PushPayload, evt *jobpa
if err != nil {
break
}
if !workflowpattern.Skip(patterns, []string{refName.ShortName()}, &workflowpattern.EmptyTraceWriter{}) {
if !workflowpattern.Skip(patterns, []string{refName.BranchName()}, &workflowpattern.EmptyTraceWriter{}) {
matchTimes++
}
case "branches-ignore":
Expand All @@ -216,7 +216,7 @@ func matchPushEvent(commit *git.Commit, pushPayload *api.PushPayload, evt *jobpa
if err != nil {
break
}
if !workflowpattern.Filter(patterns, []string{refName.ShortName()}, &workflowpattern.EmptyTraceWriter{}) {
if !workflowpattern.Filter(patterns, []string{refName.BranchName()}, &workflowpattern.EmptyTraceWriter{}) {
matchTimes++
}
case "tags":
Expand All @@ -228,7 +228,7 @@ func matchPushEvent(commit *git.Commit, pushPayload *api.PushPayload, evt *jobpa
if err != nil {
break
}
if !workflowpattern.Skip(patterns, []string{refName.ShortName()}, &workflowpattern.EmptyTraceWriter{}) {
if !workflowpattern.Skip(patterns, []string{refName.TagName()}, &workflowpattern.EmptyTraceWriter{}) {
matchTimes++
}
case "tags-ignore":
Expand All @@ -240,7 +240,7 @@ func matchPushEvent(commit *git.Commit, pushPayload *api.PushPayload, evt *jobpa
if err != nil {
break
}
if !workflowpattern.Filter(patterns, []string{refName.ShortName()}, &workflowpattern.EmptyTraceWriter{}) {
if !workflowpattern.Filter(patterns, []string{refName.TagName()}, &workflowpattern.EmptyTraceWriter{}) {
lunny marked this conversation as resolved.
Show resolved Hide resolved
matchTimes++
}
case "paths":
Expand Down
125 changes: 104 additions & 21 deletions modules/git/ref.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ package git
import (
"regexp"
"strings"

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

const (
// RemotePrefix is the base directory of the remotes information of git.
RemotePrefix = "refs/remotes/"
// PullPrefix is the base directory of the pull information of git.
PullPrefix = "refs/pull/"

pullLen = len(PullPrefix)
)

// refNamePatternInvalid is regular expression with unallowed characters in git reference name
Expand Down Expand Up @@ -53,19 +53,32 @@ func (ref *Reference) Commit() (*Commit, error) {
return ref.repo.getCommit(ref.Object)
}

// ShortName returns the short name of the reference
func (ref *Reference) ShortName() string {
return RefName(ref.Name).ShortName()
}

// RefGroup returns the group type of the reference
func (ref *Reference) RefGroup() string {
return RefName(ref.Name).RefGroup()
}

// RefName represents a git reference name
// ForPrefix special ref to create a pull request: refs/for/<target-branch>/<topic-branch>
// or refs/for/<targe-branch> -o topic='<topic-branch>'
const ForPrefix = "refs/for/"

// TODO: /refs/for-review for suggest change interface

// RefName represents a full git reference name
type RefName string

func RefNameFromBranch(shortName string) RefName {
return RefName(BranchPrefix + shortName)
}

func RefNameFromTag(shortName string) RefName {
return RefName(TagPrefix + shortName)
}

func (ref RefName) String() string {
return string(ref)
}

func (ref RefName) IsBranch() bool {
return strings.HasPrefix(string(ref), BranchPrefix)
}
Expand All @@ -74,39 +87,109 @@ func (ref RefName) IsTag() bool {
return strings.HasPrefix(string(ref), TagPrefix)
}

func (ref RefName) IsRemote() bool {
return strings.HasPrefix(string(ref), RemotePrefix)
}

func (ref RefName) IsPull() bool {
return strings.HasPrefix(string(ref), PullPrefix) && strings.IndexByte(string(ref)[len(PullPrefix):], '/') > -1
}

func (ref RefName) IsFor() bool {
return strings.HasPrefix(string(ref), ForPrefix)
}

func (ref RefName) nameWithoutPrefix(prefix string) string {
if strings.HasPrefix(string(ref), prefix) {
return strings.TrimPrefix(string(ref), prefix)
}
return ""
}

// TagName returns simple tag name if it's an operation to a tag
func (ref RefName) TagName() string {
return ref.nameWithoutPrefix(TagPrefix)
}

// BranchName returns simple branch name if it's an operation to branch
func (ref RefName) BranchName() string {
return ref.nameWithoutPrefix(BranchPrefix)
}

// PullName returns the pull request name part of refs like refs/pull/<pull_name>/head
func (ref RefName) PullName() string {
refName := string(ref)
lastIdx := strings.LastIndexByte(refName[len(PullPrefix):], '/')
if strings.HasPrefix(refName, PullPrefix) && lastIdx > -1 {
return refName[len(PullPrefix) : lastIdx+len(PullPrefix)]
}
return ""
}

// ForBranchName returns the branch name part of refs like refs/for/<branch_name>
func (ref RefName) ForBranchName() string {
return ref.nameWithoutPrefix(ForPrefix)
}

func (ref RefName) RemoteName() string {
return ref.nameWithoutPrefix(RemotePrefix)
}

// ShortName returns the short name of the reference name
func (ref RefName) ShortName() string {
refName := string(ref)
if strings.HasPrefix(refName, BranchPrefix) {
return strings.TrimPrefix(refName, BranchPrefix)
if ref.IsBranch() {
return ref.BranchName()
}
if ref.IsTag() {
return ref.TagName()
}
if strings.HasPrefix(refName, TagPrefix) {
return strings.TrimPrefix(refName, TagPrefix)
if ref.IsRemote() {
return ref.RemoteName()
}
if strings.HasPrefix(refName, RemotePrefix) {
return strings.TrimPrefix(refName, RemotePrefix)
if ref.IsPull() {
return ref.PullName()
}
if strings.HasPrefix(refName, PullPrefix) && strings.IndexByte(refName[pullLen:], '/') > -1 {
return refName[pullLen : strings.IndexByte(refName[pullLen:], '/')+pullLen]
if ref.IsFor() {
return ref.ForBranchName()
}

return refName
}

// RefGroup returns the group type of the reference
func (ref RefName) RefGroup() string {
refName := string(ref)
if strings.HasPrefix(refName, BranchPrefix) {
if ref.IsBranch() {
return "heads"
}
if strings.HasPrefix(refName, TagPrefix) {
if ref.IsTag() {
return "tags"
}
if strings.HasPrefix(refName, RemotePrefix) {
if ref.IsRemote() {
return "remotes"
}
if strings.HasPrefix(refName, PullPrefix) && strings.IndexByte(refName[pullLen:], '/') > -1 {
if ref.IsPull() {
return "pull"
}
if ref.IsFor() {
return "for"
}
return ""
}

// RefURL returns the absolute URL for a ref in a repository
func RefURL(repoURL, ref string) string {
refFullName := RefName(ref)
refName := util.PathEscapeSegments(refFullName.ShortName())
lunny marked this conversation as resolved.
Show resolved Hide resolved
switch {
case refFullName.IsBranch():
return repoURL + "/src/branch/" + refName
case refFullName.IsTag():
return repoURL + "/src/tag/" + refName
case !IsValidSHAPattern(ref):
// assume they mean a branch
return repoURL + "/src/branch/" + refName
default:
return repoURL + "/src/commit/" + refName
}
}
38 changes: 38 additions & 0 deletions modules/git/ref_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT

package git

import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestRefName(t *testing.T) {
// Test branch names (with and without slash).
assert.Equal(t, "foo", RefName("refs/heads/foo").BranchName())
assert.Equal(t, "feature/foo", RefName("refs/heads/feature/foo").BranchName())

// Test tag names (with and without slash).
assert.Equal(t, "foo", RefName("refs/tags/foo").TagName())
assert.Equal(t, "release/foo", RefName("refs/tags/release/foo").TagName())

// Test pull names
assert.Equal(t, "1", RefName("refs/pull/1/head").PullName())
assert.Equal(t, "my/pull", RefName("refs/pull/my/pull/head").PullName())

// Test for branch names
assert.Equal(t, "main", RefName("refs/for/main").ForBranchName())
assert.Equal(t, "my/branch", RefName("refs/for/my/branch").ForBranchName())

// Test commit hashes.
assert.Equal(t, "c0ffee", RefName("c0ffee").ShortName())
lunny marked this conversation as resolved.
Show resolved Hide resolved
}

func TestRefURL(t *testing.T) {
repoURL := "/user/repo"
assert.Equal(t, repoURL+"/src/branch/foo", RefURL(repoURL, "refs/heads/foo"))
assert.Equal(t, repoURL+"/src/tag/foo", RefURL(repoURL, "refs/tags/foo"))
assert.Equal(t, repoURL+"/src/commit/c0ffee", RefURL(repoURL, "c0ffee"))
}
8 changes: 0 additions & 8 deletions modules/git/repo_branch.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,6 @@ import (
// BranchPrefix base dir of the branch information file store on git
const BranchPrefix = "refs/heads/"

// AGit Flow

// PullRequestPrefix special ref to create a pull request: refs/for/<targe-branch>/<topic-branch>
// or refs/for/<targe-branch> -o topic='<topic-branch>'
const PullRequestPrefix = "refs/for/"

// TODO: /refs/for-review for suggest change interface

// IsReferenceExist returns true if given reference exists in the repository.
func IsReferenceExist(ctx context.Context, repoPath, name string) bool {
_, _, err := NewCommand(ctx, "show-ref", "--verify").AddDashesAndList(name).RunStdString(&RunOpts{Dir: repoPath})
Expand Down
Loading