mirror of
https://github.com/go-gitea/gitea.git
synced 2025-11-08 05:02:38 +09:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
84a5b81d27 | ||
|
|
84f41d9d92 | ||
|
|
acb9ae4c4d | ||
|
|
b76d899f7a | ||
|
|
9f33aa61bd | ||
|
|
d0bbfd835f | ||
|
|
c7bbfd8f5e | ||
|
|
59a64c0e1d | ||
|
|
6a86a82368 |
15
CHANGELOG.md
15
CHANGELOG.md
@@ -4,6 +4,21 @@ This changelog goes through all the changes that have been made in each release
|
|||||||
without substantial changes to our git log; to see the highlights of what has
|
without substantial changes to our git log; to see the highlights of what has
|
||||||
been added to each release, please refer to the [blog](https://blog.gitea.io).
|
been added to each release, please refer to the [blog](https://blog.gitea.io).
|
||||||
|
|
||||||
|
## [1.7.5](https://github.com/go-gitea/gitea/releases/tag/v1.7.5) - 2019-03-27
|
||||||
|
* BUGFIXES
|
||||||
|
* Fix unitTypeCode not being used in accessLevelUnit (#6419) (#6423)
|
||||||
|
* Fix bug where manifest.json was being requested without cookies and continuously creating new sessions (#6372) (#6383)
|
||||||
|
* Fix ParsePatch function to work with quoted diff --git strings (#6323) (#6332)
|
||||||
|
|
||||||
|
## [1.7.4](https://github.com/go-gitea/gitea/releases/tag/v1.7.4) - 2019-03-12
|
||||||
|
* SECURITY
|
||||||
|
* Fix potential XSS vulnerability in repository description. (#6306) (#6308)
|
||||||
|
* BUGFIXES
|
||||||
|
* Fix wrong release commit id (#6224) (#6300)
|
||||||
|
* Fix panic on empty signed commits (#6292) (#6300)
|
||||||
|
* Fix organization dropdown not being scrollable when using mouse wheel (#5988) (#6246)
|
||||||
|
* Fix displaying dashboard even if required to change password (#6214) (#6215)
|
||||||
|
|
||||||
## [1.7.3](https://github.com/go-gitea/gitea/releases/tag/v1.7.3) - 2019-02-27
|
## [1.7.3](https://github.com/go-gitea/gitea/releases/tag/v1.7.3) - 2019-02-27
|
||||||
* BUGFIXES
|
* BUGFIXES
|
||||||
* Fix server 500 when trying to migrate to an already existing repository (#6188) (#6197)
|
* Fix server 500 when trying to migrate to an already existing repository (#6188) (#6197)
|
||||||
|
|||||||
5
Gopkg.lock
generated
5
Gopkg.lock
generated
@@ -3,11 +3,11 @@
|
|||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
digest = "1:ab875622908a804a327a95a1701002b150806a3c5406df51ec231eac16d3a1ca"
|
digest = "1:e1fa64238b0a2dbf1edf98c4af8d1b8cb65179e286d7f28006b50fa9f508ee9d"
|
||||||
name = "code.gitea.io/git"
|
name = "code.gitea.io/git"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
pruneopts = "NUT"
|
pruneopts = "NUT"
|
||||||
revision = "389d3c803e12a30dffcbb54a15c2242521bc4333"
|
revision = "74d7c14dd4a3ed9c5def0dc3c1aeede399ddc5c5"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
@@ -1173,7 +1173,6 @@
|
|||||||
"github.com/keybase/go-crypto/openpgp",
|
"github.com/keybase/go-crypto/openpgp",
|
||||||
"github.com/keybase/go-crypto/openpgp/armor",
|
"github.com/keybase/go-crypto/openpgp/armor",
|
||||||
"github.com/keybase/go-crypto/openpgp/packet",
|
"github.com/keybase/go-crypto/openpgp/packet",
|
||||||
"github.com/klauspost/compress/gzip",
|
|
||||||
"github.com/lafriks/xormstore",
|
"github.com/lafriks/xormstore",
|
||||||
"github.com/lib/pq",
|
"github.com/lib/pq",
|
||||||
"github.com/lunny/dingtalk_webhook",
|
"github.com/lunny/dingtalk_webhook",
|
||||||
|
|||||||
@@ -550,7 +550,12 @@ func ParsePatch(maxLines, maxLineCharacters, maxFiles int, reader io.Reader) (*D
|
|||||||
beg := len(cmdDiffHead)
|
beg := len(cmdDiffHead)
|
||||||
a := line[beg+2 : middle]
|
a := line[beg+2 : middle]
|
||||||
b := line[middle+3:]
|
b := line[middle+3:]
|
||||||
|
|
||||||
if hasQuote {
|
if hasQuote {
|
||||||
|
// Keep the entire string in double quotes for now
|
||||||
|
a = line[beg:middle]
|
||||||
|
b = line[middle+1:]
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
a, err = strconv.Unquote(a)
|
a, err = strconv.Unquote(a)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -560,6 +565,10 @@ func ParsePatch(maxLines, maxLineCharacters, maxFiles int, reader io.Reader) (*D
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Unquote: %v", err)
|
return nil, fmt.Errorf("Unquote: %v", err)
|
||||||
}
|
}
|
||||||
|
// Now remove the /a /b
|
||||||
|
a = a[2:]
|
||||||
|
b = b[2:]
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
curFile = &DiffFile{
|
curFile = &DiffFile{
|
||||||
@@ -637,6 +646,7 @@ func ParsePatch(maxLines, maxLineCharacters, maxFiles int, reader io.Reader) (*D
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return diff, nil
|
return diff, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
|
||||||
dmp "github.com/sergi/go-diff/diffmatchpatch"
|
dmp "github.com/sergi/go-diff/diffmatchpatch"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
@@ -99,6 +101,59 @@ func ExampleCutDiffAroundLine() {
|
|||||||
println(result)
|
println(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestParsePatch(t *testing.T) {
|
||||||
|
var diff = `diff --git "a/README.md" "b/README.md"
|
||||||
|
--- a/README.md
|
||||||
|
+++ b/README.md
|
||||||
|
@@ -1,3 +1,6 @@
|
||||||
|
# gitea-github-migrator
|
||||||
|
+
|
||||||
|
+ Build Status
|
||||||
|
- Latest Release
|
||||||
|
Docker Pulls
|
||||||
|
+ cut off
|
||||||
|
+ cut off`
|
||||||
|
result, err := ParsePatch(setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(diff))
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("ParsePatch failed: %s", err)
|
||||||
|
}
|
||||||
|
println(result)
|
||||||
|
|
||||||
|
var diff2 = `diff --git "a/A \\ B" "b/A \\ B"
|
||||||
|
--- "a/A \\ B"
|
||||||
|
+++ "b/A \\ B"
|
||||||
|
@@ -1,3 +1,6 @@
|
||||||
|
# gitea-github-migrator
|
||||||
|
+
|
||||||
|
+ Build Status
|
||||||
|
- Latest Release
|
||||||
|
Docker Pulls
|
||||||
|
+ cut off
|
||||||
|
+ cut off`
|
||||||
|
result, err = ParsePatch(setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(diff2))
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("ParsePatch failed: %s", err)
|
||||||
|
}
|
||||||
|
println(result)
|
||||||
|
|
||||||
|
var diff3 = `diff --git a/README.md b/README.md
|
||||||
|
--- a/README.md
|
||||||
|
+++ b/README.md
|
||||||
|
@@ -1,3 +1,6 @@
|
||||||
|
# gitea-github-migrator
|
||||||
|
+
|
||||||
|
+ Build Status
|
||||||
|
- Latest Release
|
||||||
|
Docker Pulls
|
||||||
|
+ cut off
|
||||||
|
+ cut off`
|
||||||
|
result, err = ParsePatch(setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(diff3))
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("ParsePatch failed: %s", err)
|
||||||
|
}
|
||||||
|
println(result)
|
||||||
|
}
|
||||||
|
|
||||||
func setupDefaultDiff() *Diff {
|
func setupDefaultDiff() *Diff {
|
||||||
return &Diff{
|
return &Diff{
|
||||||
Files: []*DiffFile{
|
Files: []*DiffFile{
|
||||||
|
|||||||
@@ -719,10 +719,12 @@ var (
|
|||||||
|
|
||||||
// DescriptionHTML does special handles to description and return HTML string.
|
// DescriptionHTML does special handles to description and return HTML string.
|
||||||
func (repo *Repository) DescriptionHTML() template.HTML {
|
func (repo *Repository) DescriptionHTML() template.HTML {
|
||||||
sanitize := func(s string) string {
|
desc, err := markup.RenderDescriptionHTML([]byte(repo.Description), repo.HTMLURL(), repo.ComposeMetas())
|
||||||
return fmt.Sprintf(`<a href="%[1]s" target="_blank" rel="noopener noreferrer">%[1]s</a>`, s)
|
if err != nil {
|
||||||
|
log.Error(4, "Failed to render description for %s (ID: %d): %v", repo.Name, repo.ID, err)
|
||||||
|
return template.HTML(markup.Sanitize(repo.Description))
|
||||||
}
|
}
|
||||||
return template.HTML(descPattern.ReplaceAllStringFunc(markup.Sanitize(repo.Description), sanitize))
|
return template.HTML(markup.Sanitize(string(desc)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// LocalCopyPath returns the local repository copy path.
|
// LocalCopyPath returns the local repository copy path.
|
||||||
|
|||||||
@@ -70,10 +70,6 @@ func (repo *Repository) CheckBranchName(name string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := gitRepo.GetTag(name); err == nil {
|
|
||||||
return ErrTagAlreadyExists{name}
|
|
||||||
}
|
|
||||||
|
|
||||||
branches, err := repo.GetBranches()
|
branches, err := repo.GetBranches()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -87,6 +83,11 @@ func (repo *Repository) CheckBranchName(name string) error {
|
|||||||
return ErrBranchNameConflict{branch.Name}
|
return ErrBranchNameConflict{branch.Name}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if _, err := gitRepo.GetTag(name); err == nil {
|
||||||
|
return ErrTagAlreadyExists{name}
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -238,7 +238,7 @@ func accessLevelUnit(e Engine, user *User, repo *Repository, unitType UnitType)
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return AccessModeNone, err
|
return AccessModeNone, err
|
||||||
}
|
}
|
||||||
return perm.UnitAccessMode(UnitTypeCode), nil
|
return perm.UnitAccessMode(unitType), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func hasAccessUnit(e Engine, user *User, repo *Repository, unitType UnitType, testMode AccessMode) (bool, error) {
|
func hasAccessUnit(e Engine, user *User, repo *Repository, unitType UnitType, testMode AccessMode) (bool, error) {
|
||||||
|
|||||||
@@ -44,21 +44,17 @@ func Toggle(options *ToggleOptions) macaron.Handler {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// prevent infinite redirection
|
|
||||||
// also make sure that the form cannot be accessed by
|
|
||||||
// users who don't need this
|
|
||||||
if ctx.Req.URL.Path == "/user/settings/change_password" {
|
|
||||||
if !ctx.User.MustChangePassword {
|
|
||||||
ctx.Redirect(setting.AppSubURL + "/")
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if ctx.User.MustChangePassword {
|
if ctx.User.MustChangePassword {
|
||||||
ctx.Data["Title"] = ctx.Tr("auth.must_change_password")
|
if ctx.Req.URL.Path != "/user/settings/change_password" {
|
||||||
ctx.Data["ChangePasscodeLink"] = setting.AppSubURL + "/user/change_password"
|
ctx.Data["Title"] = ctx.Tr("auth.must_change_password")
|
||||||
ctx.SetCookie("redirect_to", url.QueryEscape(setting.AppSubURL+ctx.Req.RequestURI), 0, setting.AppSubURL)
|
ctx.Data["ChangePasscodeLink"] = setting.AppSubURL + "/user/change_password"
|
||||||
ctx.Redirect(setting.AppSubURL + "/user/settings/change_password")
|
ctx.SetCookie("redirect_to", url.QueryEscape(setting.AppSubURL+ctx.Req.RequestURI), 0, setting.AppSubURL)
|
||||||
|
ctx.Redirect(setting.AppSubURL + "/user/settings/change_password")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else if ctx.Req.URL.Path == "/user/settings/change_password" {
|
||||||
|
// make sure that the form cannot be accessed by users who don't need this
|
||||||
|
ctx.Redirect(setting.AppSubURL + "/")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -234,6 +234,23 @@ func RenderCommitMessage(
|
|||||||
return ctx.postProcess(rawHTML)
|
return ctx.postProcess(rawHTML)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RenderDescriptionHTML will use similar logic as PostProcess, but will
|
||||||
|
// use a single special linkProcessor.
|
||||||
|
func RenderDescriptionHTML(
|
||||||
|
rawHTML []byte,
|
||||||
|
urlPrefix string,
|
||||||
|
metas map[string]string,
|
||||||
|
) ([]byte, error) {
|
||||||
|
ctx := &postProcessCtx{
|
||||||
|
metas: metas,
|
||||||
|
urlPrefix: urlPrefix,
|
||||||
|
procs: []processor{
|
||||||
|
descriptionLinkProcessor,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return ctx.postProcess(rawHTML)
|
||||||
|
}
|
||||||
|
|
||||||
var byteBodyTag = []byte("<body>")
|
var byteBodyTag = []byte("<body>")
|
||||||
var byteBodyTagClosing = []byte("</body>")
|
var byteBodyTagClosing = []byte("</body>")
|
||||||
|
|
||||||
@@ -668,3 +685,34 @@ func genDefaultLinkProcessor(defaultLink string) processor {
|
|||||||
node.FirstChild, node.LastChild = ch, ch
|
node.FirstChild, node.LastChild = ch, ch
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// descriptionLinkProcessor creates links for DescriptionHTML
|
||||||
|
func descriptionLinkProcessor(ctx *postProcessCtx, node *html.Node) {
|
||||||
|
m := linkRegex.FindStringIndex(node.Data)
|
||||||
|
if m == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
uri := node.Data[m[0]:m[1]]
|
||||||
|
replaceContent(node, m[0], m[1], createDescriptionLink(uri, uri))
|
||||||
|
}
|
||||||
|
|
||||||
|
func createDescriptionLink(href, content string) *html.Node {
|
||||||
|
textNode := &html.Node{
|
||||||
|
Type: html.TextNode,
|
||||||
|
Data: content,
|
||||||
|
}
|
||||||
|
linkNode := &html.Node{
|
||||||
|
FirstChild: textNode,
|
||||||
|
LastChild: textNode,
|
||||||
|
Type: html.ElementNode,
|
||||||
|
Data: "a",
|
||||||
|
DataAtom: atom.A,
|
||||||
|
Attr: []html.Attribute{
|
||||||
|
{Key: "href", Val: href},
|
||||||
|
{Key: "target", Val: "_blank"},
|
||||||
|
{Key: "rel", Val: "noopener noreferrer"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
textNode.Parent = linkNode
|
||||||
|
return linkNode
|
||||||
|
}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -384,33 +384,12 @@ pre, code {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.overflow.menu {
|
.ui.floating.dropdown {
|
||||||
.items {
|
.overflow.menu {
|
||||||
max-height: 300px;
|
.scrolling.menu.items {
|
||||||
overflow-y: auto;
|
border-radius: 0px !important;
|
||||||
.item {
|
box-shadow: none !important;
|
||||||
position: relative;
|
border-bottom: 1px solid rgba(34, 36, 38, 0.15);
|
||||||
cursor: pointer;
|
|
||||||
display: block;
|
|
||||||
border: none;
|
|
||||||
height: auto;
|
|
||||||
border-top: none;
|
|
||||||
line-height: 1em;
|
|
||||||
color: rgba(0,0,0,.8);
|
|
||||||
padding: .71428571em 1.14285714em !important;
|
|
||||||
font-size: 1rem;
|
|
||||||
text-transform: none;
|
|
||||||
font-weight: 400;
|
|
||||||
box-shadow: none;
|
|
||||||
-webkit-touch-callout: none;
|
|
||||||
&.active {
|
|
||||||
font-weight: 700;
|
|
||||||
}
|
|
||||||
&:hover {
|
|
||||||
background: rgba(0,0,0,.05);
|
|
||||||
color: rgba(0,0,0,.8);
|
|
||||||
z-index: 13;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ package routers
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
@@ -43,6 +44,11 @@ func Home(ctx *context.Context) {
|
|||||||
log.Info("Failed authentication attempt for %s from %s", ctx.User.Name, ctx.RemoteAddr())
|
log.Info("Failed authentication attempt for %s from %s", ctx.User.Name, ctx.RemoteAddr())
|
||||||
ctx.Data["Title"] = ctx.Tr("auth.prohibit_login")
|
ctx.Data["Title"] = ctx.Tr("auth.prohibit_login")
|
||||||
ctx.HTML(200, "user/auth/prohibit_login")
|
ctx.HTML(200, "user/auth/prohibit_login")
|
||||||
|
} else if ctx.User.MustChangePassword {
|
||||||
|
ctx.Data["Title"] = ctx.Tr("auth.must_change_password")
|
||||||
|
ctx.Data["ChangePasscodeLink"] = setting.AppSubURL + "/user/change_password"
|
||||||
|
ctx.SetCookie("redirect_to", url.QueryEscape(setting.AppSubURL+ctx.Req.RequestURI), 0, setting.AppSubURL)
|
||||||
|
ctx.Redirect(setting.AppSubURL + "/user/settings/change_password")
|
||||||
} else {
|
} else {
|
||||||
user.Dashboard(ctx)
|
user.Dashboard(ctx)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ func renderDirectory(ctx *context.Context, treeLink string) {
|
|||||||
}
|
}
|
||||||
entries.CustomSort(base.NaturalSortLess)
|
entries.CustomSort(base.NaturalSortLess)
|
||||||
|
|
||||||
ctx.Data["Files"], err = entries.GetCommitsInfo(ctx.Repo.Commit, ctx.Repo.TreePath)
|
ctx.Data["Files"], err = entries.GetCommitsInfo(ctx.Repo.Commit, ctx.Repo.TreePath, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("GetCommitsInfo", err)
|
ctx.ServerError("GetCommitsInfo", err)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
||||||
<title>{{if .Title}}{{.Title}} - {{end}}{{AppName}}</title>
|
<title>{{if .Title}}{{.Title}} - {{end}}{{AppName}}</title>
|
||||||
<link rel="manifest" href="{{AppSubUrl}}/manifest.json">
|
<link rel="manifest" href="{{AppSubUrl}}/manifest.json" crossorigin="use-credentials">
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
if ('serviceWorker' in navigator) {
|
if ('serviceWorker' in navigator) {
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
<div class="ui header">
|
<div class="ui header">
|
||||||
{{.i18n.Tr "home.switch_dashboard_context"}}
|
{{.i18n.Tr "home.switch_dashboard_context"}}
|
||||||
</div>
|
</div>
|
||||||
<div class="items">
|
<div class="scrolling menu items">
|
||||||
<a class="{{if eq .ContextUser.ID .SignedUser.ID}}active selected{{end}} item" href="{{AppSubUrl}}/{{if .PageIsIssues}}issues{{else if .PageIsPulls}}pulls{{end}}">
|
<a class="{{if eq .ContextUser.ID .SignedUser.ID}}active selected{{end}} item" href="{{AppSubUrl}}/{{if .PageIsIssues}}issues{{else if .PageIsPulls}}pulls{{end}}">
|
||||||
<img class="ui avatar image" src="{{.SignedUser.RelAvatarLink}}">
|
<img class="ui avatar image" src="{{.SignedUser.RelAvatarLink}}">
|
||||||
{{.SignedUser.Name}}
|
{{.SignedUser.Name}}
|
||||||
|
|||||||
11
vendor/code.gitea.io/git/cache.go
generated
vendored
Normal file
11
vendor/code.gitea.io/git/cache.go
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
// Copyright 2019 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package git
|
||||||
|
|
||||||
|
// LastCommitCache cache
|
||||||
|
type LastCommitCache interface {
|
||||||
|
Get(repoPath, ref, entryPath string) (*Commit, error)
|
||||||
|
Put(repoPath, ref, entryPath string, commit *Commit) error
|
||||||
|
}
|
||||||
53
vendor/code.gitea.io/git/commit.go
generated
vendored
53
vendor/code.gitea.io/git/commit.go
generated
vendored
@@ -1,4 +1,5 @@
|
|||||||
// Copyright 2015 The Gogs Authors. All rights reserved.
|
// Copyright 2015 The Gogs Authors. All rights reserved.
|
||||||
|
// Copyright 2018 The Gitea Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a MIT-style
|
// Use of this source code is governed by a MIT-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
@@ -9,6 +10,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"container/list"
|
"container/list"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -16,6 +18,7 @@ import (
|
|||||||
|
|
||||||
// Commit represents a git commit.
|
// Commit represents a git commit.
|
||||||
type Commit struct {
|
type Commit struct {
|
||||||
|
Branch string // Branch this commit belongs to
|
||||||
Tree
|
Tree
|
||||||
ID SHA1 // The ID of this commit object
|
ID SHA1 // The ID of this commit object
|
||||||
Author *Signature
|
Author *Signature
|
||||||
@@ -279,6 +282,56 @@ func (c *Commit) GetSubModule(entryname string) (*SubModule, error) {
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CommitFileStatus represents status of files in a commit.
|
||||||
|
type CommitFileStatus struct {
|
||||||
|
Added []string
|
||||||
|
Removed []string
|
||||||
|
Modified []string
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewCommitFileStatus creates a CommitFileStatus
|
||||||
|
func NewCommitFileStatus() *CommitFileStatus {
|
||||||
|
return &CommitFileStatus{
|
||||||
|
[]string{}, []string{}, []string{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetCommitFileStatus returns file status of commit in given repository.
|
||||||
|
func GetCommitFileStatus(repoPath, commitID string) (*CommitFileStatus, error) {
|
||||||
|
stdout, w := io.Pipe()
|
||||||
|
done := make(chan struct{})
|
||||||
|
fileStatus := NewCommitFileStatus()
|
||||||
|
go func() {
|
||||||
|
scanner := bufio.NewScanner(stdout)
|
||||||
|
for scanner.Scan() {
|
||||||
|
fields := strings.Fields(scanner.Text())
|
||||||
|
if len(fields) < 2 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
switch fields[0][0] {
|
||||||
|
case 'A':
|
||||||
|
fileStatus.Added = append(fileStatus.Added, fields[1])
|
||||||
|
case 'D':
|
||||||
|
fileStatus.Removed = append(fileStatus.Removed, fields[1])
|
||||||
|
case 'M':
|
||||||
|
fileStatus.Modified = append(fileStatus.Modified, fields[1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
done <- struct{}{}
|
||||||
|
}()
|
||||||
|
|
||||||
|
stderr := new(bytes.Buffer)
|
||||||
|
err := NewCommand("show", "--name-status", "--pretty=format:''", commitID).RunInDirPipeline(repoPath, w, stderr)
|
||||||
|
w.Close() // Close writer to exit parsing goroutine
|
||||||
|
if err != nil {
|
||||||
|
return nil, concatenateError(err, stderr.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
<-done
|
||||||
|
return fileStatus, nil
|
||||||
|
}
|
||||||
|
|
||||||
// GetFullCommitID returns full length (40) of commit ID by given short SHA in a repository.
|
// GetFullCommitID returns full length (40) of commit ID by given short SHA in a repository.
|
||||||
func GetFullCommitID(repoPath, shortID string) (string, error) {
|
func GetFullCommitID(repoPath, shortID string) (string, error) {
|
||||||
if len(shortID) >= 40 {
|
if len(shortID) >= 40 {
|
||||||
|
|||||||
20
vendor/code.gitea.io/git/commit_info.go
generated
vendored
20
vendor/code.gitea.io/git/commit_info.go
generated
vendored
@@ -72,13 +72,20 @@ func (state *getCommitsInfoState) getTargetedEntryPath() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// repeatedly perform targeted searches for unpopulated entries
|
// repeatedly perform targeted searches for unpopulated entries
|
||||||
func targetedSearch(state *getCommitsInfoState, done chan error) {
|
func targetedSearch(state *getCommitsInfoState, done chan error, cache LastCommitCache) {
|
||||||
for {
|
for {
|
||||||
entryPath := state.getTargetedEntryPath()
|
entryPath := state.getTargetedEntryPath()
|
||||||
if len(entryPath) == 0 {
|
if len(entryPath) == 0 {
|
||||||
done <- nil
|
done <- nil
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if cache != nil {
|
||||||
|
commit, err := cache.Get(state.headCommit.repo.Path, state.headCommit.ID.String(), entryPath)
|
||||||
|
if err == nil && commit != nil {
|
||||||
|
state.update(entryPath, commit)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
command := NewCommand("rev-list", "-1", state.headCommit.ID.String(), "--", entryPath)
|
command := NewCommand("rev-list", "-1", state.headCommit.ID.String(), "--", entryPath)
|
||||||
output, err := command.RunInDir(state.headCommit.repo.Path)
|
output, err := command.RunInDir(state.headCommit.repo.Path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -96,6 +103,9 @@ func targetedSearch(state *getCommitsInfoState, done chan error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
state.update(entryPath, commit)
|
state.update(entryPath, commit)
|
||||||
|
if cache != nil {
|
||||||
|
cache.Put(state.headCommit.repo.Path, state.headCommit.ID.String(), entryPath, commit)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,9 +128,9 @@ func initGetCommitInfoState(entries Entries, headCommit *Commit, treePath string
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetCommitsInfo gets information of all commits that are corresponding to these entries
|
// GetCommitsInfo gets information of all commits that are corresponding to these entries
|
||||||
func (tes Entries) GetCommitsInfo(commit *Commit, treePath string) ([][]interface{}, error) {
|
func (tes Entries) GetCommitsInfo(commit *Commit, treePath string, cache LastCommitCache) ([][]interface{}, error) {
|
||||||
state := initGetCommitInfoState(tes, commit, treePath)
|
state := initGetCommitInfoState(tes, commit, treePath)
|
||||||
if err := getCommitsInfo(state); err != nil {
|
if err := getCommitsInfo(state, cache); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if len(state.commits) < len(state.entryPaths) {
|
if len(state.commits) < len(state.entryPaths) {
|
||||||
@@ -188,7 +198,7 @@ func (state *getCommitsInfoState) update(entryPath string, commit *Commit) bool
|
|||||||
|
|
||||||
const getCommitsInfoPretty = "--pretty=format:%H %ct %s"
|
const getCommitsInfoPretty = "--pretty=format:%H %ct %s"
|
||||||
|
|
||||||
func getCommitsInfo(state *getCommitsInfoState) error {
|
func getCommitsInfo(state *getCommitsInfoState, cache LastCommitCache) error {
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Minute)
|
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Minute)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
@@ -215,7 +225,7 @@ func getCommitsInfo(state *getCommitsInfoState) error {
|
|||||||
numThreads := runtime.NumCPU()
|
numThreads := runtime.NumCPU()
|
||||||
done := make(chan error, numThreads)
|
done := make(chan error, numThreads)
|
||||||
for i := 0; i < numThreads; i++ {
|
for i := 0; i < numThreads; i++ {
|
||||||
go targetedSearch(state, done)
|
go targetedSearch(state, done, cache)
|
||||||
}
|
}
|
||||||
|
|
||||||
scanner := bufio.NewScanner(readCloser)
|
scanner := bufio.NewScanner(readCloser)
|
||||||
|
|||||||
31
vendor/code.gitea.io/git/repo_commit.go
generated
vendored
31
vendor/code.gitea.io/git/repo_commit.go
generated
vendored
@@ -10,7 +10,7 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/mcuadros/go-version"
|
version "github.com/mcuadros/go-version"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetRefCommitID returns the last commit ID string of given reference (branch or tag).
|
// GetRefCommitID returns the last commit ID string of given reference (branch or tag).
|
||||||
@@ -32,7 +32,14 @@ func (repo *Repository) GetBranchCommitID(name string) (string, error) {
|
|||||||
|
|
||||||
// GetTagCommitID returns last commit ID string of given tag.
|
// GetTagCommitID returns last commit ID string of given tag.
|
||||||
func (repo *Repository) GetTagCommitID(name string) (string, error) {
|
func (repo *Repository) GetTagCommitID(name string) (string, error) {
|
||||||
return repo.GetRefCommitID(TagPrefix + name)
|
stdout, err := NewCommand("rev-list", "-n", "1", name).RunInDir(repo.Path)
|
||||||
|
if err != nil {
|
||||||
|
if strings.Contains(err.Error(), "unknown revision or path") {
|
||||||
|
return "", ErrNotExist{name, ""}
|
||||||
|
}
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return strings.TrimSpace(stdout), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseCommitData parses commit information from the (uncompressed) raw
|
// parseCommitData parses commit information from the (uncompressed) raw
|
||||||
@@ -94,7 +101,11 @@ l:
|
|||||||
sig, err := newGPGSignatureFromCommitline(data, (nextline+1)+sigindex, true)
|
sig, err := newGPGSignatureFromCommitline(data, (nextline+1)+sigindex, true)
|
||||||
if err == nil && sig != nil {
|
if err == nil && sig != nil {
|
||||||
// remove signature from commit message
|
// remove signature from commit message
|
||||||
cm = cm[:sigindex-1]
|
if sigindex == 0 {
|
||||||
|
cm = ""
|
||||||
|
} else {
|
||||||
|
cm = cm[:sigindex-1]
|
||||||
|
}
|
||||||
commit.Signature = sig
|
commit.Signature = sig
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -130,6 +141,14 @@ func (repo *Repository) getCommit(id SHA1) (*Commit, error) {
|
|||||||
commit.repo = repo
|
commit.repo = repo
|
||||||
commit.ID = id
|
commit.ID = id
|
||||||
|
|
||||||
|
data, err = NewCommand("name-rev", id.String()).RunInDirBytes(repo.Path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// name-rev commitID ouput will be "COMMIT_ID master" or "COMMIT_ID master~12"
|
||||||
|
commit.Branch = strings.Split(strings.Split(string(data), " ")[1], "~")[0]
|
||||||
|
|
||||||
repo.commitCache.Set(id.String(), commit)
|
repo.commitCache.Set(id.String(), commit)
|
||||||
return commit, nil
|
return commit, nil
|
||||||
}
|
}
|
||||||
@@ -138,10 +157,14 @@ func (repo *Repository) getCommit(id SHA1) (*Commit, error) {
|
|||||||
func (repo *Repository) GetCommit(commitID string) (*Commit, error) {
|
func (repo *Repository) GetCommit(commitID string) (*Commit, error) {
|
||||||
if len(commitID) != 40 {
|
if len(commitID) != 40 {
|
||||||
var err error
|
var err error
|
||||||
commitID, err = NewCommand("rev-parse", commitID).RunInDir(repo.Path)
|
actualCommitID, err := NewCommand("rev-parse", commitID).RunInDir(repo.Path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if strings.Contains(err.Error(), "unknown revision or path") {
|
||||||
|
return nil, ErrNotExist{commitID, ""}
|
||||||
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
commitID = actualCommitID
|
||||||
}
|
}
|
||||||
id, err := NewIDFromString(commitID)
|
id, err := NewIDFromString(commitID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
20
vendor/code.gitea.io/git/repo_tag.go
generated
vendored
20
vendor/code.gitea.io/git/repo_tag.go
generated
vendored
@@ -76,12 +76,12 @@ func (repo *Repository) getTag(id SHA1) (*Tag, error) {
|
|||||||
|
|
||||||
// GetTag returns a Git tag by given name.
|
// GetTag returns a Git tag by given name.
|
||||||
func (repo *Repository) GetTag(name string) (*Tag, error) {
|
func (repo *Repository) GetTag(name string) (*Tag, error) {
|
||||||
stdout, err := NewCommand("show-ref", "--tags", name).RunInDir(repo.Path)
|
idStr, err := repo.GetTagCommitID(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
id, err := NewIDFromString(strings.Split(stdout, " ")[0])
|
id, err := NewIDFromString(idStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -103,26 +103,18 @@ func (repo *Repository) GetTagInfos() ([]*Tag, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tagNames := strings.Split(stdout, "\n")
|
tagNames := strings.Split(stdout, "\n")
|
||||||
var tags []*Tag
|
var tags = make([]*Tag, 0, len(tagNames))
|
||||||
for _, tagName := range tagNames {
|
for _, tagName := range tagNames {
|
||||||
tagName = strings.TrimSpace(tagName)
|
tagName = strings.TrimSpace(tagName)
|
||||||
if len(tagName) == 0 {
|
if len(tagName) == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
commitID, err := NewCommand("rev-parse", tagName).RunInDir(repo.Path)
|
|
||||||
|
tag, err := repo.GetTag(tagName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
commit, err := repo.GetCommit(commitID)
|
tags = append(tags, tag)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
tags = append(tags, &Tag{
|
|
||||||
Name: tagName,
|
|
||||||
Message: commit.Message(),
|
|
||||||
Object: commit.ID,
|
|
||||||
Tagger: commit.Author,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
sortTagsByTime(tags)
|
sortTagsByTime(tags)
|
||||||
return tags, nil
|
return tags, nil
|
||||||
|
|||||||
16
vendor/code.gitea.io/git/submodule.go
generated
vendored
16
vendor/code.gitea.io/git/submodule.go
generated
vendored
@@ -29,13 +29,12 @@ func NewSubModuleFile(c *Commit, refURL, refID string) *SubModuleFile {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// RefURL guesses and returns reference URL.
|
func getRefURL(refURL, urlPrefix, parentPath string) string {
|
||||||
func (sf *SubModuleFile) RefURL(urlPrefix string, parentPath string) string {
|
if refURL == "" {
|
||||||
if sf.refURL == "" {
|
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
url := strings.TrimSuffix(sf.refURL, ".git")
|
url := strings.TrimSuffix(refURL, ".git")
|
||||||
|
|
||||||
// git://xxx/user/repo
|
// git://xxx/user/repo
|
||||||
if strings.HasPrefix(url, "git://") {
|
if strings.HasPrefix(url, "git://") {
|
||||||
@@ -67,12 +66,21 @@ func (sf *SubModuleFile) RefURL(urlPrefix string, parentPath string) string {
|
|||||||
if strings.Contains(urlPrefix, url[i+1:j]) {
|
if strings.Contains(urlPrefix, url[i+1:j]) {
|
||||||
return urlPrefix + url[j+1:]
|
return urlPrefix + url[j+1:]
|
||||||
}
|
}
|
||||||
|
if strings.HasPrefix(url, "ssh://") || strings.HasPrefix(url, "git+ssh://") {
|
||||||
|
k := strings.Index(url[j+1:], "/")
|
||||||
|
return "http://" + url[i+1:j] + "/" + url[j+1:][k+1:]
|
||||||
|
}
|
||||||
return "http://" + url[i+1:j] + "/" + url[j+1:]
|
return "http://" + url[i+1:j] + "/" + url[j+1:]
|
||||||
}
|
}
|
||||||
|
|
||||||
return url
|
return url
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RefURL guesses and returns reference URL.
|
||||||
|
func (sf *SubModuleFile) RefURL(urlPrefix string, parentPath string) string {
|
||||||
|
return getRefURL(sf.refURL, urlPrefix, parentPath)
|
||||||
|
}
|
||||||
|
|
||||||
// RefID returns reference ID.
|
// RefID returns reference ID.
|
||||||
func (sf *SubModuleFile) RefID() string {
|
func (sf *SubModuleFile) RefID() string {
|
||||||
return sf.refID
|
return sf.refID
|
||||||
|
|||||||
22
vendor/code.gitea.io/git/tree.go
generated
vendored
22
vendor/code.gitea.io/git/tree.go
generated
vendored
@@ -18,6 +18,9 @@ type Tree struct {
|
|||||||
|
|
||||||
entries Entries
|
entries Entries
|
||||||
entriesParsed bool
|
entriesParsed bool
|
||||||
|
|
||||||
|
entriesRecursive Entries
|
||||||
|
entriesRecursiveParsed bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewTree create a new tree according the repository and commit id
|
// NewTree create a new tree according the repository and commit id
|
||||||
@@ -67,20 +70,29 @@ func (t *Tree) ListEntries() (Entries, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
t.entries, err = parseTreeEntries(stdout, t)
|
t.entries, err = parseTreeEntries(stdout, t)
|
||||||
|
if err == nil {
|
||||||
|
t.entriesParsed = true
|
||||||
|
}
|
||||||
|
|
||||||
return t.entries, err
|
return t.entries, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListEntriesRecursive returns all entries of current tree recursively including all subtrees
|
// ListEntriesRecursive returns all entries of current tree recursively including all subtrees
|
||||||
func (t *Tree) ListEntriesRecursive() (Entries, error) {
|
func (t *Tree) ListEntriesRecursive() (Entries, error) {
|
||||||
if t.entriesParsed {
|
if t.entriesRecursiveParsed {
|
||||||
return t.entries, nil
|
return t.entriesRecursive, nil
|
||||||
}
|
}
|
||||||
stdout, err := NewCommand("ls-tree", "-t", "-r", t.ID.String()).RunInDirBytes(t.repo.Path)
|
stdout, err := NewCommand("ls-tree", "-t", "-r", t.ID.String()).RunInDirBytes(t.repo.Path)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
t.entries, err = parseTreeEntries(stdout, t)
|
|
||||||
return t.entries, err
|
t.entriesRecursive, err = parseTreeEntries(stdout, t)
|
||||||
|
if err == nil {
|
||||||
|
t.entriesRecursiveParsed = true
|
||||||
|
}
|
||||||
|
|
||||||
|
return t.entriesRecursive, err
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user