mirror of
https://github.com/go-gitea/gitea.git
synced 2025-03-26 07:01:27 +08:00
Add support for sha256 repositories (#23894)
Currently only SHA1 repositories are supported by Gitea. This adds support for alternate SHA256 with the additional aim of easier support for additional hash types in the future. Fixes: #13794 Limited by: https://github.com/go-git/go-git/issues/899 Depend on: #28138 <img width="776" alt="图片" src="https://github.com/go-gitea/gitea/assets/81045/5448c9a7-608e-4341-a149-5dd0069c9447"> --------- Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com> Co-authored-by: 6543 <6543@obermui.de>
This commit is contained in:
parent
07ba4d9f87
commit
d68a613ba8
models
git
issues
migrations
pull
repo
modules
git
blame_sha256_test.gocommit_reader.gocommit_sha256_test.gogit.goobject_format.goobject_id.goobject_id_gogit.gorepo.gorepo_base.gorepo_base_gogit.gorepo_base_nogogit.go
tests/repos
repo1_bare_sha256
repo5_pulls_sha256
repo6_blame_sha256
repo6_merge_sha256
HEADconfigdescriptionpacked-refs
info
objects
info
pack
pack-2fff0848f8d8eab8f7902ac91ab6a096c7530f577d5c0a79c63d9ac2b44f7510.bitmappack-2fff0848f8d8eab8f7902ac91ab6a096c7530f577d5c0a79c63d9ac2b44f7510.idxpack-2fff0848f8d8eab8f7902ac91ab6a096c7530f577d5c0a79c63d9ac2b44f7510.packpack-2fff0848f8d8eab8f7902ac91ab6a096c7530f577d5c0a79c63d9ac2b44f7510.revpack-65162b86afdbac3c566696d487e67bb2a4a5501ca1fa3528fad8a9474fba7e50.idxpack-65162b86afdbac3c566696d487e67bb2a4a5501ca1fa3528fad8a9474fba7e50.mtimespack-65162b86afdbac3c566696d487e67bb2a4a5501ca1fa3528fad8a9474fba7e50.packpack-65162b86afdbac3c566696d487e67bb2a4a5501ca1fa3528fad8a9474fba7e50.rev
refs/heads
markup
references
structs
templates
options/locale
routers
services/repository
templates
admin/repo
explore
repo
swagger
@ -37,7 +37,7 @@ type CommitStatus struct {
|
||||
SHA string `xorm:"VARCHAR(64) NOT NULL INDEX UNIQUE(repo_sha_index)"`
|
||||
TargetURL string `xorm:"TEXT"`
|
||||
Description string `xorm:"TEXT"`
|
||||
ContextHash string `xorm:"char(40) index"`
|
||||
ContextHash string `xorm:"VARCHAR(64) index"`
|
||||
Context string `xorm:"TEXT"`
|
||||
Creator *user_model.User `xorm:"-"`
|
||||
CreatorID int64
|
||||
|
@ -270,7 +270,7 @@ type Comment struct {
|
||||
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
|
||||
|
||||
// Reference issue in commit message
|
||||
CommitSHA string `xorm:"VARCHAR(40)"`
|
||||
CommitSHA string `xorm:"VARCHAR(64)"`
|
||||
|
||||
Attachments []*repo_model.Attachment `xorm:"-"`
|
||||
Reactions ReactionList `xorm:"-"`
|
||||
|
@ -171,11 +171,11 @@ type PullRequest struct {
|
||||
HeadBranch string
|
||||
HeadCommitID string `xorm:"-"`
|
||||
BaseBranch string
|
||||
MergeBase string `xorm:"VARCHAR(40)"`
|
||||
MergeBase string `xorm:"VARCHAR(64)"`
|
||||
AllowMaintainerEdit bool `xorm:"NOT NULL DEFAULT false"`
|
||||
|
||||
HasMerged bool `xorm:"INDEX"`
|
||||
MergedCommitID string `xorm:"VARCHAR(40)"`
|
||||
MergedCommitID string `xorm:"VARCHAR(64)"`
|
||||
MergerID int64 `xorm:"INDEX"`
|
||||
Merger *user_model.User `xorm:"-"`
|
||||
MergedUnix timeutil.TimeStamp `xorm:"updated INDEX"`
|
||||
|
@ -116,7 +116,7 @@ type Review struct {
|
||||
Content string `xorm:"TEXT"`
|
||||
// Official is a review made by an assigned approver (counts towards approval)
|
||||
Official bool `xorm:"NOT NULL DEFAULT false"`
|
||||
CommitID string `xorm:"VARCHAR(40)"`
|
||||
CommitID string `xorm:"VARCHAR(64)"`
|
||||
Stale bool `xorm:"NOT NULL DEFAULT false"`
|
||||
Dismissed bool `xorm:"NOT NULL DEFAULT false"`
|
||||
|
||||
|
@ -0,0 +1,11 @@
|
||||
# type Repository struct {
|
||||
# ID int64 `xorm:"pk autoincr"`
|
||||
# }
|
||||
-
|
||||
id: 1
|
||||
-
|
||||
id: 2
|
||||
-
|
||||
id: 3
|
||||
-
|
||||
id: 10
|
@ -556,6 +556,8 @@ var migrations = []Migration{
|
||||
NewMigration("Add ignore stale approval column on branch table", v1_22.AddIgnoreStaleApprovalsColumnToProtectedBranchTable),
|
||||
// v285 -> v286
|
||||
NewMigration("Add PreviousDuration to ActionRun", v1_22.AddPreviousDurationToActionRun),
|
||||
// v286 -> v287
|
||||
NewMigration("Add support for SHA256 git repositories", v1_22.AdjustDBForSha256),
|
||||
}
|
||||
|
||||
// GetCurrentDBVersion returns the current db version
|
||||
|
104
models/migrations/v1_22/v286.go
Normal file
104
models/migrations/v1_22/v286.go
Normal file
@ -0,0 +1,104 @@
|
||||
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
package v1_22 //nolint
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
|
||||
"xorm.io/xorm"
|
||||
)
|
||||
|
||||
func expandHashReferencesToSha256(x *xorm.Engine) error {
|
||||
alteredTables := [][2]string{
|
||||
{"commit_status", "context_hash"},
|
||||
{"comment", "commit_sha"},
|
||||
{"pull_request", "merge_base"},
|
||||
{"pull_request", "merged_commit_id"},
|
||||
{"review", "commit_id"},
|
||||
{"review_state", "commit_sha"},
|
||||
{"repo_archiver", "commit_id"},
|
||||
{"release", "sha1"},
|
||||
{"repo_indexer_status", "commit_sha"},
|
||||
}
|
||||
|
||||
db := x.NewSession()
|
||||
defer db.Close()
|
||||
|
||||
if err := db.Begin(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !setting.Database.Type.IsSQLite3() {
|
||||
if setting.Database.Type.IsMSSQL() {
|
||||
// drop indexes that need to be re-created afterwards
|
||||
droppedIndexes := []string{
|
||||
"DROP INDEX commit_status.IDX_commit_status_context_hash",
|
||||
"DROP INDEX review_state.UQE_review_state_pull_commit_user",
|
||||
"DROP INDEX repo_archiver.UQE_repo_archiver_s",
|
||||
}
|
||||
for _, s := range droppedIndexes {
|
||||
_, err := db.Exec(s)
|
||||
if err != nil {
|
||||
return errors.New(s + " " + err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, alts := range alteredTables {
|
||||
var err error
|
||||
if setting.Database.Type.IsMySQL() {
|
||||
_, err = db.Exec(fmt.Sprintf("ALTER TABLE `%s` MODIFY COLUMN `%s` VARCHAR(64)", alts[0], alts[1]))
|
||||
} else if setting.Database.Type.IsMSSQL() {
|
||||
_, err = db.Exec(fmt.Sprintf("ALTER TABLE `%s` ALTER COLUMN `%s` VARCHAR(64)", alts[0], alts[1]))
|
||||
} else {
|
||||
_, err = db.Exec(fmt.Sprintf("ALTER TABLE `%s` ALTER COLUMN `%s` TYPE VARCHAR(64)", alts[0], alts[1]))
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf("alter column '%s' of table '%s' failed: %w", alts[1], alts[0], err)
|
||||
}
|
||||
}
|
||||
|
||||
if setting.Database.Type.IsMSSQL() {
|
||||
recreateIndexes := []string{
|
||||
"CREATE INDEX IDX_commit_status_context_hash ON commit_status(context_hash)",
|
||||
"CREATE UNIQUE INDEX UQE_review_state_pull_commit_user ON review_state(user_id, pull_id, commit_sha)",
|
||||
"CREATE UNIQUE INDEX UQE_repo_archiver_s ON repo_archiver(repo_id, type, commit_id)",
|
||||
}
|
||||
for _, s := range recreateIndexes {
|
||||
_, err := db.Exec(s)
|
||||
if err != nil {
|
||||
return errors.New(s + " " + err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
log.Debug("Updated database tables to hold SHA256 git hash references")
|
||||
|
||||
return db.Commit()
|
||||
}
|
||||
|
||||
func addObjectFormatNameToRepository(x *xorm.Engine) error {
|
||||
type Repository struct {
|
||||
ObjectFormatName string `xorm:"VARCHAR(6) NOT NULL DEFAULT 'sha1'"`
|
||||
}
|
||||
|
||||
if err := x.Sync(new(Repository)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Here to catch weird edge-cases where column constraints above are
|
||||
// not applied by the DB backend
|
||||
_, err := x.Exec("UPDATE repository set object_format_name = 'sha1' WHERE object_format_name = '' or object_format_name IS NULL")
|
||||
return err
|
||||
}
|
||||
|
||||
func AdjustDBForSha256(x *xorm.Engine) error {
|
||||
if err := expandHashReferencesToSha256(x); err != nil {
|
||||
return err
|
||||
}
|
||||
return addObjectFormatNameToRepository(x)
|
||||
}
|
62
models/migrations/v1_22/v286_test.go
Normal file
62
models/migrations/v1_22/v286_test.go
Normal file
@ -0,0 +1,62 @@
|
||||
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package v1_22 //nolint
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/migrations/base"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"xorm.io/xorm"
|
||||
)
|
||||
|
||||
func PrepareOldRepository(t *testing.T) (*xorm.Engine, func()) {
|
||||
type Repository struct { // old struct
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
}
|
||||
|
||||
// Prepare and load the testing database
|
||||
return base.PrepareTestEnv(t, 0, new(Repository))
|
||||
}
|
||||
|
||||
func Test_RepositoryFormat(t *testing.T) {
|
||||
x, deferable := PrepareOldRepository(t)
|
||||
defer deferable()
|
||||
|
||||
type Repository struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
ObjectFormatName string `xorg:"not null default('sha1')"`
|
||||
}
|
||||
|
||||
repo := new(Repository)
|
||||
|
||||
// check we have some records to migrate
|
||||
count, err := x.Count(new(Repository))
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, 4, count)
|
||||
|
||||
assert.NoError(t, AdjustDBForSha256(x))
|
||||
|
||||
repo.ID = 20
|
||||
repo.ObjectFormatName = "sha256"
|
||||
_, err = x.Insert(repo)
|
||||
assert.NoError(t, err)
|
||||
|
||||
count, err = x.Count(new(Repository))
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, 5, count)
|
||||
|
||||
repo = new(Repository)
|
||||
ok, err := x.ID(2).Get(repo)
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, true, ok)
|
||||
assert.EqualValues(t, "sha1", repo.ObjectFormatName)
|
||||
|
||||
repo = new(Repository)
|
||||
ok, err = x.ID(20).Get(repo)
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, true, ok)
|
||||
assert.EqualValues(t, "sha256", repo.ObjectFormatName)
|
||||
}
|
@ -39,7 +39,7 @@ type ReviewState struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
UserID int64 `xorm:"NOT NULL UNIQUE(pull_commit_user)"`
|
||||
PullID int64 `xorm:"NOT NULL INDEX UNIQUE(pull_commit_user) DEFAULT 0"` // Which PR was the review on?
|
||||
CommitSHA string `xorm:"NOT NULL VARCHAR(40) UNIQUE(pull_commit_user)"` // Which commit was the head commit for the review?
|
||||
CommitSHA string `xorm:"NOT NULL VARCHAR(64) UNIQUE(pull_commit_user)"` // Which commit was the head commit for the review?
|
||||
UpdatedFiles map[string]ViewedState `xorm:"NOT NULL LONGTEXT JSON"` // Stores for each of the changed files of a PR whether they have been viewed, changed since last viewed, or not viewed
|
||||
UpdatedUnix timeutil.TimeStamp `xorm:"updated"` // Is an accurate indicator of the order of commits as we do not expect it to be possible to make reviews on previous commits
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ type RepoArchiver struct { //revive:disable-line:exported
|
||||
RepoID int64 `xorm:"index unique(s)"`
|
||||
Type git.ArchiveType `xorm:"unique(s)"`
|
||||
Status ArchiverStatus
|
||||
CommitID string `xorm:"VARCHAR(40) unique(s)"`
|
||||
CommitID string `xorm:"VARCHAR(64) unique(s)"`
|
||||
CreatedUnix timeutil.TimeStamp `xorm:"INDEX NOT NULL created"`
|
||||
}
|
||||
|
||||
|
@ -75,7 +75,7 @@ type Release struct {
|
||||
Target string
|
||||
TargetBehind string `xorm:"-"` // to handle non-existing or empty target
|
||||
Title string
|
||||
Sha1 string `xorm:"VARCHAR(40)"`
|
||||
Sha1 string `xorm:"VARCHAR(64)"`
|
||||
NumCommits int64
|
||||
NumCommitsBehind int64 `xorm:"-"`
|
||||
Note string `xorm:"TEXT"`
|
||||
|
@ -180,7 +180,7 @@ type Repository struct {
|
||||
IsFsckEnabled bool `xorm:"NOT NULL DEFAULT true"`
|
||||
CloseIssuesViaCommitInAnyBranch bool `xorm:"NOT NULL DEFAULT false"`
|
||||
Topics []string `xorm:"TEXT JSON"`
|
||||
ObjectFormatName string `xorm:"-"`
|
||||
ObjectFormatName string `xorm:"VARCHAR(6) NOT NULL DEFAULT 'sha1'"`
|
||||
|
||||
TrustModel TrustModelType
|
||||
|
||||
@ -276,10 +276,6 @@ func (repo *Repository) AfterLoad() {
|
||||
repo.NumOpenMilestones = repo.NumMilestones - repo.NumClosedMilestones
|
||||
repo.NumOpenProjects = repo.NumProjects - repo.NumClosedProjects
|
||||
repo.NumOpenActionRuns = repo.NumActionRuns - repo.NumClosedActionRuns
|
||||
|
||||
// this is a temporary behaviour to support old repos, next step is to store the object format in the database
|
||||
// and read from database so this line could be removed. To not depend on git module, we use a constant variable here
|
||||
repo.ObjectFormatName = "sha1"
|
||||
}
|
||||
|
||||
// LoadAttributes loads attributes of the repository.
|
||||
|
@ -27,7 +27,7 @@ const (
|
||||
type RepoIndexerStatus struct { //revive:disable-line:exported
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
RepoID int64 `xorm:"INDEX(s)"`
|
||||
CommitSha string `xorm:"VARCHAR(40)"`
|
||||
CommitSha string `xorm:"VARCHAR(64)"`
|
||||
IndexerType RepoIndexerType `xorm:"INDEX(s) NOT NULL DEFAULT 0"`
|
||||
}
|
||||
|
||||
|
144
modules/git/blame_sha256_test.go
Normal file
144
modules/git/blame_sha256_test.go
Normal file
@ -0,0 +1,144 @@
|
||||
// Copyright 2024 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package git
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestReadingBlameOutputSha256(t *testing.T) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
t.Run("Without .git-blame-ignore-revs", func(t *testing.T) {
|
||||
repo, err := OpenRepository(ctx, "./tests/repos/repo5_pulls_sha256")
|
||||
assert.NoError(t, err)
|
||||
defer repo.Close()
|
||||
|
||||
commit, err := repo.GetCommit("0b69b7bb649b5d46e14cabb6468685e5dd721290acc7ffe604d37cde57927345")
|
||||
assert.NoError(t, err)
|
||||
|
||||
parts := []*BlamePart{
|
||||
{
|
||||
Sha: "1e35a51dc00fd7de730344c07061acfe80e8117e075ac979b6a29a3a045190ca",
|
||||
Lines: []string{
|
||||
"# test_repo",
|
||||
"Test repository for testing migration from github to gitea",
|
||||
},
|
||||
},
|
||||
{
|
||||
Sha: "0b69b7bb649b5d46e14cabb6468685e5dd721290acc7ffe604d37cde57927345",
|
||||
Lines: []string{"", "Do not make any changes to this repo it is used for unit testing"},
|
||||
PreviousSha: "1e35a51dc00fd7de730344c07061acfe80e8117e075ac979b6a29a3a045190ca",
|
||||
PreviousPath: "README.md",
|
||||
},
|
||||
}
|
||||
|
||||
for _, bypass := range []bool{false, true} {
|
||||
blameReader, err := CreateBlameReader(ctx, Sha256ObjectFormat, "./tests/repos/repo5_pulls_sha256", commit, "README.md", bypass)
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, blameReader)
|
||||
defer blameReader.Close()
|
||||
|
||||
assert.False(t, blameReader.UsesIgnoreRevs())
|
||||
|
||||
for _, part := range parts {
|
||||
actualPart, err := blameReader.NextPart()
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, part, actualPart)
|
||||
}
|
||||
|
||||
// make sure all parts have been read
|
||||
actualPart, err := blameReader.NextPart()
|
||||
assert.Nil(t, actualPart)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("With .git-blame-ignore-revs", func(t *testing.T) {
|
||||
repo, err := OpenRepository(ctx, "./tests/repos/repo6_blame_sha256")
|
||||
assert.NoError(t, err)
|
||||
defer repo.Close()
|
||||
|
||||
full := []*BlamePart{
|
||||
{
|
||||
Sha: "ab2b57a4fa476fb2edb74dafa577caf918561abbaa8fba0c8dc63c412e17a7cc",
|
||||
Lines: []string{"line", "line"},
|
||||
},
|
||||
{
|
||||
Sha: "9347b0198cd1f25017579b79d0938fa89dba34ad2514f0dd92f6bc975ed1a2fe",
|
||||
Lines: []string{"changed line"},
|
||||
PreviousSha: "ab2b57a4fa476fb2edb74dafa577caf918561abbaa8fba0c8dc63c412e17a7cc",
|
||||
PreviousPath: "blame.txt",
|
||||
},
|
||||
{
|
||||
Sha: "ab2b57a4fa476fb2edb74dafa577caf918561abbaa8fba0c8dc63c412e17a7cc",
|
||||
Lines: []string{"line", "line", ""},
|
||||
},
|
||||
}
|
||||
|
||||
cases := []struct {
|
||||
CommitID string
|
||||
UsesIgnoreRevs bool
|
||||
Bypass bool
|
||||
Parts []*BlamePart
|
||||
}{
|
||||
{
|
||||
CommitID: "e2f5660e15159082902960af0ed74fc144921d2b0c80e069361853b3ece29ba3",
|
||||
UsesIgnoreRevs: true,
|
||||
Bypass: false,
|
||||
Parts: []*BlamePart{
|
||||
{
|
||||
Sha: "ab2b57a4fa476fb2edb74dafa577caf918561abbaa8fba0c8dc63c412e17a7cc",
|
||||
Lines: []string{"line", "line", "changed line", "line", "line", ""},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
CommitID: "e2f5660e15159082902960af0ed74fc144921d2b0c80e069361853b3ece29ba3",
|
||||
UsesIgnoreRevs: false,
|
||||
Bypass: true,
|
||||
Parts: full,
|
||||
},
|
||||
{
|
||||
CommitID: "9347b0198cd1f25017579b79d0938fa89dba34ad2514f0dd92f6bc975ed1a2fe",
|
||||
UsesIgnoreRevs: false,
|
||||
Bypass: false,
|
||||
Parts: full,
|
||||
},
|
||||
{
|
||||
CommitID: "9347b0198cd1f25017579b79d0938fa89dba34ad2514f0dd92f6bc975ed1a2fe",
|
||||
UsesIgnoreRevs: false,
|
||||
Bypass: false,
|
||||
Parts: full,
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
commit, err := repo.GetCommit(c.CommitID)
|
||||
assert.NoError(t, err)
|
||||
|
||||
blameReader, err := CreateBlameReader(ctx, repo.objectFormat, "./tests/repos/repo6_blame_sha256", commit, "blame.txt", c.Bypass)
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, blameReader)
|
||||
defer blameReader.Close()
|
||||
|
||||
assert.Equal(t, c.UsesIgnoreRevs, blameReader.UsesIgnoreRevs())
|
||||
|
||||
for _, part := range c.Parts {
|
||||
actualPart, err := blameReader.NextPart()
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, part, actualPart)
|
||||
}
|
||||
|
||||
// make sure all parts have been read
|
||||
actualPart, err := blameReader.NextPart()
|
||||
assert.Nil(t, actualPart)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
})
|
||||
}
|
@ -85,6 +85,8 @@ readLoop:
|
||||
commit.Committer.Decode(data)
|
||||
_, _ = payloadSB.Write(line)
|
||||
case "gpgsig":
|
||||
fallthrough
|
||||
case "gpgsig-sha256": // FIXME: no intertop, so only 1 exists at present.
|
||||
_, _ = signatureSB.Write(data)
|
||||
_ = signatureSB.WriteByte('\n')
|
||||
pgpsig = true
|
||||
|
195
modules/git/commit_sha256_test.go
Normal file
195
modules/git/commit_sha256_test.go
Normal file
@ -0,0 +1,195 @@
|
||||
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
//go:build !gogit
|
||||
|
||||
package git
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestCommitsCountSha256(t *testing.T) {
|
||||
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare_sha256")
|
||||
|
||||
commitsCount, err := CommitsCount(DefaultContext,
|
||||
CommitsCountOptions{
|
||||
RepoPath: bareRepo1Path,
|
||||
Revision: []string{"f004f41359117d319dedd0eaab8c5259ee2263da839dcba33637997458627fdc"},
|
||||
})
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, int64(3), commitsCount)
|
||||
}
|
||||
|
||||
func TestCommitsCountWithoutBaseSha256(t *testing.T) {
|
||||
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare_sha256")
|
||||
|
||||
commitsCount, err := CommitsCount(DefaultContext,
|
||||
CommitsCountOptions{
|
||||
RepoPath: bareRepo1Path,
|
||||
Not: "main",
|
||||
Revision: []string{"branch1"},
|
||||
})
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, int64(2), commitsCount)
|
||||
}
|
||||
|
||||
func TestGetFullCommitIDSha256(t *testing.T) {
|
||||
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare_sha256")
|
||||
|
||||
id, err := GetFullCommitID(DefaultContext, bareRepo1Path, "f004f4")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "f004f41359117d319dedd0eaab8c5259ee2263da839dcba33637997458627fdc", id)
|
||||
}
|
||||
|
||||
func TestGetFullCommitIDErrorSha256(t *testing.T) {
|
||||
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare_sha256")
|
||||
|
||||
id, err := GetFullCommitID(DefaultContext, bareRepo1Path, "unknown")
|
||||
assert.Empty(t, id)
|
||||
if assert.Error(t, err) {
|
||||
assert.EqualError(t, err, "object does not exist [id: unknown, rel_path: ]")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCommitFromReaderSha256(t *testing.T) {
|
||||
commitString := `9433b2a62b964c17a4485ae180f45f595d3e69d31b786087775e28c6b6399df0 commit 1114
|
||||
tree e7f9e96dd79c09b078cac8b303a7d3b9d65ff9b734e86060a4d20409fd379f9e
|
||||
parent 26e9ccc29fad747e9c5d9f4c9ddeb7eff61cc45ef6a8dc258cbeb181afc055e8
|
||||
author Adam Majer <amajer@suse.de> 1698676906 +0100
|
||||
committer Adam Majer <amajer@suse.de> 1698676906 +0100
|
||||
gpgsig-sha256 -----BEGIN PGP SIGNATURE-----
|
||||
` + " " + `
|
||||
iQIrBAABCgAtFiEES+fB08xlgTrzSdQvhkUIsBsmec8FAmU/wKoPHGFtYWplckBz
|
||||
dXNlLmRlAAoJEIZFCLAbJnnP4s4PQIJATa++WPzR6/H4etT7bsOGoMyguEJYyWOd
|
||||
aTybplzT7QAL7h2to0QszGabtzMJPIA39xSFZNYNN30voK5YyyYibXluPKgjemfK
|
||||
WNXwF+gkwgZI38gSvKf+vlqI+EYyIFe19wOhiju0m8SIlB5NEPiWHa17q2mqmqqx
|
||||
1FWa2JdqLPYjAtSLFXeSZegrY5V1FxdemyMUONkg8YO9OSIMZiE0GsnnOXQ3xcT4
|
||||
JTCnmlUxIKw689UiEY80JopUIq+Wl7+qq9507IYYSUCyB6JazL42AKMzVCbD+qBP
|
||||
oOzh/hafYgk9H9qCQXaLbmvs17zXRpicig1bAzqgAy1FDelvpERyRTydEajSLIG6
|
||||
U1cRCkgXCZ0NfsYNPPmBa8b3+rnstypXYTbyMwTln7FfUAaGo6o9JYiPMkzxlmsy
|
||||
zfp/tcaY8+LlBL9aOJjtv+a0p+HrpCGd6CCa4ARfphTLq8QRSSh8uzlB9N+6HnRI
|
||||
VAEUo6ecdDxSpyt2naeg9pKus/BRi7P6g4B1hkk/zZstUX/QP4IQuAJbXjkvsC+X
|
||||
HKRr3NlRM/DygzTyj0gN74uoa0goCIbyAQhiT42nm0cuhM7uN/W0ayrlZjGF1cbR
|
||||
8NCJUL2Nwj0ywKIavC99Ipkb8AsFwpVT6U6effs6
|
||||
=xybZ
|
||||
-----END PGP SIGNATURE-----
|
||||
|
||||
signed commit`
|
||||
|
||||
sha := &Sha256Hash{
|
||||
0x94, 0x33, 0xb2, 0xa6, 0x2b, 0x96, 0x4c, 0x17, 0xa4, 0x48, 0x5a, 0xe1, 0x80, 0xf4, 0x5f, 0x59,
|
||||
0x5d, 0x3e, 0x69, 0xd3, 0x1b, 0x78, 0x60, 0x87, 0x77, 0x5e, 0x28, 0xc6, 0xb6, 0x39, 0x9d, 0xf0,
|
||||
}
|
||||
gitRepo, err := openRepositoryWithDefaultContext(filepath.Join(testReposDir, "repo1_bare_sha256"))
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, gitRepo)
|
||||
defer gitRepo.Close()
|
||||
|
||||
commitFromReader, err := CommitFromReader(gitRepo, sha, strings.NewReader(commitString))
|
||||
assert.NoError(t, err)
|
||||
if !assert.NotNil(t, commitFromReader) {
|
||||
return
|
||||
}
|
||||
assert.EqualValues(t, sha, commitFromReader.ID)
|
||||
assert.EqualValues(t, `-----BEGIN PGP SIGNATURE-----
|
||||
|
||||
iQIrBAABCgAtFiEES+fB08xlgTrzSdQvhkUIsBsmec8FAmU/wKoPHGFtYWplckBz
|
||||
dXNlLmRlAAoJEIZFCLAbJnnP4s4PQIJATa++WPzR6/H4etT7bsOGoMyguEJYyWOd
|
||||
aTybplzT7QAL7h2to0QszGabtzMJPIA39xSFZNYNN30voK5YyyYibXluPKgjemfK
|
||||
WNXwF+gkwgZI38gSvKf+vlqI+EYyIFe19wOhiju0m8SIlB5NEPiWHa17q2mqmqqx
|
||||
1FWa2JdqLPYjAtSLFXeSZegrY5V1FxdemyMUONkg8YO9OSIMZiE0GsnnOXQ3xcT4
|
||||
JTCnmlUxIKw689UiEY80JopUIq+Wl7+qq9507IYYSUCyB6JazL42AKMzVCbD+qBP
|
||||
oOzh/hafYgk9H9qCQXaLbmvs17zXRpicig1bAzqgAy1FDelvpERyRTydEajSLIG6
|
||||
U1cRCkgXCZ0NfsYNPPmBa8b3+rnstypXYTbyMwTln7FfUAaGo6o9JYiPMkzxlmsy
|
||||
zfp/tcaY8+LlBL9aOJjtv+a0p+HrpCGd6CCa4ARfphTLq8QRSSh8uzlB9N+6HnRI
|
||||
VAEUo6ecdDxSpyt2naeg9pKus/BRi7P6g4B1hkk/zZstUX/QP4IQuAJbXjkvsC+X
|
||||
HKRr3NlRM/DygzTyj0gN74uoa0goCIbyAQhiT42nm0cuhM7uN/W0ayrlZjGF1cbR
|
||||
8NCJUL2Nwj0ywKIavC99Ipkb8AsFwpVT6U6effs6
|
||||
=xybZ
|
||||
-----END PGP SIGNATURE-----
|
||||
`, commitFromReader.Signature.Signature)
|
||||
assert.EqualValues(t, `tree e7f9e96dd79c09b078cac8b303a7d3b9d65ff9b734e86060a4d20409fd379f9e
|
||||
parent 26e9ccc29fad747e9c5d9f4c9ddeb7eff61cc45ef6a8dc258cbeb181afc055e8
|
||||
author Adam Majer <amajer@suse.de> 1698676906 +0100
|
||||
committer Adam Majer <amajer@suse.de> 1698676906 +0100
|
||||
|
||||
signed commit`, commitFromReader.Signature.Payload)
|
||||
assert.EqualValues(t, "Adam Majer <amajer@suse.de>", commitFromReader.Author.String())
|
||||
|
||||
commitFromReader2, err := CommitFromReader(gitRepo, sha, strings.NewReader(commitString+"\n\n"))
|
||||
assert.NoError(t, err)
|
||||
commitFromReader.CommitMessage += "\n\n"
|
||||
commitFromReader.Signature.Payload += "\n\n"
|
||||
assert.EqualValues(t, commitFromReader, commitFromReader2)
|
||||
}
|
||||
|
||||
func TestHasPreviousCommitSha256(t *testing.T) {
|
||||
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare_sha256")
|
||||
|
||||
repo, err := openRepositoryWithDefaultContext(bareRepo1Path)
|
||||
assert.NoError(t, err)
|
||||
defer repo.Close()
|
||||
|
||||
commit, err := repo.GetCommit("f004f41359117d319dedd0eaab8c5259ee2263da839dcba33637997458627fdc")
|
||||
assert.NoError(t, err)
|
||||
|
||||
parentSHA := MustIDFromString("b0ec7af4547047f12d5093e37ef8f1b3b5415ed8ee17894d43a34d7d34212e9c")
|
||||
notParentSHA := MustIDFromString("42e334efd04cd36eea6da0599913333c26116e1a537ca76e5b6e4af4dda00236")
|
||||
assert.Equal(t, repo.objectFormat, parentSHA.Type())
|
||||
assert.Equal(t, repo.objectFormat.Name(), "sha256")
|
||||
|
||||
haz, err := commit.HasPreviousCommit(parentSHA)
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, haz)
|
||||
|
||||
hazNot, err := commit.HasPreviousCommit(notParentSHA)
|
||||
assert.NoError(t, err)
|
||||
assert.False(t, hazNot)
|
||||
|
||||
selfNot, err := commit.HasPreviousCommit(commit.ID)
|
||||
assert.NoError(t, err)
|
||||
assert.False(t, selfNot)
|
||||
}
|
||||
|
||||
func TestGetCommitFileStatusMergesSha256(t *testing.T) {
|
||||
bareRepo1Path := filepath.Join(testReposDir, "repo6_merge_sha256")
|
||||
|
||||
commitFileStatus, err := GetCommitFileStatus(DefaultContext, bareRepo1Path, "d2e5609f630dd8db500f5298d05d16def282412e3e66ed68cc7d0833b29129a1")
|
||||
assert.NoError(t, err)
|
||||
|
||||
expected := CommitFileStatus{
|
||||
[]string{
|
||||
"add_file.txt",
|
||||
},
|
||||
[]string{},
|
||||
[]string{
|
||||
"to_modify.txt",
|
||||
},
|
||||
}
|
||||
|
||||
assert.Equal(t, expected.Added, commitFileStatus.Added)
|
||||
assert.Equal(t, expected.Removed, commitFileStatus.Removed)
|
||||
assert.Equal(t, expected.Modified, commitFileStatus.Modified)
|
||||
|
||||
expected = CommitFileStatus{
|
||||
[]string{},
|
||||
[]string{
|
||||
"to_remove.txt",
|
||||
},
|
||||
[]string{},
|
||||
}
|
||||
|
||||
commitFileStatus, err = GetCommitFileStatus(DefaultContext, bareRepo1Path, "da1ded40dc8e5b7c564171f4bf2fc8370487decfb1cb6a99ef28f3ed73d09172")
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.Equal(t, expected.Added, commitFileStatus.Added)
|
||||
assert.Equal(t, expected.Removed, commitFileStatus.Removed)
|
||||
assert.Equal(t, expected.Modified, commitFileStatus.Modified)
|
||||
}
|
@ -185,7 +185,13 @@ func InitFull(ctx context.Context) (err error) {
|
||||
globalCommandArgs = append(globalCommandArgs, "-c", "credential.helper=")
|
||||
}
|
||||
SupportProcReceive = CheckGitVersionAtLeast("2.29") == nil
|
||||
SupportHashSha256 = CheckGitVersionAtLeast("2.42") == nil
|
||||
SupportHashSha256 = CheckGitVersionAtLeast("2.42") == nil && !isGogit
|
||||
if SupportHashSha256 {
|
||||
SupportedObjectFormats = append(SupportedObjectFormats, Sha256ObjectFormat)
|
||||
} else {
|
||||
log.Warn("sha256 hash support is disabled - requires Git >= 2.42. Gogit is currently unsupported")
|
||||
}
|
||||
|
||||
if setting.LFS.StartServer {
|
||||
if CheckGitVersionAtLeast("2.1.2") != nil {
|
||||
return errors.New("LFS server support requires Git >= 2.1.2")
|
||||
|
@ -5,6 +5,7 @@ package git
|
||||
|
||||
import (
|
||||
"crypto/sha1"
|
||||
"crypto/sha256"
|
||||
"regexp"
|
||||
"strconv"
|
||||
)
|
||||
@ -12,6 +13,9 @@ import (
|
||||
// sha1Pattern can be used to determine if a string is an valid sha
|
||||
var sha1Pattern = regexp.MustCompile(`^[0-9a-f]{4,40}$`)
|
||||
|
||||
// sha256Pattern can be used to determine if a string is an valid sha
|
||||
var sha256Pattern = regexp.MustCompile(`^[0-9a-f]{4,64}$`)
|
||||
|
||||
type ObjectFormat interface {
|
||||
// Name returns the name of the object format
|
||||
Name() string
|
||||
@ -29,11 +33,12 @@ type ObjectFormat interface {
|
||||
ComputeHash(t ObjectType, content []byte) ObjectID
|
||||
}
|
||||
|
||||
/* SHA1 Type */
|
||||
type Sha1ObjectFormatImpl struct{}
|
||||
|
||||
var (
|
||||
emptyObjectID = &Sha1Hash{}
|
||||
emptyTree = &Sha1Hash{
|
||||
emptySha1ObjectID = &Sha1Hash{}
|
||||
emptySha1Tree = &Sha1Hash{
|
||||
0x4b, 0x82, 0x5d, 0xc6, 0x42, 0xcb, 0x6e, 0xb9, 0xa0, 0x60,
|
||||
0xe5, 0x4b, 0xf8, 0xd6, 0x92, 0x88, 0xfb, 0xee, 0x49, 0x04,
|
||||
}
|
||||
@ -41,11 +46,11 @@ var (
|
||||
|
||||
func (Sha1ObjectFormatImpl) Name() string { return "sha1" }
|
||||
func (Sha1ObjectFormatImpl) EmptyObjectID() ObjectID {
|
||||
return emptyObjectID
|
||||
return emptySha1ObjectID
|
||||
}
|
||||
|
||||
func (Sha1ObjectFormatImpl) EmptyTree() ObjectID {
|
||||
return emptyTree
|
||||
return emptySha1Tree
|
||||
}
|
||||
func (Sha1ObjectFormatImpl) FullLength() int { return 40 }
|
||||
func (Sha1ObjectFormatImpl) IsValid(input string) bool {
|
||||
@ -72,11 +77,59 @@ func (h Sha1ObjectFormatImpl) ComputeHash(t ObjectType, content []byte) ObjectID
|
||||
return &sha1
|
||||
}
|
||||
|
||||
var Sha1ObjectFormat ObjectFormat = Sha1ObjectFormatImpl{}
|
||||
/* SHA256 Type */
|
||||
type Sha256ObjectFormatImpl struct{}
|
||||
|
||||
var (
|
||||
emptySha256ObjectID = &Sha256Hash{}
|
||||
emptySha256Tree = &Sha256Hash{
|
||||
0x6e, 0xf1, 0x9b, 0x41, 0x22, 0x5c, 0x53, 0x69, 0xf1, 0xc1,
|
||||
0x04, 0xd4, 0x5d, 0x8d, 0x85, 0xef, 0xa9, 0xb0, 0x57, 0xb5,
|
||||
0x3b, 0x14, 0xb4, 0xb9, 0xb9, 0x39, 0xdd, 0x74, 0xde, 0xcc,
|
||||
0x53, 0x21,
|
||||
}
|
||||
)
|
||||
|
||||
func (Sha256ObjectFormatImpl) Name() string { return "sha256" }
|
||||
func (Sha256ObjectFormatImpl) EmptyObjectID() ObjectID {
|
||||
return emptySha256ObjectID
|
||||
}
|
||||
|
||||
func (Sha256ObjectFormatImpl) EmptyTree() ObjectID {
|
||||
return emptySha256Tree
|
||||
}
|
||||
func (Sha256ObjectFormatImpl) FullLength() int { return 64 }
|
||||
func (Sha256ObjectFormatImpl) IsValid(input string) bool {
|
||||
return sha256Pattern.MatchString(input)
|
||||
}
|
||||
|
||||
func (Sha256ObjectFormatImpl) MustID(b []byte) ObjectID {
|
||||
var id Sha256Hash
|
||||
copy(id[0:32], b)
|
||||
return &id
|
||||
}
|
||||
|
||||
// ComputeHash compute the hash for a given ObjectType and content
|
||||
func (h Sha256ObjectFormatImpl) ComputeHash(t ObjectType, content []byte) ObjectID {
|
||||
hasher := sha256.New()
|
||||
_, _ = hasher.Write(t.Bytes())
|
||||
_, _ = hasher.Write([]byte(" "))
|
||||
_, _ = hasher.Write([]byte(strconv.FormatInt(int64(len(content)), 10)))
|
||||
_, _ = hasher.Write([]byte{0})
|
||||
|
||||
// HashSum generates a SHA256 for the provided hash
|
||||
var sha256 Sha1Hash
|
||||
copy(sha256[:], hasher.Sum(nil))
|
||||
return &sha256
|
||||
}
|
||||
|
||||
var (
|
||||
Sha1ObjectFormat ObjectFormat = Sha1ObjectFormatImpl{}
|
||||
Sha256ObjectFormat ObjectFormat = Sha256ObjectFormatImpl{}
|
||||
)
|
||||
|
||||
var SupportedObjectFormats = []ObjectFormat{
|
||||
Sha1ObjectFormat,
|
||||
// TODO: add sha256
|
||||
}
|
||||
|
||||
func ObjectFormatFromName(name string) ObjectFormat {
|
||||
|
@ -16,6 +16,7 @@ type ObjectID interface {
|
||||
Type() ObjectFormat
|
||||
}
|
||||
|
||||
/* SHA1 */
|
||||
type Sha1Hash [20]byte
|
||||
|
||||
func (h *Sha1Hash) String() string {
|
||||
@ -39,6 +40,21 @@ func MustIDFromString(hexHash string) ObjectID {
|
||||
return id
|
||||
}
|
||||
|
||||
/* SHA256 */
|
||||
type Sha256Hash [32]byte
|
||||
|
||||
func (h *Sha256Hash) String() string {
|
||||
return hex.EncodeToString(h[:])
|
||||
}
|
||||
|
||||
func (h *Sha256Hash) IsZero() bool {
|
||||
empty := Sha256Hash{}
|
||||
return bytes.Equal(empty[:], h[:])
|
||||
}
|
||||
func (h *Sha256Hash) RawValue() []byte { return h[:] }
|
||||
func (*Sha256Hash) Type() ObjectFormat { return Sha256ObjectFormat }
|
||||
|
||||
/* utility */
|
||||
func NewIDFromString(hexHash string) (ObjectID, error) {
|
||||
var theObjectFormat ObjectFormat
|
||||
for _, objectFormat := range SupportedObjectFormats {
|
||||
|
@ -13,6 +13,8 @@ func ParseGogitHash(h plumbing.Hash) ObjectID {
|
||||
switch hash.Size {
|
||||
case 20:
|
||||
return Sha1ObjectFormat.MustID(h[:])
|
||||
case 32:
|
||||
return Sha256ObjectFormat.MustID(h[:])
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -97,15 +97,12 @@ func InitRepository(ctx context.Context, repoPath string, bare bool, objectForma
|
||||
}
|
||||
|
||||
cmd := NewCommand(ctx, "init")
|
||||
if SupportHashSha256 {
|
||||
if objectFormatName == "" {
|
||||
objectFormatName = Sha1ObjectFormat.Name()
|
||||
}
|
||||
if !IsValidObjectFormat(objectFormatName) {
|
||||
return fmt.Errorf("invalid object format: %s", objectFormatName)
|
||||
}
|
||||
cmd.AddOptionValues("--object-format", objectFormatName)
|
||||
|
||||
if !IsValidObjectFormat(objectFormatName) {
|
||||
return fmt.Errorf("invalid object format: %s", objectFormatName)
|
||||
}
|
||||
cmd.AddOptionValues("--object-format", objectFormatName)
|
||||
|
||||
if bare {
|
||||
cmd.AddArguments("--bare")
|
||||
}
|
||||
|
@ -8,6 +8,8 @@ import (
|
||||
"io"
|
||||
)
|
||||
|
||||
var isGogit bool
|
||||
|
||||
// contextKey is a value for use with context.WithValue.
|
||||
type contextKey struct {
|
||||
name string
|
||||
|
@ -21,6 +21,10 @@ import (
|
||||
"github.com/go-git/go-git/v5/storage/filesystem"
|
||||
)
|
||||
|
||||
func init() {
|
||||
isGogit = true
|
||||
}
|
||||
|
||||
// Repository represents a Git repository.
|
||||
type Repository struct {
|
||||
Path string
|
||||
|
@ -15,6 +15,10 @@ import (
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
)
|
||||
|
||||
func init() {
|
||||
isGogit = false
|
||||
}
|
||||
|
||||
// Repository represents a Git repository.
|
||||
type Repository struct {
|
||||
Path string
|
||||
|
1
modules/git/tests/repos/repo1_bare_sha256/HEAD
Normal file
1
modules/git/tests/repos/repo1_bare_sha256/HEAD
Normal file
@ -0,0 +1 @@
|
||||
ref: refs/heads/main
|
6
modules/git/tests/repos/repo1_bare_sha256/config
Normal file
6
modules/git/tests/repos/repo1_bare_sha256/config
Normal file
@ -0,0 +1,6 @@
|
||||
[core]
|
||||
repositoryformatversion = 1
|
||||
filemode = true
|
||||
bare = true
|
||||
[extensions]
|
||||
objectformat = sha256
|
1
modules/git/tests/repos/repo1_bare_sha256/description
Normal file
1
modules/git/tests/repos/repo1_bare_sha256/description
Normal file
@ -0,0 +1 @@
|
||||
Unnamed repository; edit this file 'description' to name the repository.
|
6
modules/git/tests/repos/repo1_bare_sha256/info/exclude
Normal file
6
modules/git/tests/repos/repo1_bare_sha256/info/exclude
Normal file
@ -0,0 +1,6 @@
|
||||
# git ls-files --others --exclude-from=.git/info/exclude
|
||||
# Lines that start with '#' are comments.
|
||||
# For a project mostly in C, the following would be a good set of
|
||||
# exclude patterns (uncomment them if you want to use them):
|
||||
# *.[oa]
|
||||
# *~
|
7
modules/git/tests/repos/repo1_bare_sha256/info/refs
Normal file
7
modules/git/tests/repos/repo1_bare_sha256/info/refs
Normal file
@ -0,0 +1,7 @@
|
||||
42e334efd04cd36eea6da0599913333c26116e1a537ca76e5b6e4af4dda00236 refs/heads/branch1
|
||||
5bc2249e32e0ba40a08879fba2bd4e97a13cb345831549f4bc5649525da8f6cc refs/heads/branch2
|
||||
9433b2a62b964c17a4485ae180f45f595d3e69d31b786087775e28c6b6399df0 refs/heads/main
|
||||
29a82d4fc02e19190fb489cc90d5730ed91970b49f4e39acda2798b3dd4f814e refs/tags/signed-tag
|
||||
9433b2a62b964c17a4485ae180f45f595d3e69d31b786087775e28c6b6399df0 refs/tags/signed-tag^{}
|
||||
171822a62559f3aa28a00aa3785dbe915d6a8eb02712682740db44fc8bd2187a refs/tags/test
|
||||
6aae864a3d1d0d6a5be0cc64028c1e7021e2632b031fd8eb82afc5a283d1c3d1 refs/tags/test^{}
|
Binary file not shown.
@ -0,0 +1,2 @@
|
||||
P pack-c01aa121b9c5e345fe0da2f9be78665970b0c38c6b495d5fc034bc7a7b95334b.pack
|
||||
|
BIN
modules/git/tests/repos/repo1_bare_sha256/objects/pack/pack-c01aa121b9c5e345fe0da2f9be78665970b0c38c6b495d5fc034bc7a7b95334b.bitmap
Normal file
BIN
modules/git/tests/repos/repo1_bare_sha256/objects/pack/pack-c01aa121b9c5e345fe0da2f9be78665970b0c38c6b495d5fc034bc7a7b95334b.bitmap
Normal file
Binary file not shown.
BIN
modules/git/tests/repos/repo1_bare_sha256/objects/pack/pack-c01aa121b9c5e345fe0da2f9be78665970b0c38c6b495d5fc034bc7a7b95334b.idx
Normal file
BIN
modules/git/tests/repos/repo1_bare_sha256/objects/pack/pack-c01aa121b9c5e345fe0da2f9be78665970b0c38c6b495d5fc034bc7a7b95334b.idx
Normal file
Binary file not shown.
BIN
modules/git/tests/repos/repo1_bare_sha256/objects/pack/pack-c01aa121b9c5e345fe0da2f9be78665970b0c38c6b495d5fc034bc7a7b95334b.pack
Normal file
BIN
modules/git/tests/repos/repo1_bare_sha256/objects/pack/pack-c01aa121b9c5e345fe0da2f9be78665970b0c38c6b495d5fc034bc7a7b95334b.pack
Normal file
Binary file not shown.
BIN
modules/git/tests/repos/repo1_bare_sha256/objects/pack/pack-c01aa121b9c5e345fe0da2f9be78665970b0c38c6b495d5fc034bc7a7b95334b.rev
Normal file
BIN
modules/git/tests/repos/repo1_bare_sha256/objects/pack/pack-c01aa121b9c5e345fe0da2f9be78665970b0c38c6b495d5fc034bc7a7b95334b.rev
Normal file
Binary file not shown.
8
modules/git/tests/repos/repo1_bare_sha256/packed-refs
Normal file
8
modules/git/tests/repos/repo1_bare_sha256/packed-refs
Normal file
@ -0,0 +1,8 @@
|
||||
# pack-refs with: peeled fully-peeled sorted
|
||||
42e334efd04cd36eea6da0599913333c26116e1a537ca76e5b6e4af4dda00236 refs/heads/branch1
|
||||
5bc2249e32e0ba40a08879fba2bd4e97a13cb345831549f4bc5649525da8f6cc refs/heads/branch2
|
||||
9433b2a62b964c17a4485ae180f45f595d3e69d31b786087775e28c6b6399df0 refs/heads/main
|
||||
29a82d4fc02e19190fb489cc90d5730ed91970b49f4e39acda2798b3dd4f814e refs/tags/signed-tag
|
||||
^9433b2a62b964c17a4485ae180f45f595d3e69d31b786087775e28c6b6399df0
|
||||
171822a62559f3aa28a00aa3785dbe915d6a8eb02712682740db44fc8bd2187a refs/tags/test
|
||||
^6aae864a3d1d0d6a5be0cc64028c1e7021e2632b031fd8eb82afc5a283d1c3d1
|
@ -0,0 +1 @@
|
||||
9433b2a62b964c17a4485ae180f45f595d3e69d31b786087775e28c6b6399df0
|
1
modules/git/tests/repos/repo5_pulls_sha256/HEAD
Normal file
1
modules/git/tests/repos/repo5_pulls_sha256/HEAD
Normal file
@ -0,0 +1 @@
|
||||
ref: refs/heads/main
|
6
modules/git/tests/repos/repo5_pulls_sha256/config
Normal file
6
modules/git/tests/repos/repo5_pulls_sha256/config
Normal file
@ -0,0 +1,6 @@
|
||||
[core]
|
||||
repositoryformatversion = 1
|
||||
filemode = true
|
||||
bare = true
|
||||
[extensions]
|
||||
objectformat = sha256
|
1
modules/git/tests/repos/repo5_pulls_sha256/description
Normal file
1
modules/git/tests/repos/repo5_pulls_sha256/description
Normal file
@ -0,0 +1 @@
|
||||
Unnamed repository; edit this file 'description' to name the repository.
|
4
modules/git/tests/repos/repo5_pulls_sha256/info/refs
Normal file
4
modules/git/tests/repos/repo5_pulls_sha256/info/refs
Normal file
@ -0,0 +1,4 @@
|
||||
35ecd0f946c8baeb76fa5a3876f46bf35218655e2304d8505026fa4bfb496a4b refs/heads/main
|
||||
35ecd0f946c8baeb76fa5a3876f46bf35218655e2304d8505026fa4bfb496a4b refs/heads/main-clone
|
||||
7f50a4906503378b0bbb7d61bd2ca8d8d8ff4f7a2474980f99402d742ccc9665 refs/heads/test-patch-1
|
||||
1e35a51dc00fd7de730344c07061acfe80e8117e075ac979b6a29a3a045190ca refs/tags/v0.9.99
|
Binary file not shown.
@ -0,0 +1,2 @@
|
||||
P pack-bfe8f09d42ef5dd1610bf42641fe145d4a02b788eb26c31022a362312660a29d.pack
|
||||
|
BIN
modules/git/tests/repos/repo5_pulls_sha256/objects/pack/pack-bfe8f09d42ef5dd1610bf42641fe145d4a02b788eb26c31022a362312660a29d.bitmap
Normal file
BIN
modules/git/tests/repos/repo5_pulls_sha256/objects/pack/pack-bfe8f09d42ef5dd1610bf42641fe145d4a02b788eb26c31022a362312660a29d.bitmap
Normal file
Binary file not shown.
BIN
modules/git/tests/repos/repo5_pulls_sha256/objects/pack/pack-bfe8f09d42ef5dd1610bf42641fe145d4a02b788eb26c31022a362312660a29d.idx
Normal file
BIN
modules/git/tests/repos/repo5_pulls_sha256/objects/pack/pack-bfe8f09d42ef5dd1610bf42641fe145d4a02b788eb26c31022a362312660a29d.idx
Normal file
Binary file not shown.
BIN
modules/git/tests/repos/repo5_pulls_sha256/objects/pack/pack-bfe8f09d42ef5dd1610bf42641fe145d4a02b788eb26c31022a362312660a29d.pack
Normal file
BIN
modules/git/tests/repos/repo5_pulls_sha256/objects/pack/pack-bfe8f09d42ef5dd1610bf42641fe145d4a02b788eb26c31022a362312660a29d.pack
Normal file
Binary file not shown.
BIN
modules/git/tests/repos/repo5_pulls_sha256/objects/pack/pack-bfe8f09d42ef5dd1610bf42641fe145d4a02b788eb26c31022a362312660a29d.rev
Normal file
BIN
modules/git/tests/repos/repo5_pulls_sha256/objects/pack/pack-bfe8f09d42ef5dd1610bf42641fe145d4a02b788eb26c31022a362312660a29d.rev
Normal file
Binary file not shown.
5
modules/git/tests/repos/repo5_pulls_sha256/packed-refs
Normal file
5
modules/git/tests/repos/repo5_pulls_sha256/packed-refs
Normal file
@ -0,0 +1,5 @@
|
||||
# pack-refs with: peeled fully-peeled sorted
|
||||
35ecd0f946c8baeb76fa5a3876f46bf35218655e2304d8505026fa4bfb496a4b refs/heads/main
|
||||
35ecd0f946c8baeb76fa5a3876f46bf35218655e2304d8505026fa4bfb496a4b refs/heads/main-clone
|
||||
7f50a4906503378b0bbb7d61bd2ca8d8d8ff4f7a2474980f99402d742ccc9665 refs/heads/test-patch-1
|
||||
1e35a51dc00fd7de730344c07061acfe80e8117e075ac979b6a29a3a045190ca refs/tags/v0.9.99
|
@ -0,0 +1 @@
|
||||
35ecd0f946c8baeb76fa5a3876f46bf35218655e2304d8505026fa4bfb496a4b
|
1
modules/git/tests/repos/repo6_blame_sha256/HEAD
Normal file
1
modules/git/tests/repos/repo6_blame_sha256/HEAD
Normal file
@ -0,0 +1 @@
|
||||
ref: refs/heads/main
|
6
modules/git/tests/repos/repo6_blame_sha256/config
Normal file
6
modules/git/tests/repos/repo6_blame_sha256/config
Normal file
@ -0,0 +1,6 @@
|
||||
[core]
|
||||
repositoryformatversion = 1
|
||||
filemode = true
|
||||
bare = true
|
||||
[extensions]
|
||||
objectformat = sha256
|
1
modules/git/tests/repos/repo6_blame_sha256/description
Normal file
1
modules/git/tests/repos/repo6_blame_sha256/description
Normal file
@ -0,0 +1 @@
|
||||
Unnamed repository; edit this file 'description' to name the repository.
|
6
modules/git/tests/repos/repo6_blame_sha256/info/exclude
Normal file
6
modules/git/tests/repos/repo6_blame_sha256/info/exclude
Normal file
@ -0,0 +1,6 @@
|
||||
# git ls-files --others --exclude-from=.git/info/exclude
|
||||
# Lines that start with '#' are comments.
|
||||
# For a project mostly in C, the following would be a good set of
|
||||
# exclude patterns (uncomment them if you want to use them):
|
||||
# *.[oa]
|
||||
# *~
|
1
modules/git/tests/repos/repo6_blame_sha256/info/refs
Normal file
1
modules/git/tests/repos/repo6_blame_sha256/info/refs
Normal file
@ -0,0 +1 @@
|
||||
e2f5660e15159082902960af0ed74fc144921d2b0c80e069361853b3ece29ba3 refs/heads/main
|
Binary file not shown.
@ -0,0 +1,2 @@
|
||||
P pack-fcb8a221b76025fd8415d3c562b611ac24312a5ffc3d3703d7c5cc906bdaee8e.pack
|
||||
|
BIN
modules/git/tests/repos/repo6_blame_sha256/objects/pack/pack-fcb8a221b76025fd8415d3c562b611ac24312a5ffc3d3703d7c5cc906bdaee8e.bitmap
Normal file
BIN
modules/git/tests/repos/repo6_blame_sha256/objects/pack/pack-fcb8a221b76025fd8415d3c562b611ac24312a5ffc3d3703d7c5cc906bdaee8e.bitmap
Normal file
Binary file not shown.
BIN
modules/git/tests/repos/repo6_blame_sha256/objects/pack/pack-fcb8a221b76025fd8415d3c562b611ac24312a5ffc3d3703d7c5cc906bdaee8e.idx
Normal file
BIN
modules/git/tests/repos/repo6_blame_sha256/objects/pack/pack-fcb8a221b76025fd8415d3c562b611ac24312a5ffc3d3703d7c5cc906bdaee8e.idx
Normal file
Binary file not shown.
BIN
modules/git/tests/repos/repo6_blame_sha256/objects/pack/pack-fcb8a221b76025fd8415d3c562b611ac24312a5ffc3d3703d7c5cc906bdaee8e.pack
Normal file
BIN
modules/git/tests/repos/repo6_blame_sha256/objects/pack/pack-fcb8a221b76025fd8415d3c562b611ac24312a5ffc3d3703d7c5cc906bdaee8e.pack
Normal file
Binary file not shown.
BIN
modules/git/tests/repos/repo6_blame_sha256/objects/pack/pack-fcb8a221b76025fd8415d3c562b611ac24312a5ffc3d3703d7c5cc906bdaee8e.rev
Normal file
BIN
modules/git/tests/repos/repo6_blame_sha256/objects/pack/pack-fcb8a221b76025fd8415d3c562b611ac24312a5ffc3d3703d7c5cc906bdaee8e.rev
Normal file
Binary file not shown.
2
modules/git/tests/repos/repo6_blame_sha256/packed-refs
Normal file
2
modules/git/tests/repos/repo6_blame_sha256/packed-refs
Normal file
@ -0,0 +1,2 @@
|
||||
# pack-refs with: peeled fully-peeled sorted
|
||||
e2f5660e15159082902960af0ed74fc144921d2b0c80e069361853b3ece29ba3 refs/heads/main
|
@ -0,0 +1 @@
|
||||
e2f5660e15159082902960af0ed74fc144921d2b0c80e069361853b3ece29ba3
|
1
modules/git/tests/repos/repo6_merge_sha256/HEAD
Normal file
1
modules/git/tests/repos/repo6_merge_sha256/HEAD
Normal file
@ -0,0 +1 @@
|
||||
ref: refs/heads/main
|
6
modules/git/tests/repos/repo6_merge_sha256/config
Normal file
6
modules/git/tests/repos/repo6_merge_sha256/config
Normal file
@ -0,0 +1,6 @@
|
||||
[core]
|
||||
repositoryformatversion = 1
|
||||
filemode = true
|
||||
bare = true
|
||||
[extensions]
|
||||
objectformat = sha256
|
1
modules/git/tests/repos/repo6_merge_sha256/description
Normal file
1
modules/git/tests/repos/repo6_merge_sha256/description
Normal file
@ -0,0 +1 @@
|
||||
Unnamed repository; edit this file 'description' to name the repository.
|
6
modules/git/tests/repos/repo6_merge_sha256/info/exclude
Normal file
6
modules/git/tests/repos/repo6_merge_sha256/info/exclude
Normal file
@ -0,0 +1,6 @@
|
||||
# git ls-files --others --exclude-from=.git/info/exclude
|
||||
# Lines that start with '#' are comments.
|
||||
# For a project mostly in C, the following would be a good set of
|
||||
# exclude patterns (uncomment them if you want to use them):
|
||||
# *.[oa]
|
||||
# *~
|
4
modules/git/tests/repos/repo6_merge_sha256/info/refs
Normal file
4
modules/git/tests/repos/repo6_merge_sha256/info/refs
Normal file
@ -0,0 +1,4 @@
|
||||
d2e5609f630dd8db500f5298d05d16def282412e3e66ed68cc7d0833b29129a1 refs/heads/main
|
||||
b45258e9823233edea2d40d183742f29630e1e69300479fb4a55eabfe9b1d8bf refs/heads/merge/add_file
|
||||
ff2b996e2fa366146300e4c9e51ccb6818147b360e46fa1437334f4a690955ce refs/heads/merge/modify_file
|
||||
da1ded40dc8e5b7c564171f4bf2fc8370487decfb1cb6a99ef28f3ed73d09172 refs/heads/merge/remove_file
|
Binary file not shown.
@ -0,0 +1,3 @@
|
||||
P pack-2fff0848f8d8eab8f7902ac91ab6a096c7530f577d5c0a79c63d9ac2b44f7510.pack
|
||||
P pack-65162b86afdbac3c566696d487e67bb2a4a5501ca1fa3528fad8a9474fba7e50.pack
|
||||
|
BIN
modules/git/tests/repos/repo6_merge_sha256/objects/pack/pack-2fff0848f8d8eab8f7902ac91ab6a096c7530f577d5c0a79c63d9ac2b44f7510.bitmap
Normal file
BIN
modules/git/tests/repos/repo6_merge_sha256/objects/pack/pack-2fff0848f8d8eab8f7902ac91ab6a096c7530f577d5c0a79c63d9ac2b44f7510.bitmap
Normal file
Binary file not shown.
BIN
modules/git/tests/repos/repo6_merge_sha256/objects/pack/pack-2fff0848f8d8eab8f7902ac91ab6a096c7530f577d5c0a79c63d9ac2b44f7510.idx
Normal file
BIN
modules/git/tests/repos/repo6_merge_sha256/objects/pack/pack-2fff0848f8d8eab8f7902ac91ab6a096c7530f577d5c0a79c63d9ac2b44f7510.idx
Normal file
Binary file not shown.
BIN
modules/git/tests/repos/repo6_merge_sha256/objects/pack/pack-2fff0848f8d8eab8f7902ac91ab6a096c7530f577d5c0a79c63d9ac2b44f7510.pack
Normal file
BIN
modules/git/tests/repos/repo6_merge_sha256/objects/pack/pack-2fff0848f8d8eab8f7902ac91ab6a096c7530f577d5c0a79c63d9ac2b44f7510.pack
Normal file
Binary file not shown.
BIN
modules/git/tests/repos/repo6_merge_sha256/objects/pack/pack-2fff0848f8d8eab8f7902ac91ab6a096c7530f577d5c0a79c63d9ac2b44f7510.rev
Normal file
BIN
modules/git/tests/repos/repo6_merge_sha256/objects/pack/pack-2fff0848f8d8eab8f7902ac91ab6a096c7530f577d5c0a79c63d9ac2b44f7510.rev
Normal file
Binary file not shown.
BIN
modules/git/tests/repos/repo6_merge_sha256/objects/pack/pack-65162b86afdbac3c566696d487e67bb2a4a5501ca1fa3528fad8a9474fba7e50.idx
Normal file
BIN
modules/git/tests/repos/repo6_merge_sha256/objects/pack/pack-65162b86afdbac3c566696d487e67bb2a4a5501ca1fa3528fad8a9474fba7e50.idx
Normal file
Binary file not shown.
BIN
modules/git/tests/repos/repo6_merge_sha256/objects/pack/pack-65162b86afdbac3c566696d487e67bb2a4a5501ca1fa3528fad8a9474fba7e50.mtimes
Normal file
BIN
modules/git/tests/repos/repo6_merge_sha256/objects/pack/pack-65162b86afdbac3c566696d487e67bb2a4a5501ca1fa3528fad8a9474fba7e50.mtimes
Normal file
Binary file not shown.
BIN
modules/git/tests/repos/repo6_merge_sha256/objects/pack/pack-65162b86afdbac3c566696d487e67bb2a4a5501ca1fa3528fad8a9474fba7e50.pack
Normal file
BIN
modules/git/tests/repos/repo6_merge_sha256/objects/pack/pack-65162b86afdbac3c566696d487e67bb2a4a5501ca1fa3528fad8a9474fba7e50.pack
Normal file
Binary file not shown.
BIN
modules/git/tests/repos/repo6_merge_sha256/objects/pack/pack-65162b86afdbac3c566696d487e67bb2a4a5501ca1fa3528fad8a9474fba7e50.rev
Normal file
BIN
modules/git/tests/repos/repo6_merge_sha256/objects/pack/pack-65162b86afdbac3c566696d487e67bb2a4a5501ca1fa3528fad8a9474fba7e50.rev
Normal file
Binary file not shown.
5
modules/git/tests/repos/repo6_merge_sha256/packed-refs
Normal file
5
modules/git/tests/repos/repo6_merge_sha256/packed-refs
Normal file
@ -0,0 +1,5 @@
|
||||
# pack-refs with: peeled fully-peeled sorted
|
||||
d2e5609f630dd8db500f5298d05d16def282412e3e66ed68cc7d0833b29129a1 refs/heads/main
|
||||
b45258e9823233edea2d40d183742f29630e1e69300479fb4a55eabfe9b1d8bf refs/heads/merge/add_file
|
||||
ff2b996e2fa366146300e4c9e51ccb6818147b360e46fa1437334f4a690955ce refs/heads/merge/modify_file
|
||||
da1ded40dc8e5b7c564171f4bf2fc8370487decfb1cb6a99ef28f3ed73d09172 refs/heads/merge/remove_file
|
@ -0,0 +1 @@
|
||||
d2e5609f630dd8db500f5298d05d16def282412e3e66ed68cc7d0833b29129a1
|
@ -45,19 +45,19 @@ var (
|
||||
|
||||
// valid chars in encoded path and parameter: [-+~_%.a-zA-Z0-9/]
|
||||
|
||||
// sha1CurrentPattern matches string that represents a commit SHA, e.g. d8a994ef243349f321568f9e36d5c3f444b99cae
|
||||
// Although SHA1 hashes are 40 chars long, the regex matches the hash from 7 to 40 chars in length
|
||||
// hashCurrentPattern matches string that represents a commit SHA, e.g. d8a994ef243349f321568f9e36d5c3f444b99cae
|
||||
// Although SHA1 hashes are 40 chars long, SHA256 are 64, the regex matches the hash from 7 to 64 chars in length
|
||||
// so that abbreviated hash links can be used as well. This matches git and GitHub usability.
|
||||
sha1CurrentPattern = regexp.MustCompile(`(?:\s|^|\(|\[)([0-9a-f]{7,40})(?:\s|$|\)|\]|[.,](\s|$))`)
|
||||
hashCurrentPattern = regexp.MustCompile(`(?:\s|^|\(|\[)([0-9a-f]{7,64})(?:\s|$|\)|\]|[.,](\s|$))`)
|
||||
|
||||
// shortLinkPattern matches short but difficult to parse [[name|link|arg=test]] syntax
|
||||
shortLinkPattern = regexp.MustCompile(`\[\[(.*?)\]\](\w*)`)
|
||||
|
||||
// anySHA1Pattern splits url containing SHA into parts
|
||||
anySHA1Pattern = regexp.MustCompile(`https?://(?:\S+/){4,5}([0-9a-f]{40})(/[-+~_%.a-zA-Z0-9/]+)?(#[-+~_%.a-zA-Z0-9]+)?`)
|
||||
anyHashPattern = regexp.MustCompile(`https?://(?:\S+/){4,5}([0-9a-f]{40,64})(/[-+~_%.a-zA-Z0-9/]+)?(#[-+~_%.a-zA-Z0-9]+)?`)
|
||||
|
||||
// comparePattern matches "http://domain/org/repo/compare/COMMIT1...COMMIT2#hash"
|
||||
comparePattern = regexp.MustCompile(`https?://(?:\S+/){4,5}([0-9a-f]{7,40})(\.\.\.?)([0-9a-f]{7,40})?(#[-+~_%.a-zA-Z0-9]+)?`)
|
||||
comparePattern = regexp.MustCompile(`https?://(?:\S+/){4,5}([0-9a-f]{7,64})(\.\.\.?)([0-9a-f]{7,64})?(#[-+~_%.a-zA-Z0-9]+)?`)
|
||||
|
||||
validLinksPattern = regexp.MustCompile(`^[a-z][\w-]+://`)
|
||||
|
||||
@ -171,13 +171,13 @@ type processor func(ctx *RenderContext, node *html.Node)
|
||||
var defaultProcessors = []processor{
|
||||
fullIssuePatternProcessor,
|
||||
comparePatternProcessor,
|
||||
fullSha1PatternProcessor,
|
||||
fullHashPatternProcessor,
|
||||
shortLinkProcessor,
|
||||
linkProcessor,
|
||||
mentionProcessor,
|
||||
issueIndexPatternProcessor,
|
||||
commitCrossReferencePatternProcessor,
|
||||
sha1CurrentPatternProcessor,
|
||||
hashCurrentPatternProcessor,
|
||||
emailAddressProcessor,
|
||||
emojiProcessor,
|
||||
emojiShortCodeProcessor,
|
||||
@ -199,12 +199,12 @@ func PostProcess(
|
||||
var commitMessageProcessors = []processor{
|
||||
fullIssuePatternProcessor,
|
||||
comparePatternProcessor,
|
||||
fullSha1PatternProcessor,
|
||||
fullHashPatternProcessor,
|
||||
linkProcessor,
|
||||
mentionProcessor,
|
||||
issueIndexPatternProcessor,
|
||||
commitCrossReferencePatternProcessor,
|
||||
sha1CurrentPatternProcessor,
|
||||
hashCurrentPatternProcessor,
|
||||
emailAddressProcessor,
|
||||
emojiProcessor,
|
||||
emojiShortCodeProcessor,
|
||||
@ -231,12 +231,12 @@ func RenderCommitMessage(
|
||||
var commitMessageSubjectProcessors = []processor{
|
||||
fullIssuePatternProcessor,
|
||||
comparePatternProcessor,
|
||||
fullSha1PatternProcessor,
|
||||
fullHashPatternProcessor,
|
||||
linkProcessor,
|
||||
mentionProcessor,
|
||||
issueIndexPatternProcessor,
|
||||
commitCrossReferencePatternProcessor,
|
||||
sha1CurrentPatternProcessor,
|
||||
hashCurrentPatternProcessor,
|
||||
emojiShortCodeProcessor,
|
||||
emojiProcessor,
|
||||
}
|
||||
@ -273,7 +273,7 @@ func RenderIssueTitle(
|
||||
return renderProcessString(ctx, []processor{
|
||||
issueIndexPatternProcessor,
|
||||
commitCrossReferencePatternProcessor,
|
||||
sha1CurrentPatternProcessor,
|
||||
hashCurrentPatternProcessor,
|
||||
emojiShortCodeProcessor,
|
||||
emojiProcessor,
|
||||
}, title)
|
||||
@ -946,15 +946,15 @@ func commitCrossReferencePatternProcessor(ctx *RenderContext, node *html.Node) {
|
||||
}
|
||||
}
|
||||
|
||||
// fullSha1PatternProcessor renders SHA containing URLs
|
||||
func fullSha1PatternProcessor(ctx *RenderContext, node *html.Node) {
|
||||
// fullHashPatternProcessor renders SHA containing URLs
|
||||
func fullHashPatternProcessor(ctx *RenderContext, node *html.Node) {
|
||||
if ctx.Metas == nil {
|
||||
return
|
||||
}
|
||||
|
||||
next := node.NextSibling
|
||||
for node != nil && node != next {
|
||||
m := anySHA1Pattern.FindStringSubmatchIndex(node.Data)
|
||||
m := anyHashPattern.FindStringSubmatchIndex(node.Data)
|
||||
if m == nil {
|
||||
return
|
||||
}
|
||||
@ -1111,9 +1111,9 @@ func emojiProcessor(ctx *RenderContext, node *html.Node) {
|
||||
}
|
||||
}
|
||||
|
||||
// sha1CurrentPatternProcessor renders SHA1 strings to corresponding links that
|
||||
// hashCurrentPatternProcessor renders SHA1 strings to corresponding links that
|
||||
// are assumed to be in the same repository.
|
||||
func sha1CurrentPatternProcessor(ctx *RenderContext, node *html.Node) {
|
||||
func hashCurrentPatternProcessor(ctx *RenderContext, node *html.Node) {
|
||||
if ctx.Metas == nil || ctx.Metas["user"] == "" || ctx.Metas["repo"] == "" || ctx.Metas["repoPath"] == "" {
|
||||
return
|
||||
}
|
||||
@ -1124,7 +1124,7 @@ func sha1CurrentPatternProcessor(ctx *RenderContext, node *html.Node) {
|
||||
ctx.ShaExistCache = make(map[string]bool)
|
||||
}
|
||||
for node != nil && node != next && start < len(node.Data) {
|
||||
m := sha1CurrentPattern.FindStringSubmatchIndex(node.Data[start:])
|
||||
m := hashCurrentPattern.FindStringSubmatchIndex(node.Data[start:])
|
||||
if m == nil {
|
||||
return
|
||||
}
|
||||
|
@ -390,10 +390,10 @@ func TestRegExp_sha1CurrentPattern(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, testCase := range trueTestCases {
|
||||
assert.True(t, sha1CurrentPattern.MatchString(testCase))
|
||||
assert.True(t, hashCurrentPattern.MatchString(testCase))
|
||||
}
|
||||
for _, testCase := range falseTestCases {
|
||||
assert.False(t, sha1CurrentPattern.MatchString(testCase))
|
||||
assert.False(t, hashCurrentPattern.MatchString(testCase))
|
||||
}
|
||||
}
|
||||
|
||||
@ -427,7 +427,7 @@ func TestRegExp_anySHA1Pattern(t *testing.T) {
|
||||
}
|
||||
|
||||
for k, v := range testCases {
|
||||
assert.Equal(t, anySHA1Pattern.FindStringSubmatch(k)[1:], v)
|
||||
assert.Equal(t, anyHashPattern.FindStringSubmatch(k)[1:], v)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -39,7 +39,7 @@ var (
|
||||
crossReferenceIssueNumericPattern = regexp.MustCompile(`(?:\s|^|\(|\[)([0-9a-zA-Z-_\.]+/[0-9a-zA-Z-_\.]+[#!][0-9]+)(?:\s|$|\)|\]|[:;,.?!]\s|[:;,.?!]$)`)
|
||||
// crossReferenceCommitPattern matches a string that references a commit in a different repository
|
||||
// e.g. go-gitea/gitea@d8a994ef, go-gitea/gitea@d8a994ef243349f321568f9e36d5c3f444b99cae (7-40 characters)
|
||||
crossReferenceCommitPattern = regexp.MustCompile(`(?:\s|^|\(|\[)([0-9a-zA-Z-_\.]+)/([0-9a-zA-Z-_\.]+)@([0-9a-f]{7,40})(?:\s|$|\)|\]|[:;,.?!]\s|[:;,.?!]$)`)
|
||||
crossReferenceCommitPattern = regexp.MustCompile(`(?:\s|^|\(|\[)([0-9a-zA-Z-_\.]+)/([0-9a-zA-Z-_\.]+)@([0-9a-f]{7,64})(?:\s|$|\)|\]|[:;,.?!]\s|[:;,.?!]$)`)
|
||||
// spaceTrimmedPattern let's find the trailing space
|
||||
spaceTrimmedPattern = regexp.MustCompile(`(?:.*[0-9a-zA-Z-_])\s`)
|
||||
// timeLogPattern matches string for time tracking
|
||||
|
@ -343,7 +343,7 @@ func TestFindRenderizableCommitCrossReference(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
Input: "go-gitea/gitea@abcd1234abcd1234abcd1234abcd1234abcd12340", // longer than 40 characters
|
||||
Input: "go-gitea/gitea@abcd1234abcd1234abcd1234abcd1234abcd12341234512345123451234512345", // longer than 64 characters
|
||||
Expected: nil,
|
||||
},
|
||||
{
|
||||
|
@ -105,6 +105,9 @@ type Repository struct {
|
||||
AvatarURL string `json:"avatar_url"`
|
||||
Internal bool `json:"internal"`
|
||||
MirrorInterval string `json:"mirror_interval"`
|
||||
// ObjectFormatName of the underlying git repository
|
||||
// enum: sha1,sha256
|
||||
ObjectFormatName string `json:"object_format_name"`
|
||||
// swagger:strfmt date-time
|
||||
MirrorUpdated time.Time `json:"mirror_updated,omitempty"`
|
||||
RepoTransfer *RepoTransfer `json:"repo_transfer"`
|
||||
@ -139,6 +142,9 @@ type CreateRepoOption struct {
|
||||
// TrustModel of the repository
|
||||
// enum: default,collaborator,committer,collaboratorcommitter
|
||||
TrustModel string `json:"trust_model"`
|
||||
// ObjectFormatName of the underlying git repository
|
||||
// enum: sha1,sha256
|
||||
ObjectFormatName string `json:"object_format_name" binding:"MaxSize(6)"`
|
||||
}
|
||||
|
||||
// EditRepoOption options when editing a repository's properties
|
||||
|
@ -41,3 +41,7 @@ func (su *StringUtils) Cut(s, sep string) []any {
|
||||
func (su *StringUtils) EllipsisString(s string, max int) string {
|
||||
return base.EllipsisString(s, max)
|
||||
}
|
||||
|
||||
func (su *StringUtils) ToUpper(s string) string {
|
||||
return strings.ToUpper(s)
|
||||
}
|
||||
|
@ -970,6 +970,8 @@ issue_labels_helper = Select an issue label set.
|
||||
license = License
|
||||
license_helper = Select a license file.
|
||||
license_helper_desc = A license governs what others can and can't do with your code. Not sure which one is right for your project? See <a target="_blank" rel="noopener noreferrer" href="%s">Choose a license.</a>
|
||||
object_format = Object Format
|
||||
object_format_helper = Object format of the repository. Cannot be changed later. SHA1 is most compatible.
|
||||
readme = README
|
||||
readme_helper = Select a README file template.
|
||||
readme_helper_desc = This is the place where you can write a complete description for your project.
|
||||
@ -1038,6 +1040,7 @@ desc.public = Public
|
||||
desc.template = Template
|
||||
desc.internal = Internal
|
||||
desc.archived = Archived
|
||||
desc.sha256 = SHA256
|
||||
|
||||
template.items = Template Items
|
||||
template.git_content = Git Content (Default Branch)
|
||||
|
@ -253,7 +253,7 @@ func CreateUserRepo(ctx *context.APIContext, owner *user_model.User, opt api.Cre
|
||||
DefaultBranch: opt.DefaultBranch,
|
||||
TrustModel: repo_model.ToTrustModel(opt.TrustModel),
|
||||
IsTemplate: opt.Template,
|
||||
ObjectFormatName: git.Sha1ObjectFormat.Name(),
|
||||
ObjectFormatName: opt.ObjectFormatName,
|
||||
})
|
||||
if err != nil {
|
||||
if repo_model.IsErrRepoAlreadyExist(err) {
|
||||
|
@ -36,8 +36,8 @@ func gitHTTPRouters(m *web.Route) {
|
||||
m.Methods("GET,OPTIONS", "/objects/info/http-alternates", repo.GetTextFile("objects/info/http-alternates"))
|
||||
m.Methods("GET,OPTIONS", "/objects/info/packs", repo.GetInfoPacks)
|
||||
m.Methods("GET,OPTIONS", "/objects/info/{file:[^/]*}", repo.GetTextFile(""))
|
||||
m.Methods("GET,OPTIONS", "/objects/{head:[0-9a-f]{2}}/{hash:[0-9a-f]{38}}", repo.GetLooseObject)
|
||||
m.Methods("GET,OPTIONS", "/objects/pack/pack-{file:[0-9a-f]{40}}.pack", repo.GetPackFile)
|
||||
m.Methods("GET,OPTIONS", "/objects/pack/pack-{file:[0-9a-f]{40}}.idx", repo.GetIdxFile)
|
||||
m.Methods("GET,OPTIONS", "/objects/{head:[0-9a-f]{2}}/{hash:[0-9a-f]{38,62}}", repo.GetLooseObject)
|
||||
m.Methods("GET,OPTIONS", "/objects/pack/pack-{file:[0-9a-f]{40,64}}.pack", repo.GetPackFile)
|
||||
m.Methods("GET,OPTIONS", "/objects/pack/pack-{file:[0-9a-f]{40,64}}.idx", repo.GetIdxFile)
|
||||
}, ignSignInAndCsrf, requireSignIn, repo.HTTPGitEnabledHandler, repo.CorsHandler(), context_service.UserAssignmentWeb())
|
||||
}
|
||||
|
@ -159,7 +159,6 @@ func Create(ctx *context.Context) {
|
||||
ctx.Data["private"] = getRepoPrivate(ctx)
|
||||
ctx.Data["IsForcedPrivate"] = setting.Repository.ForcePrivate
|
||||
ctx.Data["default_branch"] = setting.Repository.DefaultBranch
|
||||
ctx.Data["hash_type"] = "sha1"
|
||||
|
||||
ctxUser := checkContextUser(ctx, ctx.FormInt64("org"))
|
||||
if ctx.Written() {
|
||||
@ -179,6 +178,8 @@ func Create(ctx *context.Context) {
|
||||
|
||||
ctx.Data["CanCreateRepo"] = ctx.Doer.CanCreateRepo()
|
||||
ctx.Data["MaxCreationLimit"] = ctx.Doer.MaxCreationLimit()
|
||||
ctx.Data["SupportedObjectFormats"] = git.SupportedObjectFormats
|
||||
ctx.Data["DefaultObjectFormat"] = git.Sha1ObjectFormat
|
||||
|
||||
ctx.HTML(http.StatusOK, tplCreate)
|
||||
}
|
||||
|
@ -1235,7 +1235,7 @@ func registerRoutes(m *web.Route) {
|
||||
Post(web.Bind(forms.UploadRepoFileForm{}), repo.UploadFilePost)
|
||||
m.Combo("/_diffpatch/*").Get(repo.NewDiffPatch).
|
||||
Post(web.Bind(forms.EditRepoFileForm{}), repo.NewDiffPatchPost)
|
||||
m.Combo("/_cherrypick/{sha:([a-f0-9]{7,40})}/*").Get(repo.CherryPick).
|
||||
m.Combo("/_cherrypick/{sha:([a-f0-9]{7,64})}/*").Get(repo.CherryPick).
|
||||
Post(web.Bind(forms.CherryPickForm{}), repo.CherryPickPost)
|
||||
}, repo.MustBeEditable)
|
||||
m.Group("", func() {
|
||||
@ -1377,8 +1377,8 @@ func registerRoutes(m *web.Route) {
|
||||
m.Combo("/*").
|
||||
Get(repo.Wiki).
|
||||
Post(context.RepoMustNotBeArchived(), reqSignIn, reqRepoWikiWriter, web.Bind(forms.NewWikiForm{}), repo.WikiPost)
|
||||
m.Get("/commit/{sha:[a-f0-9]{7,40}}", repo.SetEditorconfigIfExists, repo.SetDiffViewStyle, repo.SetWhitespaceBehavior, repo.Diff)
|
||||
m.Get("/commit/{sha:[a-f0-9]{7,40}}.{ext:patch|diff}", repo.RawDiff)
|
||||
m.Get("/commit/{sha:[a-f0-9]{7,64}}", repo.SetEditorconfigIfExists, repo.SetDiffViewStyle, repo.SetWhitespaceBehavior, repo.Diff)
|
||||
m.Get("/commit/{sha:[a-f0-9]{7,64}}.{ext:patch|diff}", repo.RawDiff)
|
||||
}, repo.MustEnableWiki, func(ctx *context.Context) {
|
||||
ctx.Data["PageIsWiki"] = true
|
||||
ctx.Data["CloneButtonOriginLink"] = ctx.Repo.Repository.WikiCloneLink()
|
||||
@ -1498,9 +1498,9 @@ func registerRoutes(m *web.Route) {
|
||||
|
||||
m.Group("", func() {
|
||||
m.Get("/graph", repo.Graph)
|
||||
m.Get("/commit/{sha:([a-f0-9]{7,40})$}", repo.SetEditorconfigIfExists, repo.SetDiffViewStyle, repo.SetWhitespaceBehavior, repo.Diff)
|
||||
m.Get("/commit/{sha:([a-f0-9]{7,40})$}/load-branches-and-tags", repo.LoadBranchesAndTags)
|
||||
m.Get("/cherry-pick/{sha:([a-f0-9]{7,40})$}", repo.SetEditorconfigIfExists, repo.CherryPick)
|
||||
m.Get("/commit/{sha:([a-f0-9]{7,64})$}", repo.SetEditorconfigIfExists, repo.SetDiffViewStyle, repo.SetWhitespaceBehavior, repo.Diff)
|
||||
m.Get("/commit/{sha:([a-f0-9]{7,64})$}/load-branches-and-tags", repo.LoadBranchesAndTags)
|
||||
m.Get("/cherry-pick/{sha:([a-f0-9]{7,64})$}", repo.SetEditorconfigIfExists, repo.CherryPick)
|
||||
}, repo.MustBeNotEmpty, context.RepoRef(), reqRepoCodeReader)
|
||||
|
||||
m.Get("/rss/branch/*", context.RepoRefByType(context.RepoRefBranch), feedEnabled, feed.RenderBranchFeed)
|
||||
@ -1517,7 +1517,7 @@ func registerRoutes(m *web.Route) {
|
||||
m.Group("", func() {
|
||||
m.Get("/forks", repo.Forks)
|
||||
}, context.RepoRef(), reqRepoCodeReader)
|
||||
m.Get("/commit/{sha:([a-f0-9]{7,40})}.{ext:patch|diff}", repo.MustBeNotEmpty, reqRepoCodeReader, repo.RawDiff)
|
||||
m.Get("/commit/{sha:([a-f0-9]{7,64})}.{ext:patch|diff}", repo.MustBeNotEmpty, reqRepoCodeReader, repo.RawDiff)
|
||||
}, ignSignIn, context.RepoAssignment, context.UnitTypes())
|
||||
|
||||
m.Post("/{username}/{reponame}/lastcommit/*", ignSignInAndCsrf, context.RepoAssignment, context.UnitTypes(), context.RepoRefByType(context.RepoRefCommit), reqRepoCodeReader, repo.LastCommit)
|
||||
|
@ -217,6 +217,10 @@ func CreateRepositoryDirectly(ctx context.Context, doer, u *user_model.User, opt
|
||||
}
|
||||
}
|
||||
|
||||
if opts.ObjectFormatName == "" {
|
||||
opts.ObjectFormatName = git.Sha1ObjectFormat.Name()
|
||||
}
|
||||
|
||||
repo := &repo_model.Repository{
|
||||
OwnerID: u.ID,
|
||||
Owner: u,
|
||||
|
@ -76,17 +76,18 @@ func ForkRepository(ctx context.Context, doer, owner *user_model.User, opts Fork
|
||||
defaultBranch = opts.SingleBranch
|
||||
}
|
||||
repo := &repo_model.Repository{
|
||||
OwnerID: owner.ID,
|
||||
Owner: owner,
|
||||
OwnerName: owner.Name,
|
||||
Name: opts.Name,
|
||||
LowerName: strings.ToLower(opts.Name),
|
||||
Description: opts.Description,
|
||||
DefaultBranch: defaultBranch,
|
||||
IsPrivate: opts.BaseRepo.IsPrivate || opts.BaseRepo.Owner.Visibility == structs.VisibleTypePrivate,
|
||||
IsEmpty: opts.BaseRepo.IsEmpty,
|
||||
IsFork: true,
|
||||
ForkID: opts.BaseRepo.ID,
|
||||
OwnerID: owner.ID,
|
||||
Owner: owner,
|
||||
OwnerName: owner.Name,
|
||||
Name: opts.Name,
|
||||
LowerName: strings.ToLower(opts.Name),
|
||||
Description: opts.Description,
|
||||
DefaultBranch: defaultBranch,
|
||||
IsPrivate: opts.BaseRepo.IsPrivate || opts.BaseRepo.Owner.Visibility == structs.VisibleTypePrivate,
|
||||
IsEmpty: opts.BaseRepo.IsEmpty,
|
||||
IsFork: true,
|
||||
ForkID: opts.BaseRepo.ID,
|
||||
ObjectFormatName: opts.BaseRepo.ObjectFormatName,
|
||||
}
|
||||
|
||||
oldRepoPath := opts.BaseRepo.RepoPath()
|
||||
|
@ -67,6 +67,9 @@
|
||||
{{if .IsTemplate}}
|
||||
<span class="ui basic label">{{ctx.Locale.Tr "repo.desc.template"}}</span>
|
||||
{{end}}
|
||||
{{if eq .ObjectFormatName "sha256"}}
|
||||
<span class="ui basic label">{{ctx.Locale.Tr "repo.desc.sha256"}}</span>
|
||||
{{end}}
|
||||
{{if .IsMirror}}
|
||||
{{svg "octicon-mirror"}}
|
||||
{{else if .IsFork}}
|
||||
|
@ -25,6 +25,9 @@
|
||||
{{if .IsTemplate}}
|
||||
<span class="ui basic label">{{ctx.Locale.Tr "repo.desc.template"}}</span>
|
||||
{{end}}
|
||||
{{if eq .ObjectFormatName "sha256"}}
|
||||
<span class="ui basic label">{{ctx.Locale.Tr "repo.desc.sha256"}}</span>
|
||||
{{end}}
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex-item-trailing">
|
||||
|
@ -3,7 +3,7 @@
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="three wide">{{ctx.Locale.Tr "repo.commits.author"}}</th>
|
||||
<th class="two wide sha">SHA1</th>
|
||||
<th class="two wide sha">{{StringUtils.ToUpper $.Repository.ObjectFormatName}}</th>
|
||||
<th class="eight wide message">{{ctx.Locale.Tr "repo.commits.message"}}</th>
|
||||
<th class="two wide right aligned">{{ctx.Locale.Tr "repo.commits.date"}}</th>
|
||||
<th class="one wide"></th>
|
||||
|
@ -185,6 +185,19 @@
|
||||
<input id="default_branch" name="default_branch" value="{{.default_branch}}" placeholder="{{.default_branch}}">
|
||||
<span class="help">{{ctx.Locale.Tr "repo.default_branch_helper"}}</span>
|
||||
</div>
|
||||
<div class="inline field">
|
||||
<label>{{ctx.Locale.Tr "repo.object_format"}}</label>
|
||||
<div class="ui selection owner dropdown">
|
||||
<input type="hidden" id="object_format_name" name="object_format_name" value="{{.DefaultObjectFormat.Name}}" required>
|
||||
<div class="default text">{{.DefaultObjectFormat.Name}}</div>
|
||||
<div class="menu">
|
||||
{{range .SupportedObjectFormats}}
|
||||
<div class="item" data-value="{{.Name}}">{{.Name}}</div>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
<span class="help">{{ctx.Locale.Tr "repo.object_format_helper"}}</span>
|
||||
</div>
|
||||
<div class="inline field">
|
||||
<label>{{ctx.Locale.Tr "repo.template"}}</label>
|
||||
<div class="ui checkbox">
|
||||
|
@ -27,6 +27,9 @@
|
||||
<span class="ui basic label">{{ctx.Locale.Tr "repo.desc.template"}}</span>
|
||||
<div class="repo-icon" data-tooltip-content="{{ctx.Locale.Tr "repo.desc.template"}}">{{svg "octicon-repo-template" 18}}</div>
|
||||
{{end}}
|
||||
{{if eq .ObjectFormatName "sha256"}}
|
||||
<span class="ui basic label">{{ctx.Locale.Tr "repo.desc.sha256"}}</span>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
{{if not (or .IsBeingCreated .IsBroken)}}
|
||||
|
18
templates/swagger/v1_json.tmpl
generated
18
templates/swagger/v1_json.tmpl
generated
@ -18370,6 +18370,15 @@
|
||||
"uniqueItems": true,
|
||||
"x-go-name": "Name"
|
||||
},
|
||||
"object_format_name": {
|
||||
"description": "ObjectFormatName of the underlying git repository",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"sha1",
|
||||
"sha256"
|
||||
],
|
||||
"x-go-name": "ObjectFormatName"
|
||||
},
|
||||
"private": {
|
||||
"description": "Whether the repository is private",
|
||||
"type": "boolean",
|
||||
@ -22185,6 +22194,15 @@
|
||||
"type": "string",
|
||||
"x-go-name": "Name"
|
||||
},
|
||||
"object_format_name": {
|
||||
"description": "ObjectFormatName of the underlying git repository",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"sha1",
|
||||
"sha256"
|
||||
],
|
||||
"x-go-name": "ObjectFormatName"
|
||||
},
|
||||
"open_issues_count": {
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
|
Loading…
x
Reference in New Issue
Block a user