mirror of
https://github.com/go-gitea/gitea.git
synced 2025-07-27 00:01:20 -04:00
Compare commits
3 Commits
7fb6b51470
...
69f2b698c5
Author | SHA1 | Date | |
---|---|---|---|
|
69f2b698c5 | ||
|
20929edc99 | ||
|
408a484224 |
@ -1212,6 +1212,9 @@ LEVEL = Info
|
|||||||
;; Max size of files to be displayed (default is 8MiB)
|
;; Max size of files to be displayed (default is 8MiB)
|
||||||
;MAX_DISPLAY_FILE_SIZE = 8388608
|
;MAX_DISPLAY_FILE_SIZE = 8388608
|
||||||
;;
|
;;
|
||||||
|
;; Detect ambiguous unicode characters in file contents and show warnings on the UI
|
||||||
|
;AMBIGUOUS_UNICODE_DETECTION = true
|
||||||
|
;;
|
||||||
;; Whether the email of the user should be shown in the Explore Users page
|
;; Whether the email of the user should be shown in the Explore Users page
|
||||||
;SHOW_USER_EMAIL = true
|
;SHOW_USER_EMAIL = true
|
||||||
;;
|
;;
|
||||||
|
@ -220,6 +220,7 @@ The following configuration set `Content-Type: application/vnd.android.package-a
|
|||||||
- `THEMES`: **gitea-auto,gitea-light,gitea-dark**: All available themes. Allow users select personalized themes.
|
- `THEMES`: **gitea-auto,gitea-light,gitea-dark**: All available themes. Allow users select personalized themes.
|
||||||
regardless of the value of `DEFAULT_THEME`.
|
regardless of the value of `DEFAULT_THEME`.
|
||||||
- `MAX_DISPLAY_FILE_SIZE`: **8388608**: Max size of files to be displayed (default is 8MiB)
|
- `MAX_DISPLAY_FILE_SIZE`: **8388608**: Max size of files to be displayed (default is 8MiB)
|
||||||
|
- `AMBIGUOUS_UNICODE_DETECTION`: **true**: Detect ambiguous unicode characters in file contents and show warnings on the UI
|
||||||
- `REACTIONS`: All available reactions users can choose on issues/prs and comments
|
- `REACTIONS`: All available reactions users can choose on issues/prs and comments
|
||||||
Values can be emoji alias (:smile:) or a unicode emoji.
|
Values can be emoji alias (:smile:) or a unicode emoji.
|
||||||
For custom reactions, add a tightly cropped square image to public/assets/img/emoji/reaction_name.png
|
For custom reactions, add a tightly cropped square image to public/assets/img/emoji/reaction_name.png
|
||||||
|
@ -20,6 +20,7 @@ import (
|
|||||||
func TestAddDeletedBranch(t *testing.T) {
|
func TestAddDeletedBranch(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
||||||
|
assert.EqualValues(t, git.Sha1ObjectFormat.Name(), repo.ObjectFormatName)
|
||||||
firstBranch := unittest.AssertExistsAndLoadBean(t, &git_model.Branch{ID: 1})
|
firstBranch := unittest.AssertExistsAndLoadBean(t, &git_model.Branch{ID: 1})
|
||||||
|
|
||||||
assert.True(t, firstBranch.IsDeleted)
|
assert.True(t, firstBranch.IsDeleted)
|
||||||
@ -29,8 +30,9 @@ func TestAddDeletedBranch(t *testing.T) {
|
|||||||
secondBranch := unittest.AssertExistsAndLoadBean(t, &git_model.Branch{RepoID: repo.ID, Name: "branch2"})
|
secondBranch := unittest.AssertExistsAndLoadBean(t, &git_model.Branch{RepoID: repo.ID, Name: "branch2"})
|
||||||
assert.True(t, secondBranch.IsDeleted)
|
assert.True(t, secondBranch.IsDeleted)
|
||||||
|
|
||||||
|
objectFormat := git.ObjectFormatFromName(repo.ObjectFormatName)
|
||||||
commit := &git.Commit{
|
commit := &git.Commit{
|
||||||
ID: repo.ObjectFormat.MustIDFromString(secondBranch.CommitID),
|
ID: objectFormat.MustIDFromString(secondBranch.CommitID),
|
||||||
CommitMessage: secondBranch.CommitMessage,
|
CommitMessage: secondBranch.CommitMessage,
|
||||||
Committer: &git.Signature{
|
Committer: &git.Signature{
|
||||||
When: secondBranch.CommitTime.AsLocalTime(),
|
When: secondBranch.CommitTime.AsLocalTime(),
|
||||||
|
@ -180,7 +180,7 @@ type Repository struct {
|
|||||||
IsFsckEnabled bool `xorm:"NOT NULL DEFAULT true"`
|
IsFsckEnabled bool `xorm:"NOT NULL DEFAULT true"`
|
||||||
CloseIssuesViaCommitInAnyBranch bool `xorm:"NOT NULL DEFAULT false"`
|
CloseIssuesViaCommitInAnyBranch bool `xorm:"NOT NULL DEFAULT false"`
|
||||||
Topics []string `xorm:"TEXT JSON"`
|
Topics []string `xorm:"TEXT JSON"`
|
||||||
ObjectFormat git.ObjectFormat `xorm:"-"`
|
ObjectFormatName string `xorm:"-"`
|
||||||
|
|
||||||
TrustModel TrustModelType
|
TrustModel TrustModelType
|
||||||
|
|
||||||
@ -277,7 +277,9 @@ func (repo *Repository) AfterLoad() {
|
|||||||
repo.NumOpenProjects = repo.NumProjects - repo.NumClosedProjects
|
repo.NumOpenProjects = repo.NumProjects - repo.NumClosedProjects
|
||||||
repo.NumOpenActionRuns = repo.NumActionRuns - repo.NumClosedActionRuns
|
repo.NumOpenActionRuns = repo.NumActionRuns - repo.NumClosedActionRuns
|
||||||
|
|
||||||
repo.ObjectFormat = git.ObjectFormatFromID(git.Sha1)
|
// 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.
|
// LoadAttributes loads attributes of the repository.
|
||||||
|
@ -8,11 +8,12 @@
|
|||||||
package charset
|
package charset
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"html/template"
|
||||||
"io"
|
"io"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/translation"
|
"code.gitea.io/gitea/modules/translation"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -20,20 +21,18 @@ import (
|
|||||||
const RuneNBSP = 0xa0
|
const RuneNBSP = 0xa0
|
||||||
|
|
||||||
// EscapeControlHTML escapes the unicode control sequences in a provided html document
|
// EscapeControlHTML escapes the unicode control sequences in a provided html document
|
||||||
func EscapeControlHTML(text string, locale translation.Locale, allowed ...rune) (escaped *EscapeStatus, output string) {
|
func EscapeControlHTML(html template.HTML, locale translation.Locale, allowed ...rune) (escaped *EscapeStatus, output template.HTML) {
|
||||||
sb := &strings.Builder{}
|
sb := &strings.Builder{}
|
||||||
outputStream := &HTMLStreamerWriter{Writer: sb}
|
escaped, _ = EscapeControlReader(strings.NewReader(string(html)), sb, locale, allowed...) // err has been handled in EscapeControlReader
|
||||||
streamer := NewEscapeStreamer(locale, outputStream, allowed...).(*escapeStreamer)
|
return escaped, template.HTML(sb.String())
|
||||||
|
|
||||||
if err := StreamHTML(strings.NewReader(text), streamer); err != nil {
|
|
||||||
streamer.escaped.HasError = true
|
|
||||||
log.Error("Error whilst escaping: %v", err)
|
|
||||||
}
|
|
||||||
return streamer.escaped, sb.String()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// EscapeControlReaders escapes the unicode control sequences in a provided reader of HTML content and writer in a locale and returns the findings as an EscapeStatus and the escaped []byte
|
// EscapeControlReader escapes the unicode control sequences in a provided reader of HTML content and writer in a locale and returns the findings as an EscapeStatus
|
||||||
func EscapeControlReader(reader io.Reader, writer io.Writer, locale translation.Locale, allowed ...rune) (escaped *EscapeStatus, err error) {
|
func EscapeControlReader(reader io.Reader, writer io.Writer, locale translation.Locale, allowed ...rune) (escaped *EscapeStatus, err error) {
|
||||||
|
if !setting.UI.AmbiguousUnicodeDetection {
|
||||||
|
_, err = io.Copy(writer, reader)
|
||||||
|
return &EscapeStatus{}, err
|
||||||
|
}
|
||||||
outputStream := &HTMLStreamerWriter{Writer: writer}
|
outputStream := &HTMLStreamerWriter{Writer: writer}
|
||||||
streamer := NewEscapeStreamer(locale, outputStream, allowed...).(*escapeStreamer)
|
streamer := NewEscapeStreamer(locale, outputStream, allowed...).(*escapeStreamer)
|
||||||
|
|
||||||
@ -43,41 +42,3 @@ func EscapeControlReader(reader io.Reader, writer io.Writer, locale translation.
|
|||||||
}
|
}
|
||||||
return streamer.escaped, err
|
return streamer.escaped, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// EscapeControlStringReader escapes the unicode control sequences in a provided reader of string content and writer in a locale and returns the findings as an EscapeStatus and the escaped []byte. HTML line breaks are not inserted after every newline by this method.
|
|
||||||
func EscapeControlStringReader(reader io.Reader, writer io.Writer, locale translation.Locale, allowed ...rune) (escaped *EscapeStatus, err error) {
|
|
||||||
bufRd := bufio.NewReader(reader)
|
|
||||||
outputStream := &HTMLStreamerWriter{Writer: writer}
|
|
||||||
streamer := NewEscapeStreamer(locale, outputStream, allowed...).(*escapeStreamer)
|
|
||||||
|
|
||||||
for {
|
|
||||||
line, rdErr := bufRd.ReadString('\n')
|
|
||||||
if len(line) > 0 {
|
|
||||||
if err := streamer.Text(line); err != nil {
|
|
||||||
streamer.escaped.HasError = true
|
|
||||||
log.Error("Error whilst escaping: %v", err)
|
|
||||||
return streamer.escaped, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if rdErr != nil {
|
|
||||||
if rdErr != io.EOF {
|
|
||||||
err = rdErr
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return streamer.escaped, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// EscapeControlString escapes the unicode control sequences in a provided string and returns the findings as an EscapeStatus and the escaped string
|
|
||||||
func EscapeControlString(text string, locale translation.Locale, allowed ...rune) (escaped *EscapeStatus, output string) {
|
|
||||||
sb := &strings.Builder{}
|
|
||||||
outputStream := &HTMLStreamerWriter{Writer: sb}
|
|
||||||
streamer := NewEscapeStreamer(locale, outputStream, allowed...).(*escapeStreamer)
|
|
||||||
|
|
||||||
if err := streamer.Text(text); err != nil {
|
|
||||||
streamer.escaped.HasError = true
|
|
||||||
log.Error("Error whilst escaping: %v", err)
|
|
||||||
}
|
|
||||||
return streamer.escaped, sb.String()
|
|
||||||
}
|
|
||||||
|
@ -64,7 +64,7 @@ func (e *escapeStreamer) Text(data string) error {
|
|||||||
until, next = nextIdxs[0]+pos, nextIdxs[1]+pos
|
until, next = nextIdxs[0]+pos, nextIdxs[1]+pos
|
||||||
}
|
}
|
||||||
|
|
||||||
// from pos until until we know that the runes are not \r\t\n or even ' '
|
// from pos until we know that the runes are not \r\t\n or even ' '
|
||||||
runes := make([]rune, 0, next-until)
|
runes := make([]rune, 0, next-until)
|
||||||
positions := make([]int, 0, next-until+1)
|
positions := make([]int, 0, next-until+1)
|
||||||
|
|
||||||
|
@ -4,11 +4,14 @@
|
|||||||
package charset
|
package charset
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"reflect"
|
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
"code.gitea.io/gitea/modules/test"
|
||||||
"code.gitea.io/gitea/modules/translation"
|
"code.gitea.io/gitea/modules/translation"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
type escapeControlTest struct {
|
type escapeControlTest struct {
|
||||||
@ -132,22 +135,8 @@ then resh (ר), and finally heh (ה) (which should appear leftmost).`,
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEscapeControlString(t *testing.T) {
|
|
||||||
for _, tt := range escapeControlTests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
status, result := EscapeControlString(tt.text, &translation.MockLocale{})
|
|
||||||
if !reflect.DeepEqual(*status, tt.status) {
|
|
||||||
t.Errorf("EscapeControlString() status = %v, wanted= %v", status, tt.status)
|
|
||||||
}
|
|
||||||
if result != tt.result {
|
|
||||||
t.Errorf("EscapeControlString()\nresult= %v,\nwanted= %v", result, tt.result)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEscapeControlReader(t *testing.T) {
|
func TestEscapeControlReader(t *testing.T) {
|
||||||
// lets add some control characters to the tests
|
// add some control characters to the tests
|
||||||
tests := make([]escapeControlTest, 0, len(escapeControlTests)*3)
|
tests := make([]escapeControlTest, 0, len(escapeControlTests)*3)
|
||||||
copy(tests, escapeControlTests)
|
copy(tests, escapeControlTests)
|
||||||
|
|
||||||
@ -169,29 +158,20 @@ func TestEscapeControlReader(t *testing.T) {
|
|||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
input := strings.NewReader(tt.text)
|
|
||||||
output := &strings.Builder{}
|
output := &strings.Builder{}
|
||||||
status, err := EscapeControlReader(input, output, &translation.MockLocale{})
|
status, err := EscapeControlReader(strings.NewReader(tt.text), output, &translation.MockLocale{})
|
||||||
result := output.String()
|
assert.NoError(t, err)
|
||||||
if err != nil {
|
assert.Equal(t, tt.status, *status)
|
||||||
t.Errorf("EscapeControlReader(): err = %v", err)
|
assert.Equal(t, tt.result, output.String())
|
||||||
}
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(*status, tt.status) {
|
|
||||||
t.Errorf("EscapeControlReader() status = %v, wanted= %v", status, tt.status)
|
|
||||||
}
|
|
||||||
if result != tt.result {
|
|
||||||
t.Errorf("EscapeControlReader()\nresult= %v,\nwanted= %v", result, tt.result)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEscapeControlReader_panic(t *testing.T) {
|
func TestSettingAmbiguousUnicodeDetection(t *testing.T) {
|
||||||
bs := make([]byte, 0, 20479)
|
defer test.MockVariableValue(&setting.UI.AmbiguousUnicodeDetection, true)()
|
||||||
bs = append(bs, 'A')
|
_, out := EscapeControlHTML("a test", &translation.MockLocale{})
|
||||||
for i := 0; i < 6826; i++ {
|
assert.EqualValues(t, `a<span class="escaped-code-point" data-escaped="[U+00A0]"><span class="char"> </span></span>test`, out)
|
||||||
bs = append(bs, []byte("—")...)
|
setting.UI.AmbiguousUnicodeDetection = false
|
||||||
}
|
_, out = EscapeControlHTML("a test", &translation.MockLocale{})
|
||||||
_, _ = EscapeControlString(string(bs), &translation.MockLocale{})
|
assert.EqualValues(t, `a test`, out)
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,7 @@ func TestReadingBlameOutput(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, bypass := range []bool{false, true} {
|
for _, bypass := range []bool{false, true} {
|
||||||
blameReader, err := CreateBlameReader(ctx, &Sha1ObjectFormat{}, "./tests/repos/repo5_pulls", commit, "README.md", bypass)
|
blameReader, err := CreateBlameReader(ctx, Sha1ObjectFormat, "./tests/repos/repo5_pulls", commit, "README.md", bypass)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.NotNil(t, blameReader)
|
assert.NotNil(t, blameReader)
|
||||||
defer blameReader.Close()
|
defer blameReader.Close()
|
||||||
|
@ -14,7 +14,6 @@ import (
|
|||||||
"os/exec"
|
"os/exec"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
"unsafe"
|
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/git/internal" //nolint:depguard // only this file can use the internal type CmdArg, other files and packages should use AddXxx functions
|
"code.gitea.io/gitea/modules/git/internal" //nolint:depguard // only this file can use the internal type CmdArg, other files and packages should use AddXxx functions
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
@ -389,15 +388,11 @@ func (r *runStdError) IsExitCode(code int) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func bytesToString(b []byte) string {
|
|
||||||
return *(*string)(unsafe.Pointer(&b)) // that's what Golang's strings.Builder.String() does (go/src/strings/builder.go)
|
|
||||||
}
|
|
||||||
|
|
||||||
// RunStdString runs the command with options and returns stdout/stderr as string. and store stderr to returned error (err combined with stderr).
|
// RunStdString runs the command with options and returns stdout/stderr as string. and store stderr to returned error (err combined with stderr).
|
||||||
func (c *Command) RunStdString(opts *RunOpts) (stdout, stderr string, runErr RunStdError) {
|
func (c *Command) RunStdString(opts *RunOpts) (stdout, stderr string, runErr RunStdError) {
|
||||||
stdoutBytes, stderrBytes, err := c.RunStdBytes(opts)
|
stdoutBytes, stderrBytes, err := c.RunStdBytes(opts)
|
||||||
stdout = bytesToString(stdoutBytes)
|
stdout = util.UnsafeBytesToString(stdoutBytes)
|
||||||
stderr = bytesToString(stderrBytes)
|
stderr = util.UnsafeBytesToString(stderrBytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return stdout, stderr, &runStdError{err: err, stderr: stderr}
|
return stdout, stderr, &runStdError{err: err, stderr: stderr}
|
||||||
}
|
}
|
||||||
@ -432,7 +427,7 @@ func (c *Command) RunStdBytes(opts *RunOpts) (stdout, stderr []byte, runErr RunS
|
|||||||
err := c.Run(newOpts)
|
err := c.Run(newOpts)
|
||||||
stderr = stderrBuf.Bytes()
|
stderr = stderrBuf.Bytes()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, stderr, &runStdError{err: err, stderr: bytesToString(stderr)}
|
return nil, stderr, &runStdError{err: err, stderr: util.UnsafeBytesToString(stderr)}
|
||||||
}
|
}
|
||||||
// even if there is no err, there could still be some stderr output
|
// even if there is no err, there could still be some stderr output
|
||||||
return stdoutBuf.Bytes(), stderr, nil
|
return stdoutBuf.Bytes(), stderr, nil
|
||||||
|
@ -236,7 +236,7 @@ func (c *Commit) IsForcePush(oldCommitID string) (bool, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
if oldCommitID == objectFormat.Empty().String() {
|
if oldCommitID == objectFormat.EmptyObjectID().String() {
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,26 +5,17 @@ package git
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/sha1"
|
"crypto/sha1"
|
||||||
"fmt"
|
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
type ObjectFormatID int
|
|
||||||
|
|
||||||
const (
|
|
||||||
Sha1 ObjectFormatID = iota
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// sha1Pattern can be used to determine if a string is an valid sha
|
// sha1Pattern can be used to determine if a string is an valid sha
|
||||||
var sha1Pattern = regexp.MustCompile(`^[0-9a-f]{4,40}$`)
|
var sha1Pattern = regexp.MustCompile(`^[0-9a-f]{4,40}$`)
|
||||||
|
|
||||||
type ObjectFormat interface {
|
type ObjectFormat interface {
|
||||||
ID() ObjectFormatID
|
// Name returns the name of the object format
|
||||||
String() string
|
Name() string
|
||||||
|
// EmptyObjectID creates a new empty ObjectID from an object format hash name
|
||||||
// Empty is the hash of empty git
|
EmptyObjectID() ObjectID
|
||||||
Empty() ObjectID
|
|
||||||
// EmptyTree is the hash of an empty tree
|
// EmptyTree is the hash of an empty tree
|
||||||
EmptyTree() ObjectID
|
EmptyTree() ObjectID
|
||||||
// FullLength is the length of the hash's hex string
|
// FullLength is the length of the hash's hex string
|
||||||
@ -35,67 +26,71 @@ type ObjectFormat interface {
|
|||||||
MustIDFromString(s string) ObjectID
|
MustIDFromString(s string) ObjectID
|
||||||
NewID(b []byte) (ObjectID, error)
|
NewID(b []byte) (ObjectID, error)
|
||||||
NewIDFromString(s string) (ObjectID, error)
|
NewIDFromString(s string) (ObjectID, error)
|
||||||
NewEmptyID() ObjectID
|
|
||||||
|
|
||||||
NewHasher() HasherInterface
|
NewHasher() HasherInterface
|
||||||
}
|
}
|
||||||
|
|
||||||
type Sha1ObjectFormat struct{}
|
type Sha1ObjectFormatImpl struct{}
|
||||||
|
|
||||||
func (*Sha1ObjectFormat) ID() ObjectFormatID { return Sha1 }
|
var (
|
||||||
func (*Sha1ObjectFormat) String() string { return "sha1" }
|
emptyObjectID = &Sha1Hash{}
|
||||||
func (*Sha1ObjectFormat) Empty() ObjectID { return &Sha1Hash{} }
|
emptyTree = &Sha1Hash{
|
||||||
func (*Sha1ObjectFormat) EmptyTree() ObjectID {
|
|
||||||
return &Sha1Hash{
|
|
||||||
0x4b, 0x82, 0x5d, 0xc6, 0x42, 0xcb, 0x6e, 0xb9, 0xa0, 0x60,
|
0x4b, 0x82, 0x5d, 0xc6, 0x42, 0xcb, 0x6e, 0xb9, 0xa0, 0x60,
|
||||||
0xe5, 0x4b, 0xf8, 0xd6, 0x92, 0x88, 0xfb, 0xee, 0x49, 0x04,
|
0xe5, 0x4b, 0xf8, 0xd6, 0x92, 0x88, 0xfb, 0xee, 0x49, 0x04,
|
||||||
}
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func (Sha1ObjectFormatImpl) Name() string { return "sha1" }
|
||||||
|
func (Sha1ObjectFormatImpl) EmptyObjectID() ObjectID {
|
||||||
|
return emptyObjectID
|
||||||
}
|
}
|
||||||
func (*Sha1ObjectFormat) FullLength() int { return 40 }
|
|
||||||
func (*Sha1ObjectFormat) IsValid(input string) bool {
|
func (Sha1ObjectFormatImpl) EmptyTree() ObjectID {
|
||||||
|
return emptyTree
|
||||||
|
}
|
||||||
|
func (Sha1ObjectFormatImpl) FullLength() int { return 40 }
|
||||||
|
func (Sha1ObjectFormatImpl) IsValid(input string) bool {
|
||||||
return sha1Pattern.MatchString(input)
|
return sha1Pattern.MatchString(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*Sha1ObjectFormat) MustID(b []byte) ObjectID {
|
func (Sha1ObjectFormatImpl) MustID(b []byte) ObjectID {
|
||||||
var id Sha1Hash
|
var id Sha1Hash
|
||||||
copy(id[0:20], b)
|
copy(id[0:20], b)
|
||||||
return &id
|
return &id
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Sha1ObjectFormat) MustIDFromString(s string) ObjectID {
|
func (h Sha1ObjectFormatImpl) MustIDFromString(s string) ObjectID {
|
||||||
return MustIDFromString(h, s)
|
return MustIDFromString(h, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Sha1ObjectFormat) NewID(b []byte) (ObjectID, error) {
|
func (h Sha1ObjectFormatImpl) NewID(b []byte) (ObjectID, error) {
|
||||||
return IDFromRaw(h, b)
|
return IDFromRaw(h, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Sha1ObjectFormat) NewIDFromString(s string) (ObjectID, error) {
|
func (h Sha1ObjectFormatImpl) NewIDFromString(s string) (ObjectID, error) {
|
||||||
return genericIDFromString(h, s)
|
return genericIDFromString(h, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*Sha1ObjectFormat) NewEmptyID() ObjectID {
|
func (h Sha1ObjectFormatImpl) NewHasher() HasherInterface {
|
||||||
return NewSha1()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *Sha1ObjectFormat) NewHasher() HasherInterface {
|
|
||||||
return &Sha1Hasher{sha1.New()}
|
return &Sha1Hasher{sha1.New()}
|
||||||
}
|
}
|
||||||
|
|
||||||
func ObjectFormatFromID(id ObjectFormatID) ObjectFormat {
|
var Sha1ObjectFormat ObjectFormat = Sha1ObjectFormatImpl{}
|
||||||
switch id {
|
|
||||||
case Sha1:
|
|
||||||
return &Sha1ObjectFormat{}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
var SupportedObjectFormats = []ObjectFormat{
|
||||||
|
Sha1ObjectFormat,
|
||||||
|
// TODO: add sha256
|
||||||
|
}
|
||||||
|
|
||||||
|
func ObjectFormatFromName(name string) ObjectFormat {
|
||||||
|
for _, objectFormat := range SupportedObjectFormats {
|
||||||
|
if name == objectFormat.Name() {
|
||||||
|
return objectFormat
|
||||||
|
}
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ObjectFormatFromString(hash string) (ObjectFormat, error) {
|
func IsValidObjectFormat(name string) bool {
|
||||||
switch strings.ToLower(hash) {
|
return ObjectFormatFromName(name) != nil
|
||||||
case "sha1":
|
|
||||||
return &Sha1ObjectFormat{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, fmt.Errorf("unknown hash type: %s", hash)
|
|
||||||
}
|
}
|
||||||
|
@ -31,18 +31,15 @@ func (h *Sha1Hash) IsZero() bool {
|
|||||||
return bytes.Equal(empty[:], h[:])
|
return bytes.Equal(empty[:], h[:])
|
||||||
}
|
}
|
||||||
func (h *Sha1Hash) RawValue() []byte { return h[:] }
|
func (h *Sha1Hash) RawValue() []byte { return h[:] }
|
||||||
func (*Sha1Hash) Type() ObjectFormat { return &Sha1ObjectFormat{} }
|
func (*Sha1Hash) Type() ObjectFormat { return Sha1ObjectFormat }
|
||||||
|
|
||||||
func NewSha1() *Sha1Hash {
|
var _ ObjectID = &Sha1Hash{}
|
||||||
return &Sha1Hash{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewHash is for generic implementations
|
// EmptyObjectID creates a new ObjectID from an object format hash name
|
||||||
func NewHash(hash string) (ObjectID, error) {
|
func EmptyObjectID(objectFormatName string) (ObjectID, error) {
|
||||||
hash = strings.ToLower(hash)
|
objectFormat := ObjectFormatFromName(objectFormatName)
|
||||||
switch hash {
|
if objectFormat != nil {
|
||||||
case "sha1":
|
return objectFormat.EmptyObjectID(), nil
|
||||||
return &Sha1Hash{}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, errors.New("unsupported hash type")
|
return nil, errors.New("unsupported hash type")
|
||||||
@ -50,7 +47,7 @@ func NewHash(hash string) (ObjectID, error) {
|
|||||||
|
|
||||||
func IDFromRaw(h ObjectFormat, b []byte) (ObjectID, error) {
|
func IDFromRaw(h ObjectFormat, b []byte) (ObjectID, error) {
|
||||||
if len(b) != h.FullLength()/2 {
|
if len(b) != h.FullLength()/2 {
|
||||||
return h.Empty(), fmt.Errorf("length must be %d: %v", h.FullLength(), b)
|
return h.EmptyObjectID(), fmt.Errorf("length must be %d: %v", h.FullLength(), b)
|
||||||
}
|
}
|
||||||
return h.MustID(b), nil
|
return h.MustID(b), nil
|
||||||
}
|
}
|
||||||
@ -63,24 +60,20 @@ func MustIDFromString(h ObjectFormat, s string) ObjectID {
|
|||||||
func genericIDFromString(h ObjectFormat, s string) (ObjectID, error) {
|
func genericIDFromString(h ObjectFormat, s string) (ObjectID, error) {
|
||||||
s = strings.TrimSpace(s)
|
s = strings.TrimSpace(s)
|
||||||
if len(s) != h.FullLength() {
|
if len(s) != h.FullLength() {
|
||||||
return h.Empty(), fmt.Errorf("length must be %d: %s", h.FullLength(), s)
|
return h.EmptyObjectID(), fmt.Errorf("length must be %d: %s", h.FullLength(), s)
|
||||||
}
|
}
|
||||||
b, err := hex.DecodeString(s)
|
b, err := hex.DecodeString(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return h.Empty(), err
|
return h.EmptyObjectID(), err
|
||||||
}
|
}
|
||||||
return h.NewID(b)
|
return h.NewID(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
func IDFromString(hexHash string) (ObjectID, error) {
|
func IDFromString(hexHash string) (ObjectID, error) {
|
||||||
switch len(hexHash) {
|
for _, objectFormat := range SupportedObjectFormats {
|
||||||
case 40:
|
if len(hexHash) == objectFormat.FullLength() {
|
||||||
hashType := Sha1ObjectFormat{}
|
return objectFormat.NewIDFromString(hexHash)
|
||||||
h, err := hashType.NewIDFromString(hexHash)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
return h, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, fmt.Errorf("invalid hash hex string: '%s' len: %d", hexHash, len(hexHash))
|
return nil, fmt.Errorf("invalid hash hex string: '%s' len: %d", hexHash, len(hexHash))
|
||||||
|
@ -12,7 +12,7 @@ import (
|
|||||||
func ParseGogitHash(h plumbing.Hash) ObjectID {
|
func ParseGogitHash(h plumbing.Hash) ObjectID {
|
||||||
switch hash.Size {
|
switch hash.Size {
|
||||||
case 20:
|
case 20:
|
||||||
return ObjectFormatFromID(Sha1).MustID(h[:])
|
return Sha1ObjectFormat.MustID(h[:])
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -10,7 +10,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestIsValidSHAPattern(t *testing.T) {
|
func TestIsValidSHAPattern(t *testing.T) {
|
||||||
h := NewSha1().Type()
|
h := Sha1ObjectFormat
|
||||||
assert.True(t, h.IsValid("fee1"))
|
assert.True(t, h.IsValid("fee1"))
|
||||||
assert.True(t, h.IsValid("abc000"))
|
assert.True(t, h.IsValid("abc000"))
|
||||||
assert.True(t, h.IsValid("9023902390239023902390239023902390239023"))
|
assert.True(t, h.IsValid("9023902390239023902390239023902390239023"))
|
||||||
|
@ -28,9 +28,9 @@ func TestParseTreeEntries(t *testing.T) {
|
|||||||
Input: "100644 blob 61ab7345a1a3bbc590068ccae37b8515cfc5843c 1022\texample/file2.txt\n",
|
Input: "100644 blob 61ab7345a1a3bbc590068ccae37b8515cfc5843c 1022\texample/file2.txt\n",
|
||||||
Expected: []*TreeEntry{
|
Expected: []*TreeEntry{
|
||||||
{
|
{
|
||||||
ID: ObjectFormatFromID(Sha1).MustIDFromString("61ab7345a1a3bbc590068ccae37b8515cfc5843c"),
|
ID: Sha1ObjectFormat.MustIDFromString("61ab7345a1a3bbc590068ccae37b8515cfc5843c"),
|
||||||
gogitTreeEntry: &object.TreeEntry{
|
gogitTreeEntry: &object.TreeEntry{
|
||||||
Hash: plumbing.Hash(ObjectFormatFromID(Sha1).MustIDFromString("61ab7345a1a3bbc590068ccae37b8515cfc5843c").RawValue()),
|
Hash: plumbing.Hash(Sha1ObjectFormat.MustIDFromString("61ab7345a1a3bbc590068ccae37b8515cfc5843c").RawValue()),
|
||||||
Name: "example/file2.txt",
|
Name: "example/file2.txt",
|
||||||
Mode: filemode.Regular,
|
Mode: filemode.Regular,
|
||||||
},
|
},
|
||||||
@ -44,9 +44,9 @@ func TestParseTreeEntries(t *testing.T) {
|
|||||||
"040000 tree 1d01fb729fb0db5881daaa6030f9f2d3cd3d5ae8 -\texample\n",
|
"040000 tree 1d01fb729fb0db5881daaa6030f9f2d3cd3d5ae8 -\texample\n",
|
||||||
Expected: []*TreeEntry{
|
Expected: []*TreeEntry{
|
||||||
{
|
{
|
||||||
ID: ObjectFormatFromID(Sha1).MustIDFromString("61ab7345a1a3bbc590068ccae37b8515cfc5843c"),
|
ID: Sha1ObjectFormat.MustIDFromString("61ab7345a1a3bbc590068ccae37b8515cfc5843c"),
|
||||||
gogitTreeEntry: &object.TreeEntry{
|
gogitTreeEntry: &object.TreeEntry{
|
||||||
Hash: plumbing.Hash(ObjectFormatFromID(Sha1).MustIDFromString("61ab7345a1a3bbc590068ccae37b8515cfc5843c").RawValue()),
|
Hash: plumbing.Hash(Sha1ObjectFormat.MustIDFromString("61ab7345a1a3bbc590068ccae37b8515cfc5843c").RawValue()),
|
||||||
Name: "example/\n.txt",
|
Name: "example/\n.txt",
|
||||||
Mode: filemode.Symlink,
|
Mode: filemode.Symlink,
|
||||||
},
|
},
|
||||||
@ -54,10 +54,10 @@ func TestParseTreeEntries(t *testing.T) {
|
|||||||
sized: true,
|
sized: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ID: ObjectFormatFromID(Sha1).MustIDFromString("1d01fb729fb0db5881daaa6030f9f2d3cd3d5ae8"),
|
ID: Sha1ObjectFormat.MustIDFromString("1d01fb729fb0db5881daaa6030f9f2d3cd3d5ae8"),
|
||||||
sized: true,
|
sized: true,
|
||||||
gogitTreeEntry: &object.TreeEntry{
|
gogitTreeEntry: &object.TreeEntry{
|
||||||
Hash: plumbing.Hash(ObjectFormatFromID(Sha1).MustIDFromString("1d01fb729fb0db5881daaa6030f9f2d3cd3d5ae8").RawValue()),
|
Hash: plumbing.Hash(Sha1ObjectFormat.MustIDFromString("1d01fb729fb0db5881daaa6030f9f2d3cd3d5ae8").RawValue()),
|
||||||
Name: "example",
|
Name: "example",
|
||||||
Mode: filemode.Dir,
|
Mode: filemode.Dir,
|
||||||
},
|
},
|
||||||
@ -67,7 +67,7 @@ func TestParseTreeEntries(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, testCase := range testCases {
|
for _, testCase := range testCases {
|
||||||
entries, err := ParseTreeEntries(ObjectFormatFromID(Sha1), []byte(testCase.Input))
|
entries, err := ParseTreeEntries(Sha1ObjectFormat, []byte(testCase.Input))
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
if len(entries) > 1 {
|
if len(entries) > 1 {
|
||||||
fmt.Println(testCase.Expected[0].ID)
|
fmt.Println(testCase.Expected[0].ID)
|
||||||
|
@ -12,7 +12,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestParseTreeEntriesLong(t *testing.T) {
|
func TestParseTreeEntriesLong(t *testing.T) {
|
||||||
objectFormat := ObjectFormatFromID(Sha1)
|
objectFormat := Sha1ObjectFormat
|
||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
Input string
|
Input string
|
||||||
@ -66,7 +66,7 @@ func TestParseTreeEntriesLong(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestParseTreeEntriesShort(t *testing.T) {
|
func TestParseTreeEntriesShort(t *testing.T) {
|
||||||
objectFormat := ObjectFormatFromID(Sha1)
|
objectFormat := Sha1ObjectFormat
|
||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
Input string
|
Input string
|
||||||
@ -102,7 +102,7 @@ func TestParseTreeEntriesShort(t *testing.T) {
|
|||||||
|
|
||||||
func TestParseTreeEntriesInvalid(t *testing.T) {
|
func TestParseTreeEntriesInvalid(t *testing.T) {
|
||||||
// there was a panic: "runtime error: slice bounds out of range" when the input was invalid: #20315
|
// there was a panic: "runtime error: slice bounds out of range" when the input was invalid: #20315
|
||||||
entries, err := ParseTreeEntries(ObjectFormatFromID(Sha1), []byte("100644 blob ea0d83c9081af9500ac9f804101b3fd0a5c293af"))
|
entries, err := ParseTreeEntries(Sha1ObjectFormat, []byte("100644 blob ea0d83c9081af9500ac9f804101b3fd0a5c293af"))
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.Len(t, entries, 0)
|
assert.Len(t, entries, 0)
|
||||||
}
|
}
|
||||||
|
@ -205,7 +205,7 @@ func RefURL(repoURL, ref string) string {
|
|||||||
return repoURL + "/src/branch/" + refName
|
return repoURL + "/src/branch/" + refName
|
||||||
case refFullName.IsTag():
|
case refFullName.IsTag():
|
||||||
return repoURL + "/src/tag/" + refName
|
return repoURL + "/src/tag/" + refName
|
||||||
case !ObjectFormatFromID(Sha1).IsValid(ref):
|
case !Sha1ObjectFormat.IsValid(ref):
|
||||||
// assume they mean a branch
|
// assume they mean a branch
|
||||||
return repoURL + "/src/branch/" + refName
|
return repoURL + "/src/branch/" + refName
|
||||||
default:
|
default:
|
||||||
|
@ -90,7 +90,7 @@ func GetObjectFormatOfRepo(ctx context.Context, repoPath string) (ObjectFormat,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// InitRepository initializes a new Git repository.
|
// InitRepository initializes a new Git repository.
|
||||||
func InitRepository(ctx context.Context, repoPath string, bare bool, objectFormat ObjectFormat) error {
|
func InitRepository(ctx context.Context, repoPath string, bare bool, objectFormatName string) error {
|
||||||
err := os.MkdirAll(repoPath, os.ModePerm)
|
err := os.MkdirAll(repoPath, os.ModePerm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -98,7 +98,13 @@ func InitRepository(ctx context.Context, repoPath string, bare bool, objectForma
|
|||||||
|
|
||||||
cmd := NewCommand(ctx, "init")
|
cmd := NewCommand(ctx, "init")
|
||||||
if SupportHashSha256 {
|
if SupportHashSha256 {
|
||||||
cmd.AddOptionValues("--object-format", objectFormat.String())
|
if objectFormatName == "" {
|
||||||
|
objectFormatName = Sha1ObjectFormat.Name()
|
||||||
|
}
|
||||||
|
if !IsValidObjectFormat(objectFormatName) {
|
||||||
|
return fmt.Errorf("invalid object format: %s", objectFormatName)
|
||||||
|
}
|
||||||
|
cmd.AddOptionValues("--object-format", objectFormatName)
|
||||||
}
|
}
|
||||||
if bare {
|
if bare {
|
||||||
cmd.AddArguments("--bare")
|
cmd.AddArguments("--bare")
|
||||||
|
@ -54,9 +54,9 @@ func (repo *Repository) ConvertToGitID(commitID string) (ObjectID, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
if strings.Contains(err.Error(), "unknown revision or path") ||
|
if strings.Contains(err.Error(), "unknown revision or path") ||
|
||||||
strings.Contains(err.Error(), "fatal: Needed a single revision") {
|
strings.Contains(err.Error(), "fatal: Needed a single revision") {
|
||||||
return objectFormat.Empty(), ErrNotExist{commitID, ""}
|
return objectFormat.EmptyObjectID(), ErrNotExist{commitID, ""}
|
||||||
}
|
}
|
||||||
return objectFormat.Empty(), err
|
return objectFormat.EmptyObjectID(), err
|
||||||
}
|
}
|
||||||
|
|
||||||
return objectFormat.NewIDFromString(actualCommitID)
|
return objectFormat.NewIDFromString(actualCommitID)
|
||||||
|
@ -284,7 +284,7 @@ func (repo *Repository) GetPatch(base, head string, w io.Writer) error {
|
|||||||
// If base is the SHA of an empty tree (EmptyTreeSHA), it returns the files changes from the initial commit to the head commit
|
// If base is the SHA of an empty tree (EmptyTreeSHA), it returns the files changes from the initial commit to the head commit
|
||||||
func (repo *Repository) GetFilesChangedBetween(base, head string) ([]string, error) {
|
func (repo *Repository) GetFilesChangedBetween(base, head string) ([]string, error) {
|
||||||
cmd := NewCommand(repo.Ctx, "diff-tree", "--name-only", "--root", "--no-commit-id", "-r", "-z")
|
cmd := NewCommand(repo.Ctx, "diff-tree", "--name-only", "--root", "--no-commit-id", "-r", "-z")
|
||||||
if base == repo.objectFormat.Empty().String() {
|
if base == repo.objectFormat.EmptyObjectID().String() {
|
||||||
cmd.AddDynamicArguments(head)
|
cmd.AddDynamicArguments(head)
|
||||||
} else {
|
} else {
|
||||||
cmd.AddDynamicArguments(base, head)
|
cmd.AddDynamicArguments(base, head)
|
||||||
|
@ -131,12 +131,12 @@ func TestGetCommitFilesChanged(t *testing.T) {
|
|||||||
files []string
|
files []string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
repo.objectFormat.Empty().String(),
|
repo.objectFormat.EmptyObjectID().String(),
|
||||||
"95bb4d39648ee7e325106df01a621c530863a653",
|
"95bb4d39648ee7e325106df01a621c530863a653",
|
||||||
[]string{"file1.txt"},
|
[]string{"file1.txt"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
repo.objectFormat.Empty().String(),
|
repo.objectFormat.EmptyObjectID().String(),
|
||||||
"8d92fc957a4d7cfd98bc375f0b7bb189a0d6c9f2",
|
"8d92fc957a4d7cfd98bc375f0b7bb189a0d6c9f2",
|
||||||
[]string{"file2.txt"},
|
[]string{"file2.txt"},
|
||||||
},
|
},
|
||||||
|
@ -101,7 +101,7 @@ func (repo *Repository) RemoveFilesFromIndex(filenames ...string) error {
|
|||||||
for _, file := range filenames {
|
for _, file := range filenames {
|
||||||
if file != "" {
|
if file != "" {
|
||||||
buffer.WriteString("0 ")
|
buffer.WriteString("0 ")
|
||||||
buffer.WriteString(repo.objectFormat.Empty().String())
|
buffer.WriteString(repo.objectFormat.EmptyObjectID().String())
|
||||||
buffer.WriteByte('\t')
|
buffer.WriteByte('\t')
|
||||||
buffer.WriteString(file)
|
buffer.WriteString(file)
|
||||||
buffer.WriteByte('\000')
|
buffer.WriteByte('\000')
|
||||||
|
@ -194,7 +194,7 @@ func TestRepository_GetAnnotatedTag(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestRepository_parseTagRef(t *testing.T) {
|
func TestRepository_parseTagRef(t *testing.T) {
|
||||||
sha1 := ObjectFormatFromID(Sha1)
|
sha1 := Sha1ObjectFormat
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
|
|
||||||
|
@ -35,8 +35,8 @@ func (tag *Tag) Commit(gitRepo *Repository) (*Commit, error) {
|
|||||||
// \n\n separate headers from message
|
// \n\n separate headers from message
|
||||||
func parseTagData(objectFormat ObjectFormat, data []byte) (*Tag, error) {
|
func parseTagData(objectFormat ObjectFormat, data []byte) (*Tag, error) {
|
||||||
tag := new(Tag)
|
tag := new(Tag)
|
||||||
tag.ID = objectFormat.NewEmptyID()
|
tag.ID = objectFormat.EmptyObjectID()
|
||||||
tag.Object = objectFormat.NewEmptyID()
|
tag.Object = objectFormat.EmptyObjectID()
|
||||||
tag.Tagger = &Signature{}
|
tag.Tagger = &Signature{}
|
||||||
// we now have the contents of the commit object. Let's investigate...
|
// we now have the contents of the commit object. Let's investigate...
|
||||||
nextline := 0
|
nextline := 0
|
||||||
|
@ -22,7 +22,7 @@ tagger Lucas Michot <lucas@semalead.com> 1484491741 +0100
|
|||||||
|
|
||||||
`), tag: Tag{
|
`), tag: Tag{
|
||||||
Name: "",
|
Name: "",
|
||||||
ID: NewSha1(),
|
ID: Sha1ObjectFormat.EmptyObjectID(),
|
||||||
Object: &Sha1Hash{0x3b, 0x11, 0x4a, 0xb8, 0x0, 0xc6, 0x43, 0x2a, 0xd4, 0x23, 0x87, 0xcc, 0xf6, 0xbc, 0x8d, 0x43, 0x88, 0xa2, 0x88, 0x5a},
|
Object: &Sha1Hash{0x3b, 0x11, 0x4a, 0xb8, 0x0, 0xc6, 0x43, 0x2a, 0xd4, 0x23, 0x87, 0xcc, 0xf6, 0xbc, 0x8d, 0x43, 0x88, 0xa2, 0x88, 0x5a},
|
||||||
Type: "commit",
|
Type: "commit",
|
||||||
Tagger: &Signature{Name: "Lucas Michot", Email: "lucas@semalead.com", When: time.Unix(1484491741, 0)},
|
Tagger: &Signature{Name: "Lucas Michot", Email: "lucas@semalead.com", When: time.Unix(1484491741, 0)},
|
||||||
@ -39,7 +39,7 @@ o
|
|||||||
|
|
||||||
ono`), tag: Tag{
|
ono`), tag: Tag{
|
||||||
Name: "",
|
Name: "",
|
||||||
ID: NewSha1(),
|
ID: Sha1ObjectFormat.EmptyObjectID(),
|
||||||
Object: &Sha1Hash{0x7c, 0xdf, 0x42, 0xc0, 0xb1, 0xcc, 0x76, 0x3a, 0xb7, 0xe4, 0xc3, 0x3c, 0x47, 0xa2, 0x4e, 0x27, 0xc6, 0x6b, 0xfc, 0xcc},
|
Object: &Sha1Hash{0x7c, 0xdf, 0x42, 0xc0, 0xb1, 0xcc, 0x76, 0x3a, 0xb7, 0xe4, 0xc3, 0x3c, 0x47, 0xa2, 0x4e, 0x27, 0xc6, 0x6b, 0xfc, 0xcc},
|
||||||
Type: "commit",
|
Type: "commit",
|
||||||
Tagger: &Signature{Name: "Lucas Michot", Email: "lucas@semalead.com", When: time.Unix(1484553735, 0)},
|
Tagger: &Signature{Name: "Lucas Michot", Email: "lucas@semalead.com", When: time.Unix(1484553735, 0)},
|
||||||
@ -49,7 +49,7 @@ ono`), tag: Tag{
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range testData {
|
for _, test := range testData {
|
||||||
tag, err := parseTagData(ObjectFormatFromID(Sha1), test.data)
|
tag, err := parseTagData(Sha1ObjectFormat, test.data)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.EqualValues(t, test.tag.ID, tag.ID)
|
assert.EqualValues(t, test.tag.ID, tag.ID)
|
||||||
assert.EqualValues(t, test.tag.Object, tag.Object)
|
assert.EqualValues(t, test.tag.Object, tag.Object)
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
gohtml "html"
|
gohtml "html"
|
||||||
|
"html/template"
|
||||||
"io"
|
"io"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
@ -55,7 +56,7 @@ func NewContext() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Code returns a HTML version of code string with chroma syntax highlighting classes and the matched lexer name
|
// Code returns a HTML version of code string with chroma syntax highlighting classes and the matched lexer name
|
||||||
func Code(fileName, language, code string) (string, string) {
|
func Code(fileName, language, code string) (output template.HTML, lexerName string) {
|
||||||
NewContext()
|
NewContext()
|
||||||
|
|
||||||
// diff view newline will be passed as empty, change to literal '\n' so it can be copied
|
// diff view newline will be passed as empty, change to literal '\n' so it can be copied
|
||||||
@ -65,7 +66,7 @@ func Code(fileName, language, code string) (string, string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(code) > sizeLimit {
|
if len(code) > sizeLimit {
|
||||||
return code, ""
|
return template.HTML(template.HTMLEscapeString(code)), ""
|
||||||
}
|
}
|
||||||
|
|
||||||
var lexer chroma.Lexer
|
var lexer chroma.Lexer
|
||||||
@ -102,13 +103,11 @@ func Code(fileName, language, code string) (string, string) {
|
|||||||
cache.Add(fileName, lexer)
|
cache.Add(fileName, lexer)
|
||||||
}
|
}
|
||||||
|
|
||||||
lexerName := formatLexerName(lexer.Config().Name)
|
return CodeFromLexer(lexer, code), formatLexerName(lexer.Config().Name)
|
||||||
|
|
||||||
return CodeFromLexer(lexer, code), lexerName
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CodeFromLexer returns a HTML version of code string with chroma syntax highlighting classes
|
// CodeFromLexer returns a HTML version of code string with chroma syntax highlighting classes
|
||||||
func CodeFromLexer(lexer chroma.Lexer, code string) string {
|
func CodeFromLexer(lexer chroma.Lexer, code string) template.HTML {
|
||||||
formatter := html.New(html.WithClasses(true),
|
formatter := html.New(html.WithClasses(true),
|
||||||
html.WithLineNumbers(false),
|
html.WithLineNumbers(false),
|
||||||
html.PreventSurroundingPre(true),
|
html.PreventSurroundingPre(true),
|
||||||
@ -120,23 +119,23 @@ func CodeFromLexer(lexer chroma.Lexer, code string) string {
|
|||||||
iterator, err := lexer.Tokenise(nil, code)
|
iterator, err := lexer.Tokenise(nil, code)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Can't tokenize code: %v", err)
|
log.Error("Can't tokenize code: %v", err)
|
||||||
return code
|
return template.HTML(template.HTMLEscapeString(code))
|
||||||
}
|
}
|
||||||
// style not used for live site but need to pass something
|
// style not used for live site but need to pass something
|
||||||
err = formatter.Format(htmlw, githubStyles, iterator)
|
err = formatter.Format(htmlw, githubStyles, iterator)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Can't format code: %v", err)
|
log.Error("Can't format code: %v", err)
|
||||||
return code
|
return template.HTML(template.HTMLEscapeString(code))
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = htmlw.Flush()
|
_ = htmlw.Flush()
|
||||||
// Chroma will add newlines for certain lexers in order to highlight them properly
|
// Chroma will add newlines for certain lexers in order to highlight them properly
|
||||||
// Once highlighted, strip them here, so they don't cause copy/paste trouble in HTML output
|
// Once highlighted, strip them here, so they don't cause copy/paste trouble in HTML output
|
||||||
return strings.TrimSuffix(htmlbuf.String(), "\n")
|
return template.HTML(strings.TrimSuffix(htmlbuf.String(), "\n"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// File returns a slice of chroma syntax highlighted HTML lines of code and the matched lexer name
|
// File returns a slice of chroma syntax highlighted HTML lines of code and the matched lexer name
|
||||||
func File(fileName, language string, code []byte) ([]string, string, error) {
|
func File(fileName, language string, code []byte) ([]template.HTML, string, error) {
|
||||||
NewContext()
|
NewContext()
|
||||||
|
|
||||||
if len(code) > sizeLimit {
|
if len(code) > sizeLimit {
|
||||||
@ -183,14 +182,14 @@ func File(fileName, language string, code []byte) ([]string, string, error) {
|
|||||||
tokensLines := chroma.SplitTokensIntoLines(iterator.Tokens())
|
tokensLines := chroma.SplitTokensIntoLines(iterator.Tokens())
|
||||||
htmlBuf := &bytes.Buffer{}
|
htmlBuf := &bytes.Buffer{}
|
||||||
|
|
||||||
lines := make([]string, 0, len(tokensLines))
|
lines := make([]template.HTML, 0, len(tokensLines))
|
||||||
for _, tokens := range tokensLines {
|
for _, tokens := range tokensLines {
|
||||||
iterator = chroma.Literator(tokens...)
|
iterator = chroma.Literator(tokens...)
|
||||||
err = formatter.Format(htmlBuf, githubStyles, iterator)
|
err = formatter.Format(htmlBuf, githubStyles, iterator)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, "", fmt.Errorf("can't format code: %w", err)
|
return nil, "", fmt.Errorf("can't format code: %w", err)
|
||||||
}
|
}
|
||||||
lines = append(lines, htmlBuf.String())
|
lines = append(lines, template.HTML(htmlBuf.String()))
|
||||||
htmlBuf.Reset()
|
htmlBuf.Reset()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,9 +197,9 @@ func File(fileName, language string, code []byte) ([]string, string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// PlainText returns non-highlighted HTML for code
|
// PlainText returns non-highlighted HTML for code
|
||||||
func PlainText(code []byte) []string {
|
func PlainText(code []byte) []template.HTML {
|
||||||
r := bufio.NewReader(bytes.NewReader(code))
|
r := bufio.NewReader(bytes.NewReader(code))
|
||||||
m := make([]string, 0, bytes.Count(code, []byte{'\n'})+1)
|
m := make([]template.HTML, 0, bytes.Count(code, []byte{'\n'})+1)
|
||||||
for {
|
for {
|
||||||
content, err := r.ReadString('\n')
|
content, err := r.ReadString('\n')
|
||||||
if err != nil && err != io.EOF {
|
if err != nil && err != io.EOF {
|
||||||
@ -210,7 +209,7 @@ func PlainText(code []byte) []string {
|
|||||||
if content == "" && err == io.EOF {
|
if content == "" && err == io.EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
s := gohtml.EscapeString(content)
|
s := template.HTML(gohtml.EscapeString(content))
|
||||||
m = append(m, s)
|
m = append(m, s)
|
||||||
}
|
}
|
||||||
return m
|
return m
|
||||||
|
@ -4,21 +4,36 @@
|
|||||||
package highlight
|
package highlight
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"html/template"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func lines(s string) []string {
|
func lines(s string) (out []template.HTML) {
|
||||||
return strings.Split(strings.ReplaceAll(strings.TrimSpace(s), `\n`, "\n"), "\n")
|
// "" => [], "a" => ["a"], "a\n" => ["a\n"], "a\nb" => ["a\n", "b"] (each line always includes EOL "\n" if it exists)
|
||||||
|
out = make([]template.HTML, 0)
|
||||||
|
s = strings.ReplaceAll(strings.ReplaceAll(strings.TrimSpace(s), "\n", ""), `\n`, "\n")
|
||||||
|
for {
|
||||||
|
if p := strings.IndexByte(s, '\n'); p != -1 {
|
||||||
|
out = append(out, template.HTML(s[:p+1]))
|
||||||
|
s = s[p+1:]
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if s != "" {
|
||||||
|
out = append(out, template.HTML(s))
|
||||||
|
}
|
||||||
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFile(t *testing.T) {
|
func TestFile(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
code string
|
code string
|
||||||
want []string
|
want []template.HTML
|
||||||
lexerName string
|
lexerName string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
@ -99,10 +114,7 @@ c=2
|
|||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
out, lexerName, err := File(tt.name, "", []byte(tt.code))
|
out, lexerName, err := File(tt.name, "", []byte(tt.code))
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
expected := strings.Join(tt.want, "\n")
|
assert.EqualValues(t, tt.want, out)
|
||||||
actual := strings.Join(out, "\n")
|
|
||||||
assert.Equal(t, strings.Count(actual, "<span"), strings.Count(actual, "</span>"))
|
|
||||||
assert.EqualValues(t, expected, actual)
|
|
||||||
assert.Equal(t, tt.lexerName, lexerName)
|
assert.Equal(t, tt.lexerName, lexerName)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -112,7 +124,7 @@ func TestPlainText(t *testing.T) {
|
|||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
code string
|
code string
|
||||||
want []string
|
want []template.HTML
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "empty.py",
|
name: "empty.py",
|
||||||
@ -165,9 +177,7 @@ c=2`),
|
|||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
out := PlainText([]byte(tt.code))
|
out := PlainText([]byte(tt.code))
|
||||||
expected := strings.Join(tt.want, "\n")
|
assert.EqualValues(t, tt.want, out)
|
||||||
actual := strings.Join(out, "\n")
|
|
||||||
assert.EqualValues(t, expected, actual)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ package code
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"html/template"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/highlight"
|
"code.gitea.io/gitea/modules/highlight"
|
||||||
@ -22,7 +23,7 @@ type Result struct {
|
|||||||
Language string
|
Language string
|
||||||
Color string
|
Color string
|
||||||
LineNumbers []int
|
LineNumbers []int
|
||||||
FormattedLines string
|
FormattedLines template.HTML
|
||||||
}
|
}
|
||||||
|
|
||||||
type SearchResultLanguages = internal.SearchResultLanguages
|
type SearchResultLanguages = internal.SearchResultLanguages
|
||||||
|
@ -87,7 +87,7 @@ func Render(ctx *markup.RenderContext, input io.Reader, output io.Writer) error
|
|||||||
}
|
}
|
||||||
lexer = chroma.Coalesce(lexer)
|
lexer = chroma.Coalesce(lexer)
|
||||||
|
|
||||||
if _, err := w.WriteString(highlight.CodeFromLexer(lexer, source)); err != nil {
|
if _, err := w.WriteString(string(highlight.CodeFromLexer(lexer, source))); err != nil {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -169,7 +169,7 @@ func TestListToPushCommits(t *testing.T) {
|
|||||||
When: now,
|
When: now,
|
||||||
}
|
}
|
||||||
|
|
||||||
hashType := git.ObjectFormatFromID(git.Sha1)
|
hashType := git.Sha1ObjectFormat
|
||||||
const hexString1 = "0123456789abcdef0123456789abcdef01234567"
|
const hexString1 = "0123456789abcdef0123456789abcdef01234567"
|
||||||
hash1, err := hashType.NewIDFromString(hexString1)
|
hash1, err := hashType.NewIDFromString(hexString1)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
@ -224,7 +224,7 @@ func generateRepoCommit(ctx context.Context, repo, templateRepo, generateRepo *r
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: fix the hash
|
// FIXME: fix the hash
|
||||||
if err := git.InitRepository(ctx, tmpDir, false, git.ObjectFormatFromID(git.Sha1)); err != nil {
|
if err := git.InitRepository(ctx, tmpDir, false, git.Sha1ObjectFormat.Name()); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -358,7 +358,7 @@ func GenerateRepository(ctx context.Context, doer, owner *user_model.User, templ
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FIXME - fix the hash
|
// FIXME - fix the hash
|
||||||
if err = CheckInitRepository(ctx, owner.Name, generateRepo.Name, git.ObjectFormatFromID(git.Sha1)); err != nil {
|
if err = CheckInitRepository(ctx, owner.Name, generateRepo.Name, git.Sha1ObjectFormat.Name()); err != nil {
|
||||||
return generateRepo, err
|
return generateRepo, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,7 +188,7 @@ func InitRepoCommit(ctx context.Context, tmpPath string, repo *repo_model.Reposi
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func CheckInitRepository(ctx context.Context, owner, name string, objectFormat git.ObjectFormat) (err error) {
|
func CheckInitRepository(ctx context.Context, owner, name, objectFormatName string) (err error) {
|
||||||
// Somehow the directory could exist.
|
// Somehow the directory could exist.
|
||||||
repoPath := repo_model.RepoPath(owner, name)
|
repoPath := repo_model.RepoPath(owner, name)
|
||||||
isExist, err := util.IsExist(repoPath)
|
isExist, err := util.IsExist(repoPath)
|
||||||
@ -204,7 +204,7 @@ func CheckInitRepository(ctx context.Context, owner, name string, objectFormat g
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Init git bare new repository.
|
// Init git bare new repository.
|
||||||
if err = git.InitRepository(ctx, repoPath, true, objectFormat); err != nil {
|
if err = git.InitRepository(ctx, repoPath, true, objectFormatName); err != nil {
|
||||||
return fmt.Errorf("git.InitRepository: %w", err)
|
return fmt.Errorf("git.InitRepository: %w", err)
|
||||||
} else if err = CreateDelegateHooks(repoPath); err != nil {
|
} else if err = CreateDelegateHooks(repoPath); err != nil {
|
||||||
return fmt.Errorf("createDelegateHooks: %w", err)
|
return fmt.Errorf("createDelegateHooks: %w", err)
|
||||||
|
@ -35,6 +35,8 @@ var UI = struct {
|
|||||||
OnlyShowRelevantRepos bool
|
OnlyShowRelevantRepos bool
|
||||||
ExploreDefaultSort string `ini:"EXPLORE_PAGING_DEFAULT_SORT"`
|
ExploreDefaultSort string `ini:"EXPLORE_PAGING_DEFAULT_SORT"`
|
||||||
|
|
||||||
|
AmbiguousUnicodeDetection bool
|
||||||
|
|
||||||
Notification struct {
|
Notification struct {
|
||||||
MinTimeout time.Duration
|
MinTimeout time.Duration
|
||||||
TimeoutStep time.Duration
|
TimeoutStep time.Duration
|
||||||
@ -82,6 +84,9 @@ var UI = struct {
|
|||||||
Reactions: []string{`+1`, `-1`, `laugh`, `hooray`, `confused`, `heart`, `rocket`, `eyes`},
|
Reactions: []string{`+1`, `-1`, `laugh`, `hooray`, `confused`, `heart`, `rocket`, `eyes`},
|
||||||
CustomEmojis: []string{`git`, `gitea`, `codeberg`, `gitlab`, `github`, `gogs`},
|
CustomEmojis: []string{`git`, `gitea`, `codeberg`, `gitlab`, `github`, `gogs`},
|
||||||
CustomEmojisMap: map[string]string{"git": ":git:", "gitea": ":gitea:", "codeberg": ":codeberg:", "gitlab": ":gitlab:", "github": ":github:", "gogs": ":gogs:"},
|
CustomEmojisMap: map[string]string{"git": ":git:", "gitea": ":gitea:", "codeberg": ":codeberg:", "gitlab": ":gitlab:", "github": ":github:", "gogs": ":gogs:"},
|
||||||
|
|
||||||
|
AmbiguousUnicodeDetection: true,
|
||||||
|
|
||||||
Notification: struct {
|
Notification: struct {
|
||||||
MinTimeout time.Duration
|
MinTimeout time.Duration
|
||||||
TimeoutStep time.Duration
|
TimeoutStep time.Duration
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
package util
|
package util
|
||||||
|
|
||||||
import "github.com/yuin/goldmark/util"
|
import "unsafe"
|
||||||
|
|
||||||
func isSnakeCaseUpper(c byte) bool {
|
func isSnakeCaseUpper(c byte) bool {
|
||||||
return 'A' <= c && c <= 'Z'
|
return 'A' <= c && c <= 'Z'
|
||||||
@ -83,5 +83,15 @@ func ToSnakeCase(input string) string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return util.BytesToReadOnlyString(res)
|
return UnsafeBytesToString(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnsafeBytesToString uses Go's unsafe package to convert a byte slice to a string.
|
||||||
|
// TODO: replace all "goldmark/util.BytesToReadOnlyString" with this official approach
|
||||||
|
func UnsafeBytesToString(b []byte) string {
|
||||||
|
return unsafe.String(unsafe.SliceData(b), len(b))
|
||||||
|
}
|
||||||
|
|
||||||
|
func UnsafeStringToBytes(s string) []byte {
|
||||||
|
return unsafe.Slice(unsafe.StringData(s), len(s))
|
||||||
}
|
}
|
||||||
|
@ -888,7 +888,7 @@ webauthn_nickname=ニックネーム
|
|||||||
webauthn_delete_key=セキュリティキーの登録解除
|
webauthn_delete_key=セキュリティキーの登録解除
|
||||||
webauthn_delete_key_desc=セキュリティキーの登録を解除すると、今後そのセキュリティキーでサインインすることはできなくなります。 続行しますか?
|
webauthn_delete_key_desc=セキュリティキーの登録を解除すると、今後そのセキュリティキーでサインインすることはできなくなります。 続行しますか?
|
||||||
webauthn_key_loss_warning=セキュリティキーを紛失すると、アカウントへのアクセスを失います。
|
webauthn_key_loss_warning=セキュリティキーを紛失すると、アカウントへのアクセスを失います。
|
||||||
webauthn_alternative_tip=もうひとつ別の認証方法も設定すると良いかもしれません。
|
webauthn_alternative_tip=もうひとつ別の認証方法も設定しておくと良いでしょう。
|
||||||
|
|
||||||
manage_account_links=連携アカウントの管理
|
manage_account_links=連携アカウントの管理
|
||||||
manage_account_links_desc=これらの外部アカウントがGiteaアカウントと連携されています。
|
manage_account_links_desc=これらの外部アカウントがGiteaアカウントと連携されています。
|
||||||
@ -3457,7 +3457,7 @@ owner.settings.chef.keypair.description=Chefレジストリの認証にはキー
|
|||||||
[secrets]
|
[secrets]
|
||||||
secrets=シークレット
|
secrets=シークレット
|
||||||
description=シークレットは特定のActionsに渡されます。 それ以外で読み出されることはありません。
|
description=シークレットは特定のActionsに渡されます。 それ以外で読み出されることはありません。
|
||||||
none=まだシークレットはありません。
|
none=シークレットはまだありません。
|
||||||
creation=シークレットを追加
|
creation=シークレットを追加
|
||||||
creation.name_placeholder=大文字小文字の区別なし、英数字とアンダースコアのみ、GITEA_ や GITHUB_ で始まるものは不可
|
creation.name_placeholder=大文字小文字の区別なし、英数字とアンダースコアのみ、GITEA_ や GITHUB_ で始まるものは不可
|
||||||
creation.value_placeholder=内容を入力してください。前後の空白は除去されます。
|
creation.value_placeholder=内容を入力してください。前後の空白は除去されます。
|
||||||
|
@ -242,18 +242,18 @@ func CreateUserRepo(ctx *context.APIContext, owner *user_model.User, opt api.Cre
|
|||||||
}
|
}
|
||||||
|
|
||||||
repo, err := repo_service.CreateRepository(ctx, ctx.Doer, owner, repo_service.CreateRepoOptions{
|
repo, err := repo_service.CreateRepository(ctx, ctx.Doer, owner, repo_service.CreateRepoOptions{
|
||||||
Name: opt.Name,
|
Name: opt.Name,
|
||||||
Description: opt.Description,
|
Description: opt.Description,
|
||||||
IssueLabels: opt.IssueLabels,
|
IssueLabels: opt.IssueLabels,
|
||||||
Gitignores: opt.Gitignores,
|
Gitignores: opt.Gitignores,
|
||||||
License: opt.License,
|
License: opt.License,
|
||||||
Readme: opt.Readme,
|
Readme: opt.Readme,
|
||||||
IsPrivate: opt.Private,
|
IsPrivate: opt.Private,
|
||||||
AutoInit: opt.AutoInit,
|
AutoInit: opt.AutoInit,
|
||||||
DefaultBranch: opt.DefaultBranch,
|
DefaultBranch: opt.DefaultBranch,
|
||||||
TrustModel: repo_model.ToTrustModel(opt.TrustModel),
|
TrustModel: repo_model.ToTrustModel(opt.TrustModel),
|
||||||
IsTemplate: opt.Template,
|
IsTemplate: opt.Template,
|
||||||
ObjectFormat: git.ObjectFormatFromID(git.Sha1),
|
ObjectFormatName: git.Sha1ObjectFormat.Name(),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if repo_model.IsErrRepoAlreadyExist(err) {
|
if repo_model.IsErrRepoAlreadyExist(err) {
|
||||||
|
@ -81,7 +81,7 @@ func ConvertToObjectID(ctx gocontext.Context, repo *context.Repository, commitID
|
|||||||
|
|
||||||
gitRepo, closer, err := git.RepositoryFromContextOrOpen(ctx, repo.Repository.RepoPath())
|
gitRepo, closer, err := git.RepositoryFromContextOrOpen(ctx, repo.Repository.RepoPath())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return objectFormat.Empty(), fmt.Errorf("RepositoryFromContextOrOpen: %w", err)
|
return objectFormat.EmptyObjectID(), fmt.Errorf("RepositoryFromContextOrOpen: %w", err)
|
||||||
}
|
}
|
||||||
defer closer.Close()
|
defer closer.Close()
|
||||||
|
|
||||||
|
@ -147,7 +147,7 @@ func preReceiveBranch(ctx *preReceiveContext, oldCommitID, newCommitID string, r
|
|||||||
gitRepo := ctx.Repo.GitRepo
|
gitRepo := ctx.Repo.GitRepo
|
||||||
objectFormat, _ := gitRepo.GetObjectFormat()
|
objectFormat, _ := gitRepo.GetObjectFormat()
|
||||||
|
|
||||||
if branchName == repo.DefaultBranch && newCommitID == objectFormat.Empty().String() {
|
if branchName == repo.DefaultBranch && newCommitID == objectFormat.EmptyObjectID().String() {
|
||||||
log.Warn("Forbidden: Branch: %s is the default branch in %-v and cannot be deleted", branchName, repo)
|
log.Warn("Forbidden: Branch: %s is the default branch in %-v and cannot be deleted", branchName, repo)
|
||||||
ctx.JSON(http.StatusForbidden, private.Response{
|
ctx.JSON(http.StatusForbidden, private.Response{
|
||||||
UserMsg: fmt.Sprintf("branch %s is the default branch and cannot be deleted", branchName),
|
UserMsg: fmt.Sprintf("branch %s is the default branch and cannot be deleted", branchName),
|
||||||
@ -175,7 +175,7 @@ func preReceiveBranch(ctx *preReceiveContext, oldCommitID, newCommitID string, r
|
|||||||
// First of all we need to enforce absolutely:
|
// First of all we need to enforce absolutely:
|
||||||
//
|
//
|
||||||
// 1. Detect and prevent deletion of the branch
|
// 1. Detect and prevent deletion of the branch
|
||||||
if newCommitID == objectFormat.Empty().String() {
|
if newCommitID == objectFormat.EmptyObjectID().String() {
|
||||||
log.Warn("Forbidden: Branch: %s in %-v is protected from deletion", branchName, repo)
|
log.Warn("Forbidden: Branch: %s in %-v is protected from deletion", branchName, repo)
|
||||||
ctx.JSON(http.StatusForbidden, private.Response{
|
ctx.JSON(http.StatusForbidden, private.Response{
|
||||||
UserMsg: fmt.Sprintf("branch %s is protected from deletion", branchName),
|
UserMsg: fmt.Sprintf("branch %s is protected from deletion", branchName),
|
||||||
@ -184,7 +184,7 @@ func preReceiveBranch(ctx *preReceiveContext, oldCommitID, newCommitID string, r
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 2. Disallow force pushes to protected branches
|
// 2. Disallow force pushes to protected branches
|
||||||
if oldCommitID != objectFormat.Empty().String() {
|
if oldCommitID != objectFormat.EmptyObjectID().String() {
|
||||||
output, _, err := git.NewCommand(ctx, "rev-list", "--max-count=1").AddDynamicArguments(oldCommitID, "^"+newCommitID).RunStdString(&git.RunOpts{Dir: repo.RepoPath(), Env: ctx.env})
|
output, _, err := git.NewCommand(ctx, "rev-list", "--max-count=1").AddDynamicArguments(oldCommitID, "^"+newCommitID).RunStdString(&git.RunOpts{Dir: repo.RepoPath(), Env: ctx.env})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Unable to detect force push between: %s and %s in %-v Error: %v", oldCommitID, newCommitID, repo, err)
|
log.Error("Unable to detect force push between: %s and %s in %-v Error: %v", oldCommitID, newCommitID, repo, err)
|
||||||
|
@ -30,7 +30,7 @@ func verifyCommits(oldCommitID, newCommitID string, repo *git.Repository, env []
|
|||||||
|
|
||||||
var command *git.Command
|
var command *git.Command
|
||||||
objectFormat, _ := repo.GetObjectFormat()
|
objectFormat, _ := repo.GetObjectFormat()
|
||||||
if oldCommitID == objectFormat.Empty().String() {
|
if oldCommitID == objectFormat.EmptyObjectID().String() {
|
||||||
// When creating a new branch, the oldCommitID is empty, by using "newCommitID --not --all":
|
// When creating a new branch, the oldCommitID is empty, by using "newCommitID --not --all":
|
||||||
// List commits that are reachable by following the newCommitID, exclude "all" existing heads/tags commits
|
// List commits that are reachable by following the newCommitID, exclude "all" existing heads/tags commits
|
||||||
// So, it only lists the new commits received, doesn't list the commits already present in the receiving repository
|
// So, it only lists the new commits received, doesn't list the commits already present in the receiving repository
|
||||||
|
@ -30,9 +30,9 @@ func TestVerifyCommits(t *testing.T) {
|
|||||||
verified bool
|
verified bool
|
||||||
}{
|
}{
|
||||||
{"72920278f2f999e3005801e5d5b8ab8139d3641c", "d766f2917716d45be24bfa968b8409544941be32", true},
|
{"72920278f2f999e3005801e5d5b8ab8139d3641c", "d766f2917716d45be24bfa968b8409544941be32", true},
|
||||||
{objectFormat.Empty().String(), "93eac826f6188f34646cea81bf426aa5ba7d3bfe", true}, // New branch with verified commit
|
{objectFormat.EmptyObjectID().String(), "93eac826f6188f34646cea81bf426aa5ba7d3bfe", true}, // New branch with verified commit
|
||||||
{"9779d17a04f1e2640583d35703c62460b2d86e0a", "72920278f2f999e3005801e5d5b8ab8139d3641c", false},
|
{"9779d17a04f1e2640583d35703c62460b2d86e0a", "72920278f2f999e3005801e5d5b8ab8139d3641c", false},
|
||||||
{objectFormat.Empty().String(), "9ce3f779ae33f31fce17fac3c512047b75d7498b", false}, // New branch with unverified commit
|
{objectFormat.EmptyObjectID().String(), "9ce3f779ae33f31fce17fac3c512047b75d7498b", false}, // New branch with unverified commit
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
|
@ -315,8 +315,7 @@ func renderBlame(ctx *context.Context, blameParts []git.BlamePart, commitNames m
|
|||||||
lexerName = lexerNameForLine
|
lexerName = lexerNameForLine
|
||||||
}
|
}
|
||||||
|
|
||||||
br.EscapeStatus, line = charset.EscapeControlHTML(line, ctx.Locale)
|
br.EscapeStatus, br.Code = charset.EscapeControlHTML(line, ctx.Locale)
|
||||||
br.Code = gotemplate.HTML(line)
|
|
||||||
rows = append(rows, br)
|
rows = append(rows, br)
|
||||||
escapeStatus = escapeStatus.Or(br.EscapeStatus)
|
escapeStatus = escapeStatus.Or(br.EscapeStatus)
|
||||||
}
|
}
|
||||||
|
@ -158,7 +158,7 @@ func RestoreBranchPost(ctx *context.Context) {
|
|||||||
if err := repo_service.PushUpdate(
|
if err := repo_service.PushUpdate(
|
||||||
&repo_module.PushUpdateOptions{
|
&repo_module.PushUpdateOptions{
|
||||||
RefFullName: git.RefNameFromBranch(deletedBranch.Name),
|
RefFullName: git.RefNameFromBranch(deletedBranch.Name),
|
||||||
OldCommitID: objectFormat.Empty().String(),
|
OldCommitID: objectFormat.EmptyObjectID().String(),
|
||||||
NewCommitID: deletedBranch.CommitID,
|
NewCommitID: deletedBranch.CommitID,
|
||||||
PusherID: ctx.Doer.ID,
|
PusherID: ctx.Doer.ID,
|
||||||
PusherName: ctx.Doer.Name,
|
PusherName: ctx.Doer.Name,
|
||||||
|
@ -317,7 +317,7 @@ func ParseCompareInfo(ctx *context.Context) *CompareInfo {
|
|||||||
ci.BaseBranch = baseCommit.ID.String()
|
ci.BaseBranch = baseCommit.ID.String()
|
||||||
ctx.Data["BaseBranch"] = ci.BaseBranch
|
ctx.Data["BaseBranch"] = ci.BaseBranch
|
||||||
baseIsCommit = true
|
baseIsCommit = true
|
||||||
} else if ci.BaseBranch == objectFormat.Empty().String() {
|
} else if ci.BaseBranch == objectFormat.EmptyObjectID().String() {
|
||||||
if isSameRepo {
|
if isSameRepo {
|
||||||
ctx.Redirect(ctx.Repo.RepoLink + "/compare/" + util.PathEscapeSegments(ci.HeadBranch))
|
ctx.Redirect(ctx.Repo.RepoLink + "/compare/" + util.PathEscapeSegments(ci.HeadBranch))
|
||||||
} else {
|
} else {
|
||||||
|
@ -329,7 +329,7 @@ func dummyInfoRefs(ctx *context.Context) {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if err := git.InitRepository(ctx, tmpDir, true, git.ObjectFormatFromID(git.Sha1)); err != nil {
|
if err := git.InitRepository(ctx, tmpDir, true, git.Sha1ObjectFormat.Name()); err != nil {
|
||||||
log.Error("Failed to init bare repo for git-receive-pack cache: %v", err)
|
log.Error("Failed to init bare repo for git-receive-pack cache: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -278,18 +278,18 @@ func CreatePost(ctx *context.Context) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
repo, err = repo_service.CreateRepository(ctx, ctx.Doer, ctxUser, repo_service.CreateRepoOptions{
|
repo, err = repo_service.CreateRepository(ctx, ctx.Doer, ctxUser, repo_service.CreateRepoOptions{
|
||||||
Name: form.RepoName,
|
Name: form.RepoName,
|
||||||
Description: form.Description,
|
Description: form.Description,
|
||||||
Gitignores: form.Gitignores,
|
Gitignores: form.Gitignores,
|
||||||
IssueLabels: form.IssueLabels,
|
IssueLabels: form.IssueLabels,
|
||||||
License: form.License,
|
License: form.License,
|
||||||
Readme: form.Readme,
|
Readme: form.Readme,
|
||||||
IsPrivate: form.Private || setting.Repository.ForcePrivate,
|
IsPrivate: form.Private || setting.Repository.ForcePrivate,
|
||||||
DefaultBranch: form.DefaultBranch,
|
DefaultBranch: form.DefaultBranch,
|
||||||
AutoInit: form.AutoInit,
|
AutoInit: form.AutoInit,
|
||||||
IsTemplate: form.Template,
|
IsTemplate: form.Template,
|
||||||
TrustModel: repo_model.ToTrustModel(form.TrustModel),
|
TrustModel: repo_model.ToTrustModel(form.TrustModel),
|
||||||
ObjectFormat: form.ObjectFormat,
|
ObjectFormatName: form.ObjectFormatName,
|
||||||
})
|
})
|
||||||
if err == nil {
|
if err == nil {
|
||||||
log.Trace("Repository created [%d]: %s/%s", repo.ID, ctxUser.Name, repo.Name)
|
log.Trace("Repository created [%d]: %s/%s", repo.ID, ctxUser.Name, repo.Name)
|
||||||
|
@ -662,7 +662,7 @@ func TestWebhook(ctx *context.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
commit = &git.Commit{
|
commit = &git.Commit{
|
||||||
ID: objectFormat.NewEmptyID(),
|
ID: objectFormat.EmptyObjectID(),
|
||||||
Author: ghost.NewGitSig(),
|
Author: ghost.NewGitSig(),
|
||||||
Committer: ghost.NewGitSig(),
|
Committer: ghost.NewGitSig(),
|
||||||
CommitMessage: "This is a fake commit",
|
CommitMessage: "This is a fake commit",
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
gocontext "context"
|
gocontext "context"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"html/template"
|
||||||
"image"
|
"image"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
@ -317,19 +318,18 @@ func renderReadmeFile(ctx *context.Context, subfolder string, readmeFile *git.Tr
|
|||||||
}, rd)
|
}, rd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Render failed for %s in %-v: %v Falling back to rendering source", readmeFile.Name(), ctx.Repo.Repository, err)
|
log.Error("Render failed for %s in %-v: %v Falling back to rendering source", readmeFile.Name(), ctx.Repo.Repository, err)
|
||||||
buf := &bytes.Buffer{}
|
delete(ctx.Data, "IsMarkup")
|
||||||
ctx.Data["EscapeStatus"], _ = charset.EscapeControlStringReader(rd, buf, ctx.Locale)
|
|
||||||
ctx.Data["FileContent"] = buf.String()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ctx.Data["IsPlainText"] = true
|
|
||||||
buf := &bytes.Buffer{}
|
|
||||||
ctx.Data["EscapeStatus"], err = charset.EscapeControlStringReader(rd, buf, ctx.Locale)
|
|
||||||
if err != nil {
|
|
||||||
log.Error("Read failed: %v", err)
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ctx.Data["FileContent"] = buf.String()
|
if ctx.Data["IsMarkup"] != true {
|
||||||
|
ctx.Data["IsPlainText"] = true
|
||||||
|
content, err := io.ReadAll(rd)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Read readme content failed: %v", err)
|
||||||
|
}
|
||||||
|
contentEscaped := template.HTMLEscapeString(util.UnsafeBytesToString(content))
|
||||||
|
ctx.Data["EscapeStatus"], ctx.Data["FileContent"] = charset.EscapeControlHTML(template.HTML(contentEscaped), ctx.Locale)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !fInfo.isLFSFile && ctx.Repo.CanEnableEditor(ctx, ctx.Doer) {
|
if !fInfo.isLFSFile && ctx.Repo.CanEnableEditor(ctx, ctx.Doer) {
|
||||||
@ -493,7 +493,7 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry, treeLink, rawLink st
|
|||||||
buf, _ := io.ReadAll(rd)
|
buf, _ := io.ReadAll(rd)
|
||||||
|
|
||||||
// The Open Group Base Specification: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html
|
// The Open Group Base Specification: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html
|
||||||
// empty: 0 lines; "a": 1 line, 1 incomplete-line; "a\n": 1 line; "a\nb": 1 line, 1 incomplete-line;
|
// empty: 0 lines; "a": 1 incomplete-line; "a\n": 1 line; "a\nb": 1 line, 1 incomplete-line;
|
||||||
// Gitea uses the definition (like most modern editors):
|
// Gitea uses the definition (like most modern editors):
|
||||||
// empty: 0 lines; "a": 1 line; "a\n": 2 lines; "a\nb": 2 lines;
|
// empty: 0 lines; "a": 1 line; "a\n": 2 lines; "a\nb": 2 lines;
|
||||||
// When rendering, the last empty line is not rendered in UI, while the line-number is still counted, to tell users that the file contains a trailing EOL.
|
// When rendering, the last empty line is not rendered in UI, while the line-number is still counted, to tell users that the file contains a trailing EOL.
|
||||||
@ -620,7 +620,7 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry, treeLink, rawLink st
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func markupRender(ctx *context.Context, renderCtx *markup.RenderContext, input io.Reader) (escaped *charset.EscapeStatus, output string, err error) {
|
func markupRender(ctx *context.Context, renderCtx *markup.RenderContext, input io.Reader) (escaped *charset.EscapeStatus, output template.HTML, err error) {
|
||||||
markupRd, markupWr := io.Pipe()
|
markupRd, markupWr := io.Pipe()
|
||||||
defer markupWr.Close()
|
defer markupWr.Close()
|
||||||
done := make(chan struct{})
|
done := make(chan struct{})
|
||||||
@ -628,7 +628,7 @@ func markupRender(ctx *context.Context, renderCtx *markup.RenderContext, input i
|
|||||||
sb := &strings.Builder{}
|
sb := &strings.Builder{}
|
||||||
// We allow NBSP here this is rendered
|
// We allow NBSP here this is rendered
|
||||||
escaped, _ = charset.EscapeControlReader(markupRd, sb, ctx.Locale, charset.RuneNBSP)
|
escaped, _ = charset.EscapeControlReader(markupRd, sb, ctx.Locale, charset.RuneNBSP)
|
||||||
output = sb.String()
|
output = template.HTML(sb.String())
|
||||||
close(done)
|
close(done)
|
||||||
}()
|
}()
|
||||||
err = markup.Render(renderCtx, input, markupWr)
|
err = markup.Render(renderCtx, input, markupWr)
|
||||||
|
@ -39,7 +39,7 @@ func ProcReceive(ctx context.Context, repo *repo_model.Repository, gitRepo *git.
|
|||||||
objectFormat, _ := gitRepo.GetObjectFormat()
|
objectFormat, _ := gitRepo.GetObjectFormat()
|
||||||
|
|
||||||
for i := range opts.OldCommitIDs {
|
for i := range opts.OldCommitIDs {
|
||||||
if opts.NewCommitIDs[i] == objectFormat.Empty().String() {
|
if opts.NewCommitIDs[i] == objectFormat.EmptyObjectID().String() {
|
||||||
results = append(results, private.HookProcReceiveRefResult{
|
results = append(results, private.HookProcReceiveRefResult{
|
||||||
OriginalRef: opts.RefFullNames[i],
|
OriginalRef: opts.RefFullNames[i],
|
||||||
OldOID: opts.OldCommitIDs[i],
|
OldOID: opts.OldCommitIDs[i],
|
||||||
@ -153,7 +153,7 @@ func ProcReceive(ctx context.Context, repo *repo_model.Repository, gitRepo *git.
|
|||||||
results = append(results, private.HookProcReceiveRefResult{
|
results = append(results, private.HookProcReceiveRefResult{
|
||||||
Ref: pr.GetGitRefName(),
|
Ref: pr.GetGitRefName(),
|
||||||
OriginalRef: opts.RefFullNames[i],
|
OriginalRef: opts.RefFullNames[i],
|
||||||
OldOID: objectFormat.Empty().String(),
|
OldOID: objectFormat.EmptyObjectID().String(),
|
||||||
NewOID: opts.NewCommitIDs[i],
|
NewOID: opts.NewCommitIDs[i],
|
||||||
})
|
})
|
||||||
continue
|
continue
|
||||||
|
@ -19,12 +19,12 @@ import (
|
|||||||
func TestToCommitMeta(t *testing.T) {
|
func TestToCommitMeta(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
headRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
headRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
||||||
sha1 := git.ObjectFormatFromID(git.Sha1)
|
sha1 := git.Sha1ObjectFormat
|
||||||
signature := &git.Signature{Name: "Test Signature", Email: "test@email.com", When: time.Unix(0, 0)}
|
signature := &git.Signature{Name: "Test Signature", Email: "test@email.com", When: time.Unix(0, 0)}
|
||||||
tag := &git.Tag{
|
tag := &git.Tag{
|
||||||
Name: "Test Tag",
|
Name: "Test Tag",
|
||||||
ID: sha1.Empty(),
|
ID: sha1.EmptyObjectID(),
|
||||||
Object: sha1.Empty(),
|
Object: sha1.EmptyObjectID(),
|
||||||
Type: "Test Type",
|
Type: "Test Type",
|
||||||
Tagger: signature,
|
Tagger: signature,
|
||||||
Message: "Test Message",
|
Message: "Test Message",
|
||||||
@ -34,8 +34,8 @@ func TestToCommitMeta(t *testing.T) {
|
|||||||
|
|
||||||
assert.NotNil(t, commitMeta)
|
assert.NotNil(t, commitMeta)
|
||||||
assert.EqualValues(t, &api.CommitMeta{
|
assert.EqualValues(t, &api.CommitMeta{
|
||||||
SHA: sha1.Empty().String(),
|
SHA: sha1.EmptyObjectID().String(),
|
||||||
URL: util.URLJoin(headRepo.APIURL(), "git/commits", sha1.Empty().String()),
|
URL: util.URLJoin(headRepo.APIURL(), "git/commits", sha1.EmptyObjectID().String()),
|
||||||
Created: time.Unix(0, 0),
|
Created: time.Unix(0, 0),
|
||||||
}, commitMeta)
|
}, commitMeta)
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,6 @@ import (
|
|||||||
issues_model "code.gitea.io/gitea/models/issues"
|
issues_model "code.gitea.io/gitea/models/issues"
|
||||||
project_model "code.gitea.io/gitea/models/project"
|
project_model "code.gitea.io/gitea/models/project"
|
||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
"code.gitea.io/gitea/modules/git"
|
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/structs"
|
"code.gitea.io/gitea/modules/structs"
|
||||||
"code.gitea.io/gitea/modules/web/middleware"
|
"code.gitea.io/gitea/modules/web/middleware"
|
||||||
@ -54,7 +53,7 @@ type CreateRepoForm struct {
|
|||||||
TrustModel string
|
TrustModel string
|
||||||
|
|
||||||
ForkSingleBranch string
|
ForkSingleBranch string
|
||||||
ObjectFormat git.ObjectFormat
|
ObjectFormatName string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate validates the fields
|
// Validate validates the fields
|
||||||
|
@ -285,15 +285,15 @@ type DiffInline struct {
|
|||||||
|
|
||||||
// DiffInlineWithUnicodeEscape makes a DiffInline with hidden unicode characters escaped
|
// DiffInlineWithUnicodeEscape makes a DiffInline with hidden unicode characters escaped
|
||||||
func DiffInlineWithUnicodeEscape(s template.HTML, locale translation.Locale) DiffInline {
|
func DiffInlineWithUnicodeEscape(s template.HTML, locale translation.Locale) DiffInline {
|
||||||
status, content := charset.EscapeControlHTML(string(s), locale)
|
status, content := charset.EscapeControlHTML(s, locale)
|
||||||
return DiffInline{EscapeStatus: status, Content: template.HTML(content)}
|
return DiffInline{EscapeStatus: status, Content: content}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DiffInlineWithHighlightCode makes a DiffInline with code highlight and hidden unicode characters escaped
|
// DiffInlineWithHighlightCode makes a DiffInline with code highlight and hidden unicode characters escaped
|
||||||
func DiffInlineWithHighlightCode(fileName, language, code string, locale translation.Locale) DiffInline {
|
func DiffInlineWithHighlightCode(fileName, language, code string, locale translation.Locale) DiffInline {
|
||||||
highlighted, _ := highlight.Code(fileName, language, code)
|
highlighted, _ := highlight.Code(fileName, language, code)
|
||||||
status, content := charset.EscapeControlHTML(highlighted, locale)
|
status, content := charset.EscapeControlHTML(highlighted, locale)
|
||||||
return DiffInline{EscapeStatus: status, Content: template.HTML(content)}
|
return DiffInline{EscapeStatus: status, Content: content}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetComputedInlineDiffFor computes inline diff for the given line.
|
// GetComputedInlineDiffFor computes inline diff for the given line.
|
||||||
@ -1120,7 +1120,7 @@ func GetDiff(ctx context.Context, gitRepo *git.Repository, opts *DiffOptions, fi
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if (len(opts.BeforeCommitID) == 0 || opts.BeforeCommitID == objectFormat.Empty().String()) && commit.ParentCount() == 0 {
|
if (len(opts.BeforeCommitID) == 0 || opts.BeforeCommitID == objectFormat.EmptyObjectID().String()) && commit.ParentCount() == 0 {
|
||||||
cmdDiff.AddArguments("diff", "--src-prefix=\\a/", "--dst-prefix=\\b/", "-M").
|
cmdDiff.AddArguments("diff", "--src-prefix=\\a/", "--dst-prefix=\\b/", "-M").
|
||||||
AddArguments(opts.WhitespaceBehavior...).
|
AddArguments(opts.WhitespaceBehavior...).
|
||||||
AddDynamicArguments(objectFormat.EmptyTree().String()).
|
AddDynamicArguments(objectFormat.EmptyTree().String()).
|
||||||
@ -1229,7 +1229,7 @@ func GetDiff(ctx context.Context, gitRepo *git.Repository, opts *DiffOptions, fi
|
|||||||
}
|
}
|
||||||
|
|
||||||
diffPaths := []string{opts.BeforeCommitID + separator + opts.AfterCommitID}
|
diffPaths := []string{opts.BeforeCommitID + separator + opts.AfterCommitID}
|
||||||
if len(opts.BeforeCommitID) == 0 || opts.BeforeCommitID == objectFormat.Empty().String() {
|
if len(opts.BeforeCommitID) == 0 || opts.BeforeCommitID == objectFormat.EmptyObjectID().String() {
|
||||||
diffPaths = []string{objectFormat.EmptyTree().String(), opts.AfterCommitID}
|
diffPaths = []string{objectFormat.EmptyTree().String(), opts.AfterCommitID}
|
||||||
}
|
}
|
||||||
diff.NumFiles, diff.TotalAddition, diff.TotalDeletion, err = git.GetDiffShortStat(gitRepo.Ctx, repoPath, nil, diffPaths...)
|
diff.NumFiles, diff.TotalAddition, diff.TotalDeletion, err = git.GetDiffShortStat(gitRepo.Ctx, repoPath, nil, diffPaths...)
|
||||||
@ -1267,7 +1267,7 @@ func GetPullDiffStats(gitRepo *git.Repository, opts *DiffOptions) (*PullDiffStat
|
|||||||
}
|
}
|
||||||
|
|
||||||
diffPaths := []string{opts.BeforeCommitID + separator + opts.AfterCommitID}
|
diffPaths := []string{opts.BeforeCommitID + separator + opts.AfterCommitID}
|
||||||
if len(opts.BeforeCommitID) == 0 || opts.BeforeCommitID == objectFormat.Empty().String() {
|
if len(opts.BeforeCommitID) == 0 || opts.BeforeCommitID == objectFormat.EmptyObjectID().String() {
|
||||||
diffPaths = []string{objectFormat.EmptyTree().String(), opts.AfterCommitID}
|
diffPaths = []string{objectFormat.EmptyTree().String(), opts.AfterCommitID}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,10 +93,10 @@ func (hcd *highlightCodeDiff) diffWithHighlight(filename, language, codeA, codeB
|
|||||||
highlightCodeA, _ := highlight.Code(filename, language, codeA)
|
highlightCodeA, _ := highlight.Code(filename, language, codeA)
|
||||||
highlightCodeB, _ := highlight.Code(filename, language, codeB)
|
highlightCodeB, _ := highlight.Code(filename, language, codeB)
|
||||||
|
|
||||||
highlightCodeA = hcd.convertToPlaceholders(highlightCodeA)
|
convertedCodeA := hcd.convertToPlaceholders(string(highlightCodeA))
|
||||||
highlightCodeB = hcd.convertToPlaceholders(highlightCodeB)
|
convertedCodeB := hcd.convertToPlaceholders(string(highlightCodeB))
|
||||||
|
|
||||||
diffs := diffMatchPatch.DiffMain(highlightCodeA, highlightCodeB, true)
|
diffs := diffMatchPatch.DiffMain(convertedCodeA, convertedCodeB, true)
|
||||||
diffs = diffMatchPatch.DiffCleanupEfficiency(diffs)
|
diffs = diffMatchPatch.DiffCleanupEfficiency(diffs)
|
||||||
|
|
||||||
for i := range diffs {
|
for i := range diffs {
|
||||||
|
@ -49,7 +49,7 @@ func CheckAndEnsureSafePR(pr *base.PullRequest, commonCloneBaseURL string, g bas
|
|||||||
|
|
||||||
// SECURITY: SHAs Must be a SHA
|
// SECURITY: SHAs Must be a SHA
|
||||||
// FIXME: hash only a SHA1
|
// FIXME: hash only a SHA1
|
||||||
CommitType := git.ObjectFormatFromID(git.Sha1)
|
CommitType := git.Sha1ObjectFormat
|
||||||
if pr.MergeCommitSHA != "" && !CommitType.IsValid(pr.MergeCommitSHA) {
|
if pr.MergeCommitSHA != "" && !CommitType.IsValid(pr.MergeCommitSHA) {
|
||||||
WarnAndNotice("PR #%d in %s has invalid MergeCommitSHA: %s", pr.Number, g, pr.MergeCommitSHA)
|
WarnAndNotice("PR #%d in %s has invalid MergeCommitSHA: %s", pr.Number, g, pr.MergeCommitSHA)
|
||||||
pr.MergeCommitSHA = ""
|
pr.MergeCommitSHA = ""
|
||||||
|
@ -232,7 +232,7 @@ func TestGiteaUploadUpdateGitForPullRequest(t *testing.T) {
|
|||||||
//
|
//
|
||||||
fromRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
fromRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
||||||
baseRef := "master"
|
baseRef := "master"
|
||||||
assert.NoError(t, git.InitRepository(git.DefaultContext, fromRepo.RepoPath(), false, fromRepo.ObjectFormat))
|
assert.NoError(t, git.InitRepository(git.DefaultContext, fromRepo.RepoPath(), false, fromRepo.ObjectFormatName))
|
||||||
err := git.NewCommand(git.DefaultContext, "symbolic-ref").AddDynamicArguments("HEAD", git.BranchPrefix+baseRef).Run(&git.RunOpts{Dir: fromRepo.RepoPath()})
|
err := git.NewCommand(git.DefaultContext, "symbolic-ref").AddDynamicArguments("HEAD", git.BranchPrefix+baseRef).Run(&git.RunOpts{Dir: fromRepo.RepoPath()})
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.NoError(t, os.WriteFile(filepath.Join(fromRepo.RepoPath(), "README.md"), []byte(fmt.Sprintf("# Testing Repository\n\nOriginally created in: %s", fromRepo.RepoPath())), 0o644))
|
assert.NoError(t, os.WriteFile(filepath.Join(fromRepo.RepoPath(), "README.md"), []byte(fmt.Sprintf("# Testing Repository\n\nOriginally created in: %s", fromRepo.RepoPath())), 0o644))
|
||||||
|
@ -484,7 +484,7 @@ func SyncPullMirror(ctx context.Context, repoID int64) bool {
|
|||||||
}
|
}
|
||||||
notify_service.SyncPushCommits(ctx, m.Repo.MustOwner(ctx), m.Repo, &repo_module.PushUpdateOptions{
|
notify_service.SyncPushCommits(ctx, m.Repo.MustOwner(ctx), m.Repo, &repo_module.PushUpdateOptions{
|
||||||
RefFullName: result.refName,
|
RefFullName: result.refName,
|
||||||
OldCommitID: objectFormat.Empty().String(),
|
OldCommitID: objectFormat.EmptyObjectID().String(),
|
||||||
NewCommitID: commitID,
|
NewCommitID: commitID,
|
||||||
}, repo_module.NewPushCommits())
|
}, repo_module.NewPushCommits())
|
||||||
notify_service.SyncCreateRef(ctx, m.Repo.MustOwner(ctx), m.Repo, result.refName, commitID)
|
notify_service.SyncCreateRef(ctx, m.Repo.MustOwner(ctx), m.Repo, result.refName, commitID)
|
||||||
|
@ -271,7 +271,7 @@ func alterRepositoryContent(ctx context.Context, doer *user_model.User, repo *re
|
|||||||
if !git.IsErrBranchNotExist(err) || !repo.IsEmpty {
|
if !git.IsErrBranchNotExist(err) || !repo.IsEmpty {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := t.Init(repo.ObjectFormat); err != nil {
|
if err := t.Init(repo.ObjectFormatName); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -328,7 +328,7 @@ func AddTestPullRequestTask(doer *user_model.User, repoID int64, branch string,
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
for _, pr := range prs {
|
for _, pr := range prs {
|
||||||
objectFormat, _ := git.GetObjectFormatOfRepo(ctx, pr.BaseRepo.RepoPath())
|
objectFormat, _ := git.GetObjectFormatOfRepo(ctx, pr.BaseRepo.RepoPath())
|
||||||
if newCommitID != "" && newCommitID != objectFormat.Empty().String() {
|
if newCommitID != "" && newCommitID != objectFormat.EmptyObjectID().String() {
|
||||||
changed, err := checkIfPRContentChanged(ctx, pr, oldCommitID, newCommitID)
|
changed, err := checkIfPRContentChanged(ctx, pr, oldCommitID, newCommitID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("checkIfPRContentChanged: %v", err)
|
log.Error("checkIfPRContentChanged: %v", err)
|
||||||
|
@ -93,14 +93,8 @@ func createTemporaryRepoForPR(ctx context.Context, pr *issues_model.PullRequest)
|
|||||||
|
|
||||||
baseRepoPath := pr.BaseRepo.RepoPath()
|
baseRepoPath := pr.BaseRepo.RepoPath()
|
||||||
headRepoPath := pr.HeadRepo.RepoPath()
|
headRepoPath := pr.HeadRepo.RepoPath()
|
||||||
objectFormat, err := git.GetObjectFormatOfRepo(ctx, baseRepoPath)
|
|
||||||
if err != nil {
|
|
||||||
log.Error("Unable to fetch ObjectFormat of repository %s: %v", baseRepoPath, err)
|
|
||||||
cancel()
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := git.InitRepository(ctx, tmpBasePath, false, objectFormat); err != nil {
|
if err := git.InitRepository(ctx, tmpBasePath, false, pr.BaseRepo.ObjectFormatName); err != nil {
|
||||||
log.Error("Unable to init tmpBasePath for %-v: %v", pr, err)
|
log.Error("Unable to init tmpBasePath for %-v: %v", pr, err)
|
||||||
cancel()
|
cancel()
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
@ -174,6 +168,7 @@ func createTemporaryRepoForPR(ctx context.Context, pr *issues_model.PullRequest)
|
|||||||
}
|
}
|
||||||
|
|
||||||
trackingBranch := "tracking"
|
trackingBranch := "tracking"
|
||||||
|
objectFormat := git.ObjectFormatFromName(pr.BaseRepo.ObjectFormatName)
|
||||||
// Fetch head branch
|
// Fetch head branch
|
||||||
var headBranch string
|
var headBranch string
|
||||||
if pr.Flow == issues_model.PullRequestFlowGithub {
|
if pr.Flow == issues_model.PullRequestFlowGithub {
|
||||||
|
@ -89,14 +89,14 @@ func createTag(ctx context.Context, gitRepo *git.Repository, rel *repo_model.Rel
|
|||||||
objectFormat, _ := gitRepo.GetObjectFormat()
|
objectFormat, _ := gitRepo.GetObjectFormat()
|
||||||
commits := repository.NewPushCommits()
|
commits := repository.NewPushCommits()
|
||||||
commits.HeadCommit = repository.CommitToPushCommit(commit)
|
commits.HeadCommit = repository.CommitToPushCommit(commit)
|
||||||
commits.CompareURL = rel.Repo.ComposeCompareURL(objectFormat.Empty().String(), commit.ID.String())
|
commits.CompareURL = rel.Repo.ComposeCompareURL(objectFormat.EmptyObjectID().String(), commit.ID.String())
|
||||||
|
|
||||||
refFullName := git.RefNameFromTag(rel.TagName)
|
refFullName := git.RefNameFromTag(rel.TagName)
|
||||||
notify_service.PushCommits(
|
notify_service.PushCommits(
|
||||||
ctx, rel.Publisher, rel.Repo,
|
ctx, rel.Publisher, rel.Repo,
|
||||||
&repository.PushUpdateOptions{
|
&repository.PushUpdateOptions{
|
||||||
RefFullName: refFullName,
|
RefFullName: refFullName,
|
||||||
OldCommitID: objectFormat.Empty().String(),
|
OldCommitID: objectFormat.EmptyObjectID().String(),
|
||||||
NewCommitID: commit.ID.String(),
|
NewCommitID: commit.ID.String(),
|
||||||
}, commits)
|
}, commits)
|
||||||
notify_service.CreateRef(ctx, rel.Publisher, rel.Repo, refFullName, commit.ID.String())
|
notify_service.CreateRef(ctx, rel.Publisher, rel.Repo, refFullName, commit.ID.String())
|
||||||
@ -335,7 +335,7 @@ func DeleteReleaseByID(ctx context.Context, repo *repo_model.Repository, rel *re
|
|||||||
&repository.PushUpdateOptions{
|
&repository.PushUpdateOptions{
|
||||||
RefFullName: refName,
|
RefFullName: refName,
|
||||||
OldCommitID: rel.Sha1,
|
OldCommitID: rel.Sha1,
|
||||||
NewCommitID: objectFormat.Empty().String(),
|
NewCommitID: objectFormat.EmptyObjectID().String(),
|
||||||
}, repository.NewPushCommits())
|
}, repository.NewPushCommits())
|
||||||
notify_service.DeleteRef(ctx, doer, repo, refName)
|
notify_service.DeleteRef(ctx, doer, repo, refName)
|
||||||
|
|
||||||
|
@ -408,7 +408,7 @@ func DeleteBranch(ctx context.Context, doer *user_model.User, repo *repo_model.R
|
|||||||
&repo_module.PushUpdateOptions{
|
&repo_module.PushUpdateOptions{
|
||||||
RefFullName: git.RefNameFromBranch(branchName),
|
RefFullName: git.RefNameFromBranch(branchName),
|
||||||
OldCommitID: commit.ID.String(),
|
OldCommitID: commit.ID.String(),
|
||||||
NewCommitID: objectFormat.Empty().String(),
|
NewCommitID: objectFormat.EmptyObjectID().String(),
|
||||||
PusherID: doer.ID,
|
PusherID: doer.ID,
|
||||||
PusherName: doer.Name,
|
PusherName: doer.Name,
|
||||||
RepoUserName: repo.OwnerName,
|
RepoUserName: repo.OwnerName,
|
||||||
|
@ -192,7 +192,7 @@ func ReinitMissingRepositories(ctx context.Context) error {
|
|||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
log.Trace("Initializing %d/%d...", repo.OwnerID, repo.ID)
|
log.Trace("Initializing %d/%d...", repo.OwnerID, repo.ID)
|
||||||
if err := git.InitRepository(ctx, repo.RepoPath(), true, repo.ObjectFormat); err != nil {
|
if err := git.InitRepository(ctx, repo.RepoPath(), true, repo.ObjectFormatName); err != nil {
|
||||||
log.Error("Unable (re)initialize repository %d at %s. Error: %v", repo.ID, repo.RepoPath(), err)
|
log.Error("Unable (re)initialize repository %d at %s. Error: %v", repo.ID, repo.RepoPath(), err)
|
||||||
if err2 := system_model.CreateRepositoryNotice("InitRepository [%d]: %v", repo.ID, err); err2 != nil {
|
if err2 := system_model.CreateRepositoryNotice("InitRepository [%d]: %v", repo.ID, err); err2 != nil {
|
||||||
log.Error("CreateRepositoryNotice: %v", err2)
|
log.Error("CreateRepositoryNotice: %v", err2)
|
||||||
|
@ -27,23 +27,23 @@ import (
|
|||||||
|
|
||||||
// CreateRepoOptions contains the create repository options
|
// CreateRepoOptions contains the create repository options
|
||||||
type CreateRepoOptions struct {
|
type CreateRepoOptions struct {
|
||||||
Name string
|
Name string
|
||||||
Description string
|
Description string
|
||||||
OriginalURL string
|
OriginalURL string
|
||||||
GitServiceType api.GitServiceType
|
GitServiceType api.GitServiceType
|
||||||
Gitignores string
|
Gitignores string
|
||||||
IssueLabels string
|
IssueLabels string
|
||||||
License string
|
License string
|
||||||
Readme string
|
Readme string
|
||||||
DefaultBranch string
|
DefaultBranch string
|
||||||
IsPrivate bool
|
IsPrivate bool
|
||||||
IsMirror bool
|
IsMirror bool
|
||||||
IsTemplate bool
|
IsTemplate bool
|
||||||
AutoInit bool
|
AutoInit bool
|
||||||
Status repo_model.RepositoryStatus
|
Status repo_model.RepositoryStatus
|
||||||
TrustModel repo_model.TrustModelType
|
TrustModel repo_model.TrustModelType
|
||||||
MirrorInterval string
|
MirrorInterval string
|
||||||
ObjectFormat git.ObjectFormat
|
ObjectFormatName string
|
||||||
}
|
}
|
||||||
|
|
||||||
func prepareRepoCommit(ctx context.Context, repo *repo_model.Repository, tmpDir, repoPath string, opts CreateRepoOptions) error {
|
func prepareRepoCommit(ctx context.Context, repo *repo_model.Repository, tmpDir, repoPath string, opts CreateRepoOptions) error {
|
||||||
@ -135,7 +135,7 @@ func prepareRepoCommit(ctx context.Context, repo *repo_model.Repository, tmpDir,
|
|||||||
|
|
||||||
// InitRepository initializes README and .gitignore if needed.
|
// InitRepository initializes README and .gitignore if needed.
|
||||||
func initRepository(ctx context.Context, repoPath string, u *user_model.User, repo *repo_model.Repository, opts CreateRepoOptions) (err error) {
|
func initRepository(ctx context.Context, repoPath string, u *user_model.User, repo *repo_model.Repository, opts CreateRepoOptions) (err error) {
|
||||||
if err = repo_module.CheckInitRepository(ctx, repo.OwnerName, repo.Name, opts.ObjectFormat); err != nil {
|
if err = repo_module.CheckInitRepository(ctx, repo.OwnerName, repo.Name, opts.ObjectFormatName); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,10 +210,6 @@ func CreateRepositoryDirectly(ctx context.Context, doer, u *user_model.User, opt
|
|||||||
opts.DefaultBranch = setting.Repository.DefaultBranch
|
opts.DefaultBranch = setting.Repository.DefaultBranch
|
||||||
}
|
}
|
||||||
|
|
||||||
if opts.ObjectFormat == nil {
|
|
||||||
opts.ObjectFormat = git.ObjectFormatFromID(git.Sha1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if label template exist
|
// Check if label template exist
|
||||||
if len(opts.IssueLabels) > 0 {
|
if len(opts.IssueLabels) > 0 {
|
||||||
if _, err := repo_module.LoadTemplateLabelsByDisplayName(opts.IssueLabels); err != nil {
|
if _, err := repo_module.LoadTemplateLabelsByDisplayName(opts.IssueLabels); err != nil {
|
||||||
@ -239,7 +235,7 @@ func CreateRepositoryDirectly(ctx context.Context, doer, u *user_model.User, opt
|
|||||||
TrustModel: opts.TrustModel,
|
TrustModel: opts.TrustModel,
|
||||||
IsMirror: opts.IsMirror,
|
IsMirror: opts.IsMirror,
|
||||||
DefaultBranch: opts.DefaultBranch,
|
DefaultBranch: opts.DefaultBranch,
|
||||||
ObjectFormat: opts.ObjectFormat,
|
ObjectFormatName: opts.ObjectFormatName,
|
||||||
}
|
}
|
||||||
|
|
||||||
var rollbackRepo *repo_model.Repository
|
var rollbackRepo *repo_model.Repository
|
||||||
|
@ -11,6 +11,7 @@ import (
|
|||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
"code.gitea.io/gitea/modules/git"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/structs"
|
"code.gitea.io/gitea/modules/structs"
|
||||||
"code.gitea.io/gitea/services/pull"
|
"code.gitea.io/gitea/services/pull"
|
||||||
@ -66,7 +67,7 @@ func CherryPick(ctx context.Context, repo *repo_model.Repository, doer *user_mod
|
|||||||
}
|
}
|
||||||
parent, err := commit.ParentID(0)
|
parent, err := commit.ParentID(0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
parent = repo.ObjectFormat.EmptyTree()
|
parent = git.ObjectFormatFromName(repo.ObjectFormatName).EmptyTree()
|
||||||
}
|
}
|
||||||
|
|
||||||
base, right := parent.String(), commit.ID.String()
|
base, right := parent.String(), commit.ID.String()
|
||||||
|
@ -77,8 +77,8 @@ func (t *TemporaryUploadRepository) Clone(branch string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Init the repository
|
// Init the repository
|
||||||
func (t *TemporaryUploadRepository) Init(objectFormat git.ObjectFormat) error {
|
func (t *TemporaryUploadRepository) Init(objectFormatName string) error {
|
||||||
if err := git.InitRepository(t.ctx, t.basePath, false, objectFormat); err != nil {
|
if err := git.InitRepository(t.ctx, t.basePath, false, objectFormatName); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
gitRepo, err := git.OpenRepository(t.ctx, t.basePath)
|
gitRepo, err := git.OpenRepository(t.ctx, t.basePath)
|
||||||
|
@ -155,8 +155,7 @@ func ChangeRepoFiles(ctx context.Context, repo *repo_model.Repository, doer *use
|
|||||||
if !git.IsErrBranchNotExist(err) || !repo.IsEmpty {
|
if !git.IsErrBranchNotExist(err) || !repo.IsEmpty {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
objectFormat, _ := gitRepo.GetObjectFormat()
|
if err := t.Init(repo.ObjectFormatName); err != nil {
|
||||||
if err := t.Init(objectFormat); err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
hasOldBranch = false
|
hasOldBranch = false
|
||||||
|
@ -91,7 +91,7 @@ func UploadRepoFiles(ctx context.Context, repo *repo_model.Repository, doer *use
|
|||||||
if !git.IsErrBranchNotExist(err) || !repo.IsEmpty {
|
if !git.IsErrBranchNotExist(err) || !repo.IsEmpty {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err = t.Init(repo.ObjectFormat); err != nil {
|
if err = t.Init(repo.ObjectFormatName); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
hasOldBranch = false
|
hasOldBranch = false
|
||||||
|
@ -111,7 +111,7 @@ func pushUpdates(optsList []*repo_module.PushUpdateOptions) error {
|
|||||||
log.Trace("pushUpdates: %-v %s %s %s", repo, opts.OldCommitID, opts.NewCommitID, opts.RefFullName)
|
log.Trace("pushUpdates: %-v %s %s %s", repo, opts.OldCommitID, opts.NewCommitID, opts.RefFullName)
|
||||||
|
|
||||||
if opts.IsNewRef() && opts.IsDelRef() {
|
if opts.IsNewRef() && opts.IsDelRef() {
|
||||||
return fmt.Errorf("old and new revisions are both %s", objectFormat.Empty())
|
return fmt.Errorf("old and new revisions are both %s", objectFormat.EmptyObjectID())
|
||||||
}
|
}
|
||||||
if opts.RefFullName.IsTag() {
|
if opts.RefFullName.IsTag() {
|
||||||
if pusher == nil || pusher.ID != opts.PusherID {
|
if pusher == nil || pusher.ID != opts.PusherID {
|
||||||
@ -131,7 +131,7 @@ func pushUpdates(optsList []*repo_module.PushUpdateOptions) error {
|
|||||||
&repo_module.PushUpdateOptions{
|
&repo_module.PushUpdateOptions{
|
||||||
RefFullName: git.RefNameFromTag(tagName),
|
RefFullName: git.RefNameFromTag(tagName),
|
||||||
OldCommitID: opts.OldCommitID,
|
OldCommitID: opts.OldCommitID,
|
||||||
NewCommitID: objectFormat.Empty().String(),
|
NewCommitID: objectFormat.EmptyObjectID().String(),
|
||||||
}, repo_module.NewPushCommits())
|
}, repo_module.NewPushCommits())
|
||||||
|
|
||||||
delTags = append(delTags, tagName)
|
delTags = append(delTags, tagName)
|
||||||
@ -144,13 +144,13 @@ func pushUpdates(optsList []*repo_module.PushUpdateOptions) error {
|
|||||||
|
|
||||||
commits := repo_module.NewPushCommits()
|
commits := repo_module.NewPushCommits()
|
||||||
commits.HeadCommit = repo_module.CommitToPushCommit(newCommit)
|
commits.HeadCommit = repo_module.CommitToPushCommit(newCommit)
|
||||||
commits.CompareURL = repo.ComposeCompareURL(objectFormat.Empty().String(), opts.NewCommitID)
|
commits.CompareURL = repo.ComposeCompareURL(objectFormat.EmptyObjectID().String(), opts.NewCommitID)
|
||||||
|
|
||||||
notify_service.PushCommits(
|
notify_service.PushCommits(
|
||||||
ctx, pusher, repo,
|
ctx, pusher, repo,
|
||||||
&repo_module.PushUpdateOptions{
|
&repo_module.PushUpdateOptions{
|
||||||
RefFullName: opts.RefFullName,
|
RefFullName: opts.RefFullName,
|
||||||
OldCommitID: objectFormat.Empty().String(),
|
OldCommitID: objectFormat.EmptyObjectID().String(),
|
||||||
NewCommitID: opts.NewCommitID,
|
NewCommitID: opts.NewCommitID,
|
||||||
}, commits)
|
}, commits)
|
||||||
|
|
||||||
@ -234,7 +234,7 @@ func pushUpdates(optsList []*repo_module.PushUpdateOptions) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
oldCommitID := opts.OldCommitID
|
oldCommitID := opts.OldCommitID
|
||||||
if oldCommitID == objectFormat.Empty().String() && len(commits.Commits) > 0 {
|
if oldCommitID == objectFormat.EmptyObjectID().String() && len(commits.Commits) > 0 {
|
||||||
oldCommit, err := gitRepo.GetCommit(commits.Commits[len(commits.Commits)-1].Sha1)
|
oldCommit, err := gitRepo.GetCommit(commits.Commits[len(commits.Commits)-1].Sha1)
|
||||||
if err != nil && !git.IsErrNotExist(err) {
|
if err != nil && !git.IsErrNotExist(err) {
|
||||||
log.Error("unable to GetCommit %s from %-v: %v", oldCommitID, repo, err)
|
log.Error("unable to GetCommit %s from %-v: %v", oldCommitID, repo, err)
|
||||||
@ -250,11 +250,11 @@ func pushUpdates(optsList []*repo_module.PushUpdateOptions) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if oldCommitID == objectFormat.Empty().String() && repo.DefaultBranch != branch {
|
if oldCommitID == objectFormat.EmptyObjectID().String() && repo.DefaultBranch != branch {
|
||||||
oldCommitID = repo.DefaultBranch
|
oldCommitID = repo.DefaultBranch
|
||||||
}
|
}
|
||||||
|
|
||||||
if oldCommitID != objectFormat.Empty().String() {
|
if oldCommitID != objectFormat.EmptyObjectID().String() {
|
||||||
commits.CompareURL = repo.ComposeCompareURL(oldCommitID, opts.NewCommitID)
|
commits.CompareURL = repo.ComposeCompareURL(oldCommitID, opts.NewCommitID)
|
||||||
} else {
|
} else {
|
||||||
commits.CompareURL = ""
|
commits.CompareURL = ""
|
||||||
|
@ -36,7 +36,7 @@ func InitWiki(ctx context.Context, repo *repo_model.Repository) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := git.InitRepository(ctx, repo.WikiPath(), true, git.ObjectFormatFromID(git.Sha1)); err != nil {
|
if err := git.InitRepository(ctx, repo.WikiPath(), true, repo.ObjectFormatName); err != nil {
|
||||||
return fmt.Errorf("InitRepository: %w", err)
|
return fmt.Errorf("InitRepository: %w", err)
|
||||||
} else if err = repo_module.CreateDelegateHooks(repo.WikiPath()); err != nil {
|
} else if err = repo_module.CreateDelegateHooks(repo.WikiPath()); err != nil {
|
||||||
return fmt.Errorf("createDelegateHooks: %w", err)
|
return fmt.Errorf("createDelegateHooks: %w", err)
|
||||||
|
@ -302,7 +302,7 @@ func TestPrepareWikiFileName_FirstPage(t *testing.T) {
|
|||||||
// Now create a temporaryDirectory
|
// Now create a temporaryDirectory
|
||||||
tmpDir := t.TempDir()
|
tmpDir := t.TempDir()
|
||||||
|
|
||||||
err := git.InitRepository(git.DefaultContext, tmpDir, true, git.ObjectFormatFromID(git.Sha1))
|
err := git.InitRepository(git.DefaultContext, tmpDir, true, git.Sha1ObjectFormat.Name())
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
gitRepo, err := git.OpenRepository(git.DefaultContext, tmpDir)
|
gitRepo, err := git.OpenRepository(git.DefaultContext, tmpDir)
|
||||||
|
@ -74,9 +74,9 @@
|
|||||||
{{end}}
|
{{end}}
|
||||||
<div class="file-view{{if .IsMarkup}} markup {{.MarkupType}}{{else if .IsPlainText}} plain-text{{else if .IsTextSource}} code-view{{end}}">
|
<div class="file-view{{if .IsMarkup}} markup {{.MarkupType}}{{else if .IsPlainText}} plain-text{{else if .IsTextSource}} code-view{{end}}">
|
||||||
{{if .IsMarkup}}
|
{{if .IsMarkup}}
|
||||||
{{if .FileContent}}{{.FileContent | Safe}}{{end}}
|
{{if .FileContent}}{{.FileContent}}{{end}}
|
||||||
{{else if .IsPlainText}}
|
{{else if .IsPlainText}}
|
||||||
<pre>{{if .FileContent}}{{.FileContent | Safe}}{{end}}</pre>
|
<pre>{{if .FileContent}}{{.FileContent}}{{end}}</pre>
|
||||||
{{else if not .IsTextSource}}
|
{{else if not .IsTextSource}}
|
||||||
<div class="view-raw">
|
<div class="view-raw">
|
||||||
{{if .IsImageFile}}
|
{{if .IsImageFile}}
|
||||||
@ -114,7 +114,7 @@
|
|||||||
{{if $.EscapeStatus.Escaped}}
|
{{if $.EscapeStatus.Escaped}}
|
||||||
<td class="lines-escape">{{if (index $.LineEscapeStatus $idx).Escaped}}<button class="toggle-escape-button btn interact-bg" title="{{if (index $.LineEscapeStatus $idx).HasInvisible}}{{ctx.Locale.Tr "repo.invisible_runes_line"}} {{end}}{{if (index $.LineEscapeStatus $idx).HasAmbiguous}}{{ctx.Locale.Tr "repo.ambiguous_runes_line"}}{{end}}"></button>{{end}}</td>
|
<td class="lines-escape">{{if (index $.LineEscapeStatus $idx).Escaped}}<button class="toggle-escape-button btn interact-bg" title="{{if (index $.LineEscapeStatus $idx).HasInvisible}}{{ctx.Locale.Tr "repo.invisible_runes_line"}} {{end}}{{if (index $.LineEscapeStatus $idx).HasAmbiguous}}{{ctx.Locale.Tr "repo.ambiguous_runes_line"}}{{end}}"></button>{{end}}</td>
|
||||||
{{end}}
|
{{end}}
|
||||||
<td rel="L{{$line}}" class="lines-code chroma"><code class="code-inner">{{$code | Safe}}</code></td>
|
<td rel="L{{$line}}" class="lines-code chroma"><code class="code-inner">{{$code}}</code></td>
|
||||||
</tr>
|
</tr>
|
||||||
{{end}}
|
{{end}}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
@ -120,7 +120,7 @@ func doGitCloneFail(u *url.URL) func(*testing.T) {
|
|||||||
func doGitInitTestRepository(dstPath string) func(*testing.T) {
|
func doGitInitTestRepository(dstPath string) func(*testing.T) {
|
||||||
return func(t *testing.T) {
|
return func(t *testing.T) {
|
||||||
// Init repository in dstPath
|
// Init repository in dstPath
|
||||||
assert.NoError(t, git.InitRepository(git.DefaultContext, dstPath, false, git.ObjectFormatFromID(git.Sha1)))
|
assert.NoError(t, git.InitRepository(git.DefaultContext, dstPath, false, git.Sha1ObjectFormat.Name()))
|
||||||
// forcibly set default branch to master
|
// forcibly set default branch to master
|
||||||
_, _, err := git.NewCommand(git.DefaultContext, "symbolic-ref", "HEAD", git.BranchPrefix+"master").RunStdString(&git.RunOpts{Dir: dstPath})
|
_, _, err := git.NewCommand(git.DefaultContext, "symbolic-ref", "HEAD", git.BranchPrefix+"master").RunStdString(&git.RunOpts{Dir: dstPath})
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user