Skip to content

Commit e156a9b

Browse files
authored
Merge branch 'main' into add_some_headings
2 parents 1acacd8 + 00f695d commit e156a9b

File tree

10 files changed

+108
-112
lines changed

10 files changed

+108
-112
lines changed

modules/git/tree_entry.go

+9
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,15 @@ func (te *TreeEntry) FollowLinks() (*TreeEntry, error) {
101101
return entry, nil
102102
}
103103

104+
// returns the subtree, or nil if this is not a tree
105+
func (te *TreeEntry) Tree() *Tree {
106+
t, err := te.ptree.repo.getTree(te.ID)
107+
if err != nil {
108+
return nil
109+
}
110+
return t
111+
}
112+
104113
// GetSubJumpablePathName return the full path of subdirectory jumpable ( contains only one directory )
105114
func (te *TreeEntry) GetSubJumpablePathName() string {
106115
if te.IsSubModule() || !te.IsDir() {

modules/lfs/endpoint.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@
44
package lfs
55

66
import (
7-
"fmt"
87
"net/url"
98
"os"
109
"path"
1110
"path/filepath"
1211
"strings"
1312

1413
"code.gitea.io/gitea/modules/log"
14+
"code.gitea.io/gitea/modules/util"
1515
)
1616

1717
// DetermineEndpoint determines an endpoint from the clone url or uses the specified LFS url.
@@ -95,7 +95,7 @@ func endpointFromLocalPath(path string) *url.URL {
9595
return nil
9696
}
9797

98-
path = fmt.Sprintf("file://%s%s", slash, filepath.ToSlash(path))
98+
path = "file://" + slash + util.PathEscapeSegments(filepath.ToSlash(path))
9999

100100
u, _ := url.Parse(path)
101101

routers/web/repo/view.go

+69-98
Original file line numberDiff line numberDiff line change
@@ -56,35 +56,54 @@ type namedBlob struct {
5656
blob *git.Blob
5757
}
5858

59+
// locate a README for a tree in one of the supported paths.
60+
//
61+
// entries is passed to reduce calls to ListEntries(), so
62+
// this has precondition:
63+
//
64+
// entries == ctx.Repo.Commit.SubTree(ctx.Repo.TreePath).ListEntries()
65+
//
5966
// FIXME: There has to be a more efficient way of doing this
60-
func getReadmeFileFromPath(ctx *context.Context, commit *git.Commit, treePath string) (*namedBlob, error) {
61-
tree, err := commit.SubTree(treePath)
62-
if err != nil {
63-
return nil, err
64-
}
65-
66-
entries, err := tree.ListEntries()
67-
if err != nil {
68-
return nil, err
69-
}
70-
67+
func findReadmeFileInEntries(ctx *context.Context, entries []*git.TreeEntry) (*namedBlob, error) {
7168
// Create a list of extensions in priority order
7269
// 1. Markdown files - with and without localisation - e.g. README.en-us.md or README.md
7370
// 2. Txt files - e.g. README.txt
7471
// 3. No extension - e.g. README
7572
exts := append(localizedExtensions(".md", ctx.Language()), ".txt", "") // sorted by priority
7673
extCount := len(exts)
7774
readmeFiles := make([]*namedBlob, extCount+1)
75+
76+
docsEntries := make([]*git.TreeEntry, 3) // (one of docs/, .gitea/ or .github/)
7877
for _, entry := range entries {
7978
if entry.IsDir() {
79+
// as a special case for the top-level repo introduction README,
80+
// fall back to subfolders, looking for e.g. docs/README.md, .gitea/README.zh-CN.txt, .github/README.txt, ...
81+
// (note that docsEntries is ignored unless we are at the root)
82+
lowerName := strings.ToLower(entry.Name())
83+
switch lowerName {
84+
case "docs":
85+
if entry.Name() == "docs" || docsEntries[0] == nil {
86+
docsEntries[0] = entry
87+
}
88+
case ".gitea":
89+
if entry.Name() == ".gitea" || docsEntries[1] == nil {
90+
docsEntries[1] = entry
91+
}
92+
case ".github":
93+
if entry.Name() == ".github" || docsEntries[2] == nil {
94+
docsEntries[2] = entry
95+
}
96+
}
8097
continue
8198
}
8299
if i, ok := markup.IsReadmeFileExtension(entry.Name(), exts...); ok {
100+
log.Debug("Potential readme file: %s", entry.Name())
83101
if readmeFiles[i] == nil || base.NaturalSortLess(readmeFiles[i].name, entry.Blob().Name()) {
84102
name := entry.Name()
85103
isSymlink := entry.IsLink()
86104
target := entry
87105
if isSymlink {
106+
var err error
88107
target, err = entry.FollowLinks()
89108
if err != nil && !git.IsErrBadLink(err) {
90109
return nil, err
@@ -107,6 +126,33 @@ func getReadmeFileFromPath(ctx *context.Context, commit *git.Commit, treePath st
107126
break
108127
}
109128
}
129+
130+
if ctx.Repo.TreePath == "" && readmeFile == nil {
131+
for _, subTreeEntry := range docsEntries {
132+
if subTreeEntry == nil {
133+
continue
134+
}
135+
subTree := subTreeEntry.Tree()
136+
if subTree == nil {
137+
// this should be impossible; if subTreeEntry exists so should this.
138+
continue
139+
}
140+
var err error
141+
childEntries, err := subTree.ListEntries()
142+
if err != nil {
143+
return nil, err
144+
}
145+
readmeFile, err = findReadmeFileInEntries(ctx, childEntries)
146+
if err != nil && !git.IsErrNotExist(err) {
147+
return nil, err
148+
}
149+
if readmeFile != nil {
150+
readmeFile.name = subTreeEntry.Name() + "/" + readmeFile.name
151+
break
152+
}
153+
}
154+
}
155+
110156
return readmeFile, nil
111157
}
112158

@@ -127,12 +173,20 @@ func renderDirectory(ctx *context.Context, treeLink string) {
127173
ctx.Data["CanUploadFile"] = setting.Repository.Upload.Enabled && !ctx.Repo.Repository.IsArchived
128174
}
129175

130-
readmeFile, readmeTreelink := findReadmeFile(ctx, entries, treeLink)
131-
if ctx.Written() || readmeFile == nil {
176+
if ctx.Written() {
177+
return
178+
}
179+
180+
readmeFile, err := findReadmeFileInEntries(ctx, entries)
181+
if err != nil {
182+
ctx.ServerError("findReadmeFileInEntries", err)
183+
return
184+
}
185+
if readmeFile == nil {
132186
return
133187
}
134188

135-
renderReadmeFile(ctx, readmeFile, readmeTreelink)
189+
renderReadmeFile(ctx, readmeFile, treeLink)
136190
}
137191

138192
// localizedExtensions prepends the provided language code with and without a
@@ -157,89 +211,6 @@ func localizedExtensions(ext, languageCode string) (localizedExts []string) {
157211
return []string{lowerLangCode + ext, ext}
158212
}
159213

160-
func findReadmeFile(ctx *context.Context, entries git.Entries, treeLink string) (*namedBlob, string) {
161-
// Create a list of extensions in priority order
162-
// 1. Markdown files - with and without localisation - e.g. README.en-us.md or README.md
163-
// 2. Txt files - e.g. README.txt
164-
// 3. No extension - e.g. README
165-
exts := append(localizedExtensions(".md", ctx.Language()), ".txt", "") // sorted by priority
166-
extCount := len(exts)
167-
readmeFiles := make([]*namedBlob, extCount+1)
168-
169-
docsEntries := make([]*git.TreeEntry, 3) // (one of docs/, .gitea/ or .github/)
170-
for _, entry := range entries {
171-
if entry.IsDir() {
172-
lowerName := strings.ToLower(entry.Name())
173-
switch lowerName {
174-
case "docs":
175-
if entry.Name() == "docs" || docsEntries[0] == nil {
176-
docsEntries[0] = entry
177-
}
178-
case ".gitea":
179-
if entry.Name() == ".gitea" || docsEntries[1] == nil {
180-
docsEntries[1] = entry
181-
}
182-
case ".github":
183-
if entry.Name() == ".github" || docsEntries[2] == nil {
184-
docsEntries[2] = entry
185-
}
186-
}
187-
continue
188-
}
189-
190-
if i, ok := markup.IsReadmeFileExtension(entry.Name(), exts...); ok {
191-
log.Debug("Potential readme file: %s", entry.Name())
192-
name := entry.Name()
193-
isSymlink := entry.IsLink()
194-
target := entry
195-
if isSymlink {
196-
var err error
197-
target, err = entry.FollowLinks()
198-
if err != nil && !git.IsErrBadLink(err) {
199-
ctx.ServerError("FollowLinks", err)
200-
return nil, ""
201-
}
202-
}
203-
if target != nil && (target.IsExecutable() || target.IsRegular()) {
204-
readmeFiles[i] = &namedBlob{
205-
name,
206-
isSymlink,
207-
target.Blob(),
208-
}
209-
}
210-
}
211-
}
212-
213-
var readmeFile *namedBlob
214-
readmeTreelink := treeLink
215-
for _, f := range readmeFiles {
216-
if f != nil {
217-
readmeFile = f
218-
break
219-
}
220-
}
221-
222-
if ctx.Repo.TreePath == "" && readmeFile == nil {
223-
for _, entry := range docsEntries {
224-
if entry == nil {
225-
continue
226-
}
227-
var err error
228-
readmeFile, err = getReadmeFileFromPath(ctx, ctx.Repo.Commit, entry.GetSubJumpablePathName())
229-
if err != nil {
230-
ctx.ServerError("getReadmeFileFromPath", err)
231-
return nil, ""
232-
}
233-
if readmeFile != nil {
234-
readmeFile.name = entry.Name() + "/" + readmeFile.name
235-
readmeTreelink = treeLink + "/" + util.PathEscapeSegments(entry.GetSubJumpablePathName())
236-
break
237-
}
238-
}
239-
}
240-
return readmeFile, readmeTreelink
241-
}
242-
243214
type fileInfo struct {
244215
isTextFile bool
245216
isLFSFile bool
@@ -342,7 +313,7 @@ func renderReadmeFile(ctx *context.Context, readmeFile *namedBlob, readmeTreelin
342313
ctx.Data["EscapeStatus"], ctx.Data["FileContent"], err = markupRender(ctx, &markup.RenderContext{
343314
Ctx: ctx,
344315
RelativePath: path.Join(ctx.Repo.TreePath, readmeFile.name), // ctx.Repo.TreePath is the directory not the Readme so we must append the Readme filename (and path).
345-
URLPrefix: readmeTreelink,
316+
URLPrefix: path.Dir(readmeTreelink),
346317
Metas: ctx.Repo.Repository.ComposeDocumentMetas(),
347318
GitRepo: ctx.Repo.GitRepo,
348319
}, rd)

services/repository/files/content.go

+5-4
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"code.gitea.io/gitea/modules/git"
1616
"code.gitea.io/gitea/modules/setting"
1717
api "code.gitea.io/gitea/modules/structs"
18+
"code.gitea.io/gitea/modules/util"
1819
)
1920

2021
// ContentType repo content type
@@ -158,7 +159,7 @@ func GetContents(ctx context.Context, repo *repo_model.Repository, treePath, ref
158159
return nil, fmt.Errorf("no commit found for the ref [ref: %s]", ref)
159160
}
160161

161-
selfURL, err := url.Parse(fmt.Sprintf("%s/contents/%s?ref=%s", repo.APIURL(), treePath, origRef))
162+
selfURL, err := url.Parse(repo.APIURL() + "/contents/" + util.PathEscapeSegments(treePath) + "?ref=" + url.QueryEscape(origRef))
162163
if err != nil {
163164
return nil, err
164165
}
@@ -217,23 +218,23 @@ func GetContents(ctx context.Context, repo *repo_model.Repository, treePath, ref
217218
}
218219
// Handle links
219220
if entry.IsRegular() || entry.IsLink() {
220-
downloadURL, err := url.Parse(fmt.Sprintf("%s/raw/%s/%s/%s", repo.HTMLURL(), refType, ref, treePath))
221+
downloadURL, err := url.Parse(repo.HTMLURL() + "/raw/" + url.PathEscape(string(refType)) + "/" + util.PathEscapeSegments(ref) + "/" + util.PathEscapeSegments(treePath))
221222
if err != nil {
222223
return nil, err
223224
}
224225
downloadURLString := downloadURL.String()
225226
contentsResponse.DownloadURL = &downloadURLString
226227
}
227228
if !entry.IsSubModule() {
228-
htmlURL, err := url.Parse(fmt.Sprintf("%s/src/%s/%s/%s", repo.HTMLURL(), refType, ref, treePath))
229+
htmlURL, err := url.Parse(repo.HTMLURL() + "/src/" + url.PathEscape(string(refType)) + "/" + util.PathEscapeSegments(ref) + "/" + util.PathEscapeSegments(treePath))
229230
if err != nil {
230231
return nil, err
231232
}
232233
htmlURLString := htmlURL.String()
233234
contentsResponse.HTMLURL = &htmlURLString
234235
contentsResponse.Links.HTMLURL = &htmlURLString
235236

236-
gitURL, err := url.Parse(fmt.Sprintf("%s/git/blobs/%s", repo.APIURL(), entry.ID.String()))
237+
gitURL, err := url.Parse(repo.APIURL() + "/git/blobs/" + url.PathEscape(entry.ID.String()))
237238
if err != nil {
238239
return nil, err
239240
}

templates/repo/issue/milestones.tmpl

+2-2
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,9 @@
6262
{{range .Milestones}}
6363
<li class="item">
6464
<div class="df ac sb">
65-
<h2 class="df ac m-0 fw">
65+
<h3 class="df ac m-0 fw">
6666
{{svg "octicon-milestone" 16 "mr-3"}}<a class="muted" href="{{$.RepoLink}}/milestone/{{.ID}}">{{.Name}}</a>
67-
</h2>
67+
</h3>
6868
<div class="df ac">
6969
<span class="mr-3">{{.Completeness}}%</span>
7070
<progress value="{{.Completeness}}" max="100"></progress>

templates/user/dashboard/milestones.tmpl

+2-2
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,10 @@
8181
{{range .Milestones}}
8282
<li class="item">
8383
<div class="df ac sb">
84-
<h2 class="df ac m-0 fw">
84+
<h3 class="df ac m-0 fw">
8585
<span class="ui large label">{{.Repo.FullName}}</span>
8686
{{svg "octicon-milestone" 16 "mr-3"}}<a class="muted" href="{{.Repo.Link}}/milestone/{{.ID}}">{{.Name}}</a>
87-
</h2>
87+
</h3>
8888
<div class="df ac">
8989
<span class="mr-3">{{.Completeness}}%</span>
9090
<progress value="{{.Completeness}}" max="100"></progress>

web_src/js/components/DiffFileTreeItem.vue

+5-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
/>
1111
<a
1212
v-if="item.isFile"
13-
class="file ellipsis"
13+
class="file ellipsis muted"
1414
:href="item.isFile ? '#diff-' + item.file.NameHash : ''"
1515
>{{ item.name }}</a>
1616
<SvgIcon
@@ -63,7 +63,7 @@ export default {
6363
if (itemIsFile) {
6464
return;
6565
}
66-
this.$set(this, 'collapsed', !this.collapsed);
66+
this.collapsed = !this.collapsed;
6767
},
6868
getIconForDiffType(pType) {
6969
const diffTypes = {
@@ -83,6 +83,7 @@ export default {
8383
span.svg-icon.status {
8484
float: right;
8585
}
86+
8687
span.svg-icon.file {
8788
color: var(--color-secondary-dark-7);
8889
}
@@ -122,6 +123,8 @@ span.svg-icon.octicon-diff-renamed {
122123
div.directory {
123124
display: grid;
124125
grid-template-columns: 18px 20px auto;
126+
user-select: none;
127+
cursor: pointer;
125128
}
126129
127130
div.directory:hover {

web_src/less/_base.less

-1
Original file line numberDiff line numberDiff line change
@@ -1803,7 +1803,6 @@ footer {
18031803
}
18041804
}
18051805

1806-
/* TODO: remove in favor of .hidden helper */
18071806
.hide {
18081807
display: none;
18091808

web_src/less/_repository.less

+14
Original file line numberDiff line numberDiff line change
@@ -1614,6 +1614,20 @@
16141614
margin-right: .25rem;
16151615
}
16161616

1617+
// Because the translations contain the <strong> we need to style with nth-of-type
1618+
1619+
.diff-detail-stats strong:nth-of-type(1) {
1620+
color: var(--color-yellow);
1621+
}
1622+
1623+
.diff-detail-stats strong:nth-of-type(2) {
1624+
color: var(--color-green);
1625+
}
1626+
1627+
.diff-detail-stats strong:nth-of-type(3) {
1628+
color: var(--color-red);
1629+
}
1630+
16171631
.diff-detail-stats {
16181632
@media (max-width: 480px) {
16191633
font-size: 0;

0 commit comments

Comments
 (0)