Compare commits

...

5 Commits

Author SHA1 Message Date
Giteabot
f4512426a1 Fix code tag style problem and LFS view bug (#35628) (#35636)
Backport #35628 by lutinglt

Signed-off-by: 鲁汀 <131967983+lutinglt@users.noreply.github.com>
Co-authored-by: 鲁汀 <131967983+lutinglt@users.noreply.github.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2025-10-11 20:25:03 +00:00
Giteabot
a3458c669a The status icon of the Action step is consistent with GitHub (#35618) (#35621)
Backport #35618 by @lutinglt

#35616
Before:
running:
<img width="45" height="34" alt="image"
src="https://github.com/user-attachments/assets/e2508f98-2f1f-4b7e-a80c-30b406f42531"
/>
waiting:
<img width="44" height="33" alt="image"
src="https://github.com/user-attachments/assets/e7c8164e-fdc3-4546-b088-31166544edb0"
/>

---
After:
running:
<img width="49" height="43" alt="image"
src="https://github.com/user-attachments/assets/b5a9b245-a995-458a-af23-d1723daa3692"
/>
waiting:
<img width="42" height="44" alt="image"
src="https://github.com/user-attachments/assets/ff72551e-cfb5-4665-af52-938ef0cf8f1c"
/>

`gitea-running.svg` is not an icon from the @ primer/octicon library,
extracted from the Github page. Github did not assign a clear class name
to this icon

Signed-off-by: 鲁汀 <131967983+lutinglt@users.noreply.github.com>
Co-authored-by: 鲁汀 <131967983+lutinglt@users.noreply.github.com>
Co-authored-by: lutinglt <lutinglt@users.noreply.github.com>
2025-10-10 12:12:21 -07:00
Giteabot
609d88f029 Fix inputing review comment will remove reviewer (#35591) (#35615)
Backport #35591 by @lunny

Fix #34617

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2025-10-10 08:28:44 +00:00
Giteabot
3c78598217 Mock external service in hcaptcha TestCaptcha (#35604) (#35614)
Backport #35604 by silverwind

The test calls out to a web service which may be down or unreachable as
seen in the linked issue. It's better for tests to not have such
external dependencies to make them absolutely stable.

Fixes: https://github.com/go-gitea/gitea/issues/35571

Co-authored-by: silverwind <me@silverwind.io>
2025-10-10 04:49:20 +00:00
Giteabot
b7bb0fa538 Fix diffpatch API endpoint (#35610) (#35613)
Backport #35610 by @surya-purohit

Updates the swagger documentation for the `diffpatch` API endpoint.

The request body is corrected from the outdated `UpdateFileOptions` to
the current `ApplyDiffPatchOptions` to match the code implementation.

Closes [issue#35602](https://github.com/go-gitea/gitea/issues/35602)

---------

Co-authored-by: Surya Purohit <suryaprakash.sharma@sourcefuse.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2025-10-10 03:28:40 +00:00
24 changed files with 228 additions and 36 deletions

View File

@@ -173,7 +173,7 @@ func GetReviewsByIssueID(ctx context.Context, issueID int64) (latestReviews, mig
reviewersMap := make(map[int64][]*Review) // key is reviewer id
originalReviewersMap := make(map[int64][]*Review) // key is original author id
reviewTeamsMap := make(map[int64][]*Review) // key is reviewer team id
countedReivewTypes := []ReviewType{ReviewTypeApprove, ReviewTypeReject, ReviewTypeRequest}
countedReivewTypes := []ReviewType{ReviewTypeApprove, ReviewTypeReject, ReviewTypeRequest, ReviewTypeComment}
for _, review := range reviews {
if review.ReviewerTeamID == 0 && slices.Contains(countedReivewTypes, review.Type) && !review.Dismissed {
if review.OriginalAuthorID != 0 {

View File

@@ -122,6 +122,7 @@ func TestGetReviewersByIssueID(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 3})
user1 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
org3 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 3})
user4 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4})
@@ -129,6 +130,12 @@ func TestGetReviewersByIssueID(t *testing.T) {
expectedReviews := []*issues_model.Review{}
expectedReviews = append(expectedReviews,
&issues_model.Review{
ID: 5,
Reviewer: user1,
Type: issues_model.ReviewTypeComment,
UpdatedUnix: 946684810,
},
&issues_model.Review{
ID: 7,
Reviewer: org3,
@@ -167,8 +174,9 @@ func TestGetReviewersByIssueID(t *testing.T) {
for _, review := range allReviews {
assert.NoError(t, review.LoadReviewer(t.Context()))
}
if assert.Len(t, allReviews, 5) {
if assert.Len(t, allReviews, 6) {
for i, review := range allReviews {
assert.Equal(t, expectedReviews[i].ID, review.ID)
assert.Equal(t, expectedReviews[i].Reviewer, review.Reviewer)
assert.Equal(t, expectedReviews[i].Type, review.Type)
assert.Equal(t, expectedReviews[i].UpdatedUnix, review.UpdatedUnix)

View File

@@ -4,7 +4,10 @@
package hcaptcha
import (
"errors"
"io"
"net/http"
"net/url"
"os"
"strings"
"testing"
@@ -21,6 +24,33 @@ func TestMain(m *testing.M) {
os.Exit(m.Run())
}
type mockTransport struct{}
func (mockTransport) RoundTrip(req *http.Request) (*http.Response, error) {
if req.URL.String() != verifyURL {
return nil, errors.New("unsupported url")
}
body, err := io.ReadAll(req.Body)
if err != nil {
return nil, err
}
bodyValues, err := url.ParseQuery(string(body))
if err != nil {
return nil, err
}
var responseText string
if bodyValues.Get("response") == dummyToken {
responseText = `{"success":true,"credit":false,"hostname":"dummy-key-pass","challenge_ts":"2025-10-08T16:02:56.136Z"}`
} else {
responseText = `{"success":false,"error-codes":["invalid-input-response"]}`
}
return &http.Response{Request: req, Body: io.NopCloser(strings.NewReader(responseText))}, nil
}
func TestCaptcha(t *testing.T) {
tt := []struct {
Name string
@@ -54,7 +84,8 @@ func TestCaptcha(t *testing.T) {
for _, tc := range tt {
t.Run(tc.Name, func(t *testing.T) {
client, err := New(tc.Secret, WithHTTP(&http.Client{
Timeout: time.Second * 5,
Timeout: time.Second * 5,
Transport: mockTransport{},
}))
if err != nil {
// The only error that can be returned from creating a client

1
public/assets/img/svg/gitea-running.svg generated Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" class="svg gitea-running" width="16" height="16" aria-hidden="true"><path fill="none" stroke="currentColor" stroke-width="2" d="M3.05 3.05a7 7 0 1 1 9.9 9.9 7 7 0 0 1-9.9-9.9Z" opacity=".5"/><path fill="currentColor" fill-rule="evenodd" d="M8 4a4 4 0 1 0 0 8 4 4 0 0 0 0-8" clip-rule="evenodd"/><path fill="currentColor" d="M14 8a6 6 0 0 0-6-6V0a8 8 0 0 1 8 8z"/></svg>

After

Width:  |  Height:  |  Size: 429 B

View File

@@ -1423,6 +1423,7 @@ func Routes() *web.Router {
m.Get("/tags/{sha}", repo.GetAnnotatedTag)
m.Get("/notes/{sha}", repo.GetNote)
}, context.ReferencesGitRepo(true), reqRepoReader(unit.TypeCode))
m.Post("/diffpatch", mustEnableEditor, reqToken(), bind(api.ApplyDiffPatchFileOptions{}), repo.ReqChangeRepoFileOptionsAndCheck, repo.ApplyDiffPatch)
m.Group("/contents", func() {
m.Get("", repo.GetContentsList)
m.Get("/*", repo.GetContents)
@@ -1434,7 +1435,6 @@ func Routes() *web.Router {
m.Put("", bind(api.UpdateFileOptions{}), repo.ReqChangeRepoFileOptionsAndCheck, repo.UpdateFile)
m.Delete("", bind(api.DeleteFileOptions{}), repo.ReqChangeRepoFileOptionsAndCheck, repo.DeleteFile)
})
m.Post("/diffpatch", bind(api.ApplyDiffPatchFileOptions{}), repo.ReqChangeRepoFileOptionsAndCheck, repo.ApplyDiffPatch)
}, mustEnableEditor, reqToken())
}, reqRepoReader(unit.TypeCode), context.ReferencesGitRepo())
m.Group("/contents-ext", func() {

View File

@@ -36,7 +36,7 @@ func ApplyDiffPatch(ctx *context.APIContext) {
// in: body
// required: true
// schema:
// "$ref": "#/definitions/UpdateFileOptions"
// "$ref": "#/definitions/ApplyDiffPatchFileOptions"
// responses:
// "200":
// "$ref": "#/responses/FileResponse"

View File

@@ -121,6 +121,9 @@ type swaggerParameterBodies struct {
// in:body
GetFilesOptions api.GetFilesOptions
// in:body
ApplyDiffPatchFileOptions api.ApplyDiffPatchFileOptions
// in:body
ChangeFilesOptions api.ChangeFilesOptions

View File

@@ -270,8 +270,7 @@ func LFSFileGet(ctx *context.Context) {
// FIXME: there is no IsPlainText set, but template uses it
ctx.Data["IsTextFile"] = st.IsText()
ctx.Data["FileSize"] = meta.Size
// FIXME: the last field is the URL-base64-encoded filename, it should not be "direct"
ctx.Data["RawFileLink"] = fmt.Sprintf("%s%s/%s.git/info/lfs/objects/%s/%s", setting.AppURL, url.PathEscape(ctx.Repo.Repository.OwnerName), url.PathEscape(ctx.Repo.Repository.Name), url.PathEscape(meta.Oid), "direct")
ctx.Data["RawFileLink"] = fmt.Sprintf("%s/%s/%s.git/info/lfs/objects/%s", setting.AppSubURL, url.PathEscape(ctx.Repo.Repository.OwnerName), url.PathEscape(ctx.Repo.Repository.Name), url.PathEscape(meta.Oid))
switch {
case st.IsRepresentableAsText():
if meta.Size >= setting.UI.MaxDisplayFileSize {

View File

@@ -252,9 +252,9 @@
{{end}}
{{if .CacheConn}}
<dt>{{ctx.Locale.Tr "admin.config.cache_conn"}}</dt>
<dd><code>{{.CacheConn}}</code></dd>
<dd>{{.CacheConn}}</dd>
<dt>{{ctx.Locale.Tr "admin.config.cache_item_ttl"}}</dt>
<dd><code>{{.CacheItemTTL}}</code></dd>
<dd>{{.CacheItemTTL}}</dd>
{{end}}
<div class="divider"></div>
<dt class="tw-py-1 tw-flex tw-items-center">{{ctx.Locale.Tr "admin.config.cache_test"}}</dt>
@@ -275,7 +275,7 @@
<dt>{{ctx.Locale.Tr "admin.config.session_provider"}}</dt>
<dd>{{.SessionConfig.Provider}}</dd>
<dt>{{ctx.Locale.Tr "admin.config.provider_config"}}</dt>
<dd><code>{{if .SessionConfig.ProviderConfig}}{{.SessionConfig.ProviderConfig}}{{else}}-{{end}}</code></dd>
<dd>{{if .SessionConfig.ProviderConfig}}{{.SessionConfig.ProviderConfig}}{{else}}-{{end}}</dd>
<dt>{{ctx.Locale.Tr "admin.config.cookie_name"}}</dt>
<dd>{{.SessionConfig.CookieName}}</dd>
<dt>{{ctx.Locale.Tr "admin.config.gc_interval_time"}}</dt>
@@ -301,7 +301,7 @@
<dt>{{ctx.Locale.Tr "admin.config.git_max_diff_files"}}</dt>
<dd>{{.Git.MaxGitDiffFiles}}</dd>
<dt>{{ctx.Locale.Tr "admin.config.git_gc_args"}}</dt>
<dd><code>{{.Git.GCArgs}}</code></dd>
<dd>{{.Git.GCArgs}}</dd>
<div class="divider"></div>
@@ -330,7 +330,7 @@
{{if .Loggers.access.IsEnabled}}
<dt>{{ctx.Locale.Tr "admin.config.access_log_template"}}</dt>
<dd><code>{{$.AccessLogTemplate}}</code></dd>
<dd>{{$.AccessLogTemplate}}</dd>
{{end}}
{{range $loggerName, $loggerDetail := .Loggers}}

View File

@@ -46,8 +46,8 @@
<div class="item tw-flex tw-items-center">
<span class="icon tw-mr-4">{{svg "octicon-dot-fill" 16}}</span>
<div class="content tw-flex-1">
<div class="header"><code>{{.Function}}</code></div>
<div class="description"><code>{{.File}}:{{.Line}}</code></div>
<div class="header">{{.Function}}</div>
<div class="description">{{.File}}:{{.Line}}</div>
</div>
</div>
{{end}}

View File

@@ -2,7 +2,7 @@
{{if .Details}}
<details>
<summary>{{.Summary}}</summary>
<code>{{.Details | SanitizeHTML}}</code>
{{.Details | SanitizeHTML}}
</details>
{{else}}
<div>

View File

@@ -65,7 +65,9 @@
</div>
<div class="ui container project-description">
{{$.Project.RenderedContent}}
<div class="render-content markup">
{{$.Project.RenderedContent}}
</div>
<div class="divider"></div>
</div>

View File

@@ -12,11 +12,11 @@
{{else if eq .status "cancelled"}}
{{svg "octicon-stop" $size (printf "text grey %s" $className)}}
{{else if eq .status "waiting"}}
{{svg "octicon-clock" $size (printf "text yellow %s" $className)}}
{{svg "octicon-circle" $size (printf "text grey %s" $className)}}
{{else if eq .status "blocked"}}
{{svg "octicon-blocked" $size (printf "text yellow %s" $className)}}
{{else if eq .status "running"}}
{{svg "octicon-meter" $size (printf "text yellow circular-spin %s" $className)}}
{{svg "gitea-running" $size (printf "text yellow circular-spin %s" $className)}}
{{else}}{{/*failure, unknown*/}}
{{svg "octicon-x-circle-fill" $size (printf "text red %s" $className)}}
{{end}}

View File

@@ -39,7 +39,7 @@
<tbody>
<tr>
<td class="lines-num">{{.LineNums}}</td>
<td class="lines-code"><pre><code class="{{.HighlightClass}}"><ol>{{.FileContent}}</ol></code></pre></td>
<td class="lines-code"><pre>{{.FileContent}}</pre></td>
</tr>
</tbody>
</table>

View File

@@ -68,7 +68,7 @@
{{range $key, $val := .RequestInfo.Headers}}<strong>{{$key}}:</strong> {{$val}}
{{end}}</pre>
<h5>{{ctx.Locale.Tr "repo.settings.webhook.payload"}}</h5>
<pre class="webhook-info"><code class="json">{{or .RequestInfo.Body .PayloadContent}}</code></pre>
<pre class="webhook-info">{{or .RequestInfo.Body .PayloadContent}}</pre>
{{else}}
-
{{end}}
@@ -79,7 +79,7 @@
<pre class="webhook-info">{{range $key, $val := .ResponseInfo.Headers}}<strong>{{$key}}:</strong> {{$val}}
{{end}}</pre>
<h5>{{ctx.Locale.Tr "repo.settings.webhook.body"}}</h5>
<pre class="webhook-info"><code>{{.ResponseInfo.Body}}</code></pre>
<pre class="webhook-info">{{.ResponseInfo.Body}}</pre>
{{else}}
-
{{end}}

View File

@@ -7844,7 +7844,7 @@
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/UpdateFileOptions"
"$ref": "#/definitions/ApplyDiffPatchFileOptions"
}
}
],
@@ -21645,6 +21645,49 @@
},
"x-go-package": "code.gitea.io/gitea/modules/structs"
},
"ApplyDiffPatchFileOptions": {
"description": "ApplyDiffPatchFileOptions options for applying a diff patch\nNote: `author` and `committer` are optional (if only one is given, it will be used for the other, otherwise the authenticated user will be used)",
"type": "object",
"required": [
"content"
],
"properties": {
"author": {
"$ref": "#/definitions/Identity"
},
"branch": {
"description": "branch (optional) to base this file from. if not given, the default branch is used",
"type": "string",
"x-go-name": "BranchName"
},
"committer": {
"$ref": "#/definitions/Identity"
},
"content": {
"type": "string",
"x-go-name": "Content"
},
"dates": {
"$ref": "#/definitions/CommitDateOptions"
},
"message": {
"description": "message (optional) for the commit of this file. if not supplied, a default message will be used",
"type": "string",
"x-go-name": "Message"
},
"new_branch": {
"description": "new_branch (optional) will make a new branch from `branch` before creating the file",
"type": "string",
"x-go-name": "NewBranchName"
},
"signoff": {
"description": "Add a Signed-off-by trailer by the committer at the end of the commit log message.",
"type": "boolean",
"x-go-name": "Signoff"
}
},
"x-go-package": "code.gitea.io/gitea/modules/structs"
},
"Attachment": {
"description": "Attachment a generic attachment",
"type": "object",

View File

@@ -21,8 +21,8 @@
<label for="token">{{ctx.Locale.Tr "settings.gpg_token"}}</label>
<input readonly="" value="{{.TokenToSign}}">
<div class="help">
<p>{{ctx.Locale.Tr "settings.gpg_token_help"}}</p>
<p><code>{{printf `echo "%s" | gpg -a --default-key %s --detach-sig` .TokenToSign .PaddedKeyID}}</code></p>
{{ctx.Locale.Tr "settings.gpg_token_help"}}
<pre class="command-block">{{printf `echo "%s" | gpg -a --default-key %s --detach-sig` .TokenToSign .PaddedKeyID}}</pre>
</div>
</div>
<div class="field">
@@ -89,8 +89,8 @@
<label for="token">{{ctx.Locale.Tr "settings.gpg_token"}}</label>
<input readonly="" value="{{$.TokenToSign}}">
<div class="help">
<p>{{ctx.Locale.Tr "settings.gpg_token_help"}}</p>
<p><code>{{printf `echo "%s" | gpg -a --default-key %s --detach-sig` $.TokenToSign .PaddedKeyID}}</code></p>
{{ctx.Locale.Tr "settings.gpg_token_help"}}
<pre class="command-block">{{printf `echo "%s" | gpg -a --default-key %s --detach-sig` $.TokenToSign .PaddedKeyID}}</pre>
</div>
<br>
</div>

View File

@@ -77,16 +77,15 @@
<label for="token">{{ctx.Locale.Tr "settings.ssh_token"}}</label>
<input readonly="" value="{{$.TokenToSign}}">
<div class="help">
<p>{{ctx.Locale.Tr "settings.ssh_token_help"}}</p>
<p><code>echo -n '{{$.TokenToSign}}' | ssh-keygen -Y sign -n gitea -f /path_to_PrivateKey_or_RelatedPublicKey</code></p>
{{ctx.Locale.Tr "settings.ssh_token_help"}}
<pre class="command-block">echo -n '{{$.TokenToSign}}' | ssh-keygen -Y sign -n gitea -f /path_to_PrivateKey_or_RelatedPublicKey</pre>
<details>
<summary>Windows PowerShell</summary>
<p><code>cmd /c "&lt;NUL set /p=`"{{$.TokenToSign}}`"| ssh-keygen -Y sign -n gitea -f /path_to_PrivateKey_or_RelatedPublicKey"</code></p>
<pre class="command-block">cmd /c "&lt;NUL set /p=`"{{$.TokenToSign}}`"| ssh-keygen -Y sign -n gitea -f /path_to_PrivateKey_or_RelatedPublicKey"</pre>
</details>
<br>
<details>
<summary>Windows CMD</summary>
<p><code>set /p={{$.TokenToSign}}| ssh-keygen -Y sign -n gitea -f /path_to_PrivateKey_or_RelatedPublicKey</code></p>
<pre class="command-block">set /p={{$.TokenToSign}}| ssh-keygen -Y sign -n gitea -f /path_to_PrivateKey_or_RelatedPublicKey</pre>
</details>
</div>
<br>

View File

@@ -0,0 +1,89 @@
// Copyright 2025 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package integration
import (
"fmt"
"net/http"
"net/url"
"testing"
auth_model "code.gitea.io/gitea/models/auth"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
api "code.gitea.io/gitea/modules/structs"
"github.com/stretchr/testify/assert"
)
func getApplyDiffPatchFileOptions() *api.ApplyDiffPatchFileOptions {
return &api.ApplyDiffPatchFileOptions{
FileOptions: api.FileOptions{
BranchName: "master",
},
Content: `diff --git a/patch-file-1.txt b/patch-file-1.txt
new file mode 100644
index 0000000000..aaaaaaaaaa
--- /dev/null
+++ b/patch-file-1.txt
@@ -0,0 +1 @@
+File 1
`,
}
}
func TestAPIApplyDiffPatchFileOptions(t *testing.T) {
onGiteaRun(t, func(t *testing.T, u *url.URL) {
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) // owner of the repo1 & repo16
org3 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 3}) // owner of the repo3, is an org
user4 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4}) // owner of neither repos
repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) // public repo
repo3 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3}) // public repo
repo16 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 16}) // private repo
session2 := loginUser(t, user2.Name)
token2 := getTokenForLoggedInUser(t, session2, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
session4 := loginUser(t, user4.Name)
token4 := getTokenForLoggedInUser(t, session4, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
req := NewRequestWithJSON(t, "POST", "/api/v1/repos/user2/repo1/diffpatch", getApplyDiffPatchFileOptions()).AddTokenAuth(token2)
resp := MakeRequest(t, req, http.StatusCreated)
var fileResponse api.FileResponse
DecodeJSON(t, resp, &fileResponse)
assert.Nil(t, fileResponse.Content)
assert.NotEmpty(t, fileResponse.Commit.HTMLURL)
req = NewRequest(t, "GET", "/api/v1/repos/user2/repo1/raw/patch-file-1.txt")
resp = MakeRequest(t, req, http.StatusOK)
assert.Equal(t, "File 1\n", resp.Body.String())
// Test creating a file in repo1 by user4 who does not have write access
req = NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/repos/%s/%s/diffpatch", user2.Name, repo16.Name), getApplyDiffPatchFileOptions()).
AddTokenAuth(token4)
MakeRequest(t, req, http.StatusNotFound)
// Tests a repo with no token given so will fail
req = NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/repos/%s/%s/diffpatch", user2.Name, repo16.Name), getApplyDiffPatchFileOptions())
MakeRequest(t, req, http.StatusNotFound)
// Test using access token for a private repo that the user of the token owns
req = NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/repos/%s/%s/diffpatch", user2.Name, repo16.Name), getApplyDiffPatchFileOptions()).
AddTokenAuth(token2)
MakeRequest(t, req, http.StatusCreated)
// Test using org repo "org3/repo3" where user2 is a collaborator
req = NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/repos/%s/%s/diffpatch", org3.Name, repo3.Name), getApplyDiffPatchFileOptions()).
AddTokenAuth(token2)
MakeRequest(t, req, http.StatusCreated)
// Test using org repo "org3/repo3" with no user token
req = NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/repos/%s/%s/diffpatch", org3.Name, repo3.Name), getApplyDiffPatchFileOptions())
MakeRequest(t, req, http.StatusNotFound)
// Test using repo "user2/repo1" where user4 is a NOT collaborator
req = NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/repos/%s/%s/diffpatch", user2.Name, repo1.Name), getApplyDiffPatchFileOptions()).
AddTokenAuth(token4)
MakeRequest(t, req, http.StatusForbidden)
})
}

View File

@@ -101,11 +101,13 @@ samp,
font-size: 0.95em; /* compensate for monospace fonts being usually slightly larger */
}
code {
/* there are many <code> blocks in non-markup(.markup code) / non-code-diff(code.code-inner) containers (for example: translation strings, etc),
so we need to make <code> have default global styles, ".markup code" has its own styles and doesn't conflict, but `.code-inner` is special.
TODO: in the future, we should use `div` instead of `code` for `.code-inner` because it is a container for highlighted code line */
code:not(.code-inner) {
padding: 1px 4px;
border-radius: var(--border-radius);
background-color: var(--color-label-bg);
color: var(--color-label-text);
}
b,

View File

@@ -228,6 +228,12 @@ textarea:focus,
color: var(--color-text-light-1);
}
.form .help pre.command-block {
white-space: pre-wrap;
overflow-wrap: anywhere;
margin: 0.25em 0 0.25em 1em;
}
.m-captcha-style {
width: 100%;
height: 5em;

View File

@@ -21,10 +21,10 @@ withDefaults(defineProps<{
<span :data-tooltip-content="localeStatus ?? status" v-if="status">
<SvgIcon name="octicon-check-circle-fill" class="text green" :size="size" :class="className" v-if="status === 'success'"/>
<SvgIcon name="octicon-skip" class="text grey" :size="size" :class="className" v-else-if="status === 'skipped'"/>
<SvgIcon name="octicon-stop" class="text yellow" :size="size" :class="className" v-else-if="status === 'cancelled'"/>
<SvgIcon name="octicon-clock" class="text yellow" :size="size" :class="className" v-else-if="status === 'waiting'"/>
<SvgIcon name="octicon-stop" class="text grey" :size="size" :class="className" v-else-if="status === 'cancelled'"/>
<SvgIcon name="octicon-circle" class="text grey" :size="size" :class="className" v-else-if="status === 'waiting'"/>
<SvgIcon name="octicon-blocked" class="text yellow" :size="size" :class="className" v-else-if="status === 'blocked'"/>
<SvgIcon name="octicon-meter" class="text yellow" :size="size" :class="'circular-spin ' + className" v-else-if="status === 'running'"/>
<SvgIcon name="gitea-running" class="text yellow" :size="size" :class="'circular-spin ' + className" v-else-if="status === 'running'"/>
<SvgIcon name="octicon-x-circle-fill" class="text red" :size="size" v-else/><!-- failure, unknown -->
</span>
</template>

View File

@@ -5,6 +5,7 @@ import giteaDoubleChevronLeft from '../../public/assets/img/svg/gitea-double-che
import giteaDoubleChevronRight from '../../public/assets/img/svg/gitea-double-chevron-right.svg';
import giteaEmptyCheckbox from '../../public/assets/img/svg/gitea-empty-checkbox.svg';
import giteaExclamation from '../../public/assets/img/svg/gitea-exclamation.svg';
import giteaRunning from '../../public/assets/img/svg/gitea-running.svg';
import octiconArchive from '../../public/assets/img/svg/octicon-archive.svg';
import octiconArrowSwitch from '../../public/assets/img/svg/octicon-arrow-switch.svg';
import octiconBlocked from '../../public/assets/img/svg/octicon-blocked.svg';
@@ -15,6 +16,7 @@ import octiconCheckCircleFill from '../../public/assets/img/svg/octicon-check-ci
import octiconChevronDown from '../../public/assets/img/svg/octicon-chevron-down.svg';
import octiconChevronLeft from '../../public/assets/img/svg/octicon-chevron-left.svg';
import octiconChevronRight from '../../public/assets/img/svg/octicon-chevron-right.svg';
import octiconCircle from '../../public/assets/img/svg/octicon-circle.svg';
import octiconClock from '../../public/assets/img/svg/octicon-clock.svg';
import octiconCode from '../../public/assets/img/svg/octicon-code.svg';
import octiconColumns from '../../public/assets/img/svg/octicon-columns.svg';
@@ -84,6 +86,7 @@ const svgs = {
'gitea-double-chevron-right': giteaDoubleChevronRight,
'gitea-empty-checkbox': giteaEmptyCheckbox,
'gitea-exclamation': giteaExclamation,
'gitea-running': giteaRunning,
'octicon-archive': octiconArchive,
'octicon-arrow-switch': octiconArrowSwitch,
'octicon-blocked': octiconBlocked,
@@ -94,6 +97,7 @@ const svgs = {
'octicon-chevron-down': octiconChevronDown,
'octicon-chevron-left': octiconChevronLeft,
'octicon-chevron-right': octiconChevronRight,
'octicon-circle': octiconCircle,
'octicon-clock': octiconClock,
'octicon-code': octiconCode,
'octicon-columns': octiconColumns,

View File

@@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16">
<path fill="none" stroke="currentColor" stroke-width="2" d="M3.05 3.05a7 7 0 1 1 9.9 9.9 7 7 0 0 1-9.9-9.9Z" opacity=".5"></path>
<path fill="currentColor" fill-rule="evenodd" d="M8 4a4 4 0 1 0 0 8 4 4 0 0 0 0-8Z" clip-rule="evenodd"></path>
<path fill="currentColor" d="M14 8a6 6 0 0 0-6-6V0a8 8 0 0 1 8 8h-2Z"></path>
</svg>

After

Width:  |  Height:  |  Size: 416 B