mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2024-12-22 12:54:53 -05:00
Merge pull request '[gitea] week 2024-50 cherry pick (gitea/main -> forgejo)' (#6200) from earl-warren/wcp/2024-50 into forgejo
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/6200 Reviewed-by: Otto <otto@codeberg.org> Reviewed-by: Gusted <gusted@noreply.codeberg.org>
This commit is contained in:
commit
021c8fe15a
13 changed files with 142 additions and 232 deletions
|
@ -15,7 +15,6 @@ code.gitea.io/gitea/models
|
||||||
ErrUpdateTaskNotExist.Unwrap
|
ErrUpdateTaskNotExist.Unwrap
|
||||||
IsErrSHANotFound
|
IsErrSHANotFound
|
||||||
IsErrMergeDivergingFastForwardOnly
|
IsErrMergeDivergingFastForwardOnly
|
||||||
GetYamlFixturesAccess
|
|
||||||
|
|
||||||
code.gitea.io/gitea/models/actions
|
code.gitea.io/gitea/models/actions
|
||||||
ScheduleList.GetUserIDs
|
ScheduleList.GetUserIDs
|
||||||
|
|
|
@ -1,80 +0,0 @@
|
||||||
// Copyright 2020 The Gitea Authors. All rights reserved.
|
|
||||||
// SPDX-License-Identifier: MIT
|
|
||||||
|
|
||||||
//nolint:forbidigo
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
|
||||||
"code.gitea.io/gitea/models/unittest"
|
|
||||||
)
|
|
||||||
|
|
||||||
// To generate derivative fixtures, execute the following from Gitea's repository base dir:
|
|
||||||
// go run -tags 'sqlite sqlite_unlock_notify' contrib/fixtures/fixture_generation.go [fixture...]
|
|
||||||
|
|
||||||
var (
|
|
||||||
generators = []struct {
|
|
||||||
gen func(ctx context.Context) (string, error)
|
|
||||||
name string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
models.GetYamlFixturesAccess, "access",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
fixturesDir string
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
pathToGiteaRoot := "."
|
|
||||||
fixturesDir = filepath.Join(pathToGiteaRoot, "models", "fixtures")
|
|
||||||
if err := unittest.CreateTestEngine(unittest.FixturesOptions{
|
|
||||||
Dir: fixturesDir,
|
|
||||||
}); err != nil {
|
|
||||||
fmt.Printf("CreateTestEngine: %+v", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
if err := unittest.PrepareTestDatabase(); err != nil {
|
|
||||||
fmt.Printf("PrepareTestDatabase: %+v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
ctx := context.Background()
|
|
||||||
if len(os.Args) == 0 {
|
|
||||||
for _, r := range os.Args {
|
|
||||||
if err := generate(ctx, r); err != nil {
|
|
||||||
fmt.Printf("generate '%s': %+v\n", r, err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for _, g := range generators {
|
|
||||||
if err := generate(ctx, g.name); err != nil {
|
|
||||||
fmt.Printf("generate '%s': %+v\n", g.name, err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func generate(ctx context.Context, name string) error {
|
|
||||||
for _, g := range generators {
|
|
||||||
if g.name == name {
|
|
||||||
data, err := g.gen(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
path := filepath.Join(fixturesDir, name+".yml")
|
|
||||||
if err := os.WriteFile(path, []byte(data), 0o644); err != nil {
|
|
||||||
return fmt.Errorf("%s: %+v", path, err)
|
|
||||||
}
|
|
||||||
fmt.Printf("%s created.\n", path)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return fmt.Errorf("generator not found")
|
|
||||||
}
|
|
|
@ -1,50 +0,0 @@
|
||||||
// Copyright 2020 The Gitea Authors. All rights reserved.
|
|
||||||
// SPDX-License-Identifier: MIT
|
|
||||||
|
|
||||||
package models
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
|
||||||
access_model "code.gitea.io/gitea/models/perm/access"
|
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
|
||||||
)
|
|
||||||
|
|
||||||
// GetYamlFixturesAccess returns a string containing the contents
|
|
||||||
// for the access table, as recalculated using repo.RecalculateAccesses()
|
|
||||||
func GetYamlFixturesAccess(ctx context.Context) (string, error) {
|
|
||||||
repos := make([]*repo_model.Repository, 0, 50)
|
|
||||||
if err := db.GetEngine(ctx).Find(&repos); err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, repo := range repos {
|
|
||||||
repo.MustOwner(ctx)
|
|
||||||
if err := access_model.RecalculateAccesses(ctx, repo); err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var b strings.Builder
|
|
||||||
|
|
||||||
accesses := make([]*access_model.Access, 0, 200)
|
|
||||||
if err := db.GetEngine(ctx).OrderBy("user_id, repo_id").Find(&accesses); err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, a := range accesses {
|
|
||||||
fmt.Fprintf(&b, "-\n")
|
|
||||||
fmt.Fprintf(&b, " id: %d\n", i+1)
|
|
||||||
fmt.Fprintf(&b, " user_id: %d\n", a.UserID)
|
|
||||||
fmt.Fprintf(&b, " repo_id: %d\n", a.RepoID)
|
|
||||||
fmt.Fprintf(&b, " mode: %d\n", a.Mode)
|
|
||||||
if i < len(accesses)-1 {
|
|
||||||
fmt.Fprintf(&b, "\n")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return b.String(), nil
|
|
||||||
}
|
|
|
@ -1,36 +0,0 @@
|
||||||
// Copyright 2020 The Gitea Authors. All rights reserved.
|
|
||||||
// SPDX-License-Identifier: MIT
|
|
||||||
|
|
||||||
package models
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
|
||||||
"code.gitea.io/gitea/models/unittest"
|
|
||||||
"code.gitea.io/gitea/modules/util"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestFixtureGeneration(t *testing.T) {
|
|
||||||
require.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
|
|
||||||
test := func(ctx context.Context, gen func(ctx context.Context) (string, error), name string) {
|
|
||||||
expected, err := gen(ctx)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
p := filepath.Join(unittest.FixturesDir(), name+".yml")
|
|
||||||
bytes, err := os.ReadFile(p)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
data := string(util.NormalizeEOL(bytes))
|
|
||||||
assert.EqualValues(t, expected, data, "Differences detected for %s", p)
|
|
||||||
}
|
|
||||||
|
|
||||||
test(db.DefaultContext, GetYamlFixturesAccess, "access")
|
|
||||||
}
|
|
1
release-notes/6200.md
Normal file
1
release-notes/6200.md
Normal file
|
@ -0,0 +1 @@
|
||||||
|
feat: [commit](https://codeberg.org/forgejo/forgejo/commit/0786ddc5de37a01d1c3e3bf99b794665341b3c12) Add Swift login endpoint
|
|
@ -637,40 +637,46 @@ func CommonRoutes() *web.Route {
|
||||||
}, reqPackageAccess(perm.AccessModeWrite))
|
}, reqPackageAccess(perm.AccessModeWrite))
|
||||||
}, reqPackageAccess(perm.AccessModeRead))
|
}, reqPackageAccess(perm.AccessModeRead))
|
||||||
r.Group("/swift", func() {
|
r.Group("/swift", func() {
|
||||||
r.Group("/{scope}/{name}", func() {
|
r.Group("", func() { // Needs to be unauthenticated.
|
||||||
r.Group("", func() {
|
r.Post("", swift.CheckAuthenticate)
|
||||||
r.Get("", swift.EnumeratePackageVersions)
|
r.Post("/login", swift.CheckAuthenticate)
|
||||||
r.Get(".json", swift.EnumeratePackageVersions)
|
})
|
||||||
}, swift.CheckAcceptMediaType(swift.AcceptJSON))
|
r.Group("", func() {
|
||||||
r.Group("/{version}", func() {
|
r.Group("/{scope}/{name}", func() {
|
||||||
r.Get("/Package.swift", swift.CheckAcceptMediaType(swift.AcceptSwift), swift.DownloadManifest)
|
r.Group("", func() {
|
||||||
r.Put("", reqPackageAccess(perm.AccessModeWrite), swift.CheckAcceptMediaType(swift.AcceptJSON), enforcePackagesQuota(), swift.UploadPackageFile)
|
r.Get("", swift.EnumeratePackageVersions)
|
||||||
r.Get("", func(ctx *context.Context) {
|
r.Get(".json", swift.EnumeratePackageVersions)
|
||||||
// Can't use normal routes here: https://github.com/go-chi/chi/issues/781
|
}, swift.CheckAcceptMediaType(swift.AcceptJSON))
|
||||||
|
r.Group("/{version}", func() {
|
||||||
|
r.Get("/Package.swift", swift.CheckAcceptMediaType(swift.AcceptSwift), swift.DownloadManifest)
|
||||||
|
r.Put("", reqPackageAccess(perm.AccessModeWrite), swift.CheckAcceptMediaType(swift.AcceptJSON), enforcePackagesQuota(), swift.UploadPackageFile)
|
||||||
|
r.Get("", func(ctx *context.Context) {
|
||||||
|
// Can't use normal routes here: https://github.com/go-chi/chi/issues/781
|
||||||
|
|
||||||
version := ctx.Params("version")
|
version := ctx.Params("version")
|
||||||
if strings.HasSuffix(version, ".zip") {
|
if strings.HasSuffix(version, ".zip") {
|
||||||
swift.CheckAcceptMediaType(swift.AcceptZip)(ctx)
|
swift.CheckAcceptMediaType(swift.AcceptZip)(ctx)
|
||||||
if ctx.Written() {
|
if ctx.Written() {
|
||||||
return
|
return
|
||||||
|
}
|
||||||
|
ctx.SetParams("version", version[:len(version)-4])
|
||||||
|
swift.DownloadPackageFile(ctx)
|
||||||
|
} else {
|
||||||
|
swift.CheckAcceptMediaType(swift.AcceptJSON)(ctx)
|
||||||
|
if ctx.Written() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if strings.HasSuffix(version, ".json") {
|
||||||
|
ctx.SetParams("version", version[:len(version)-5])
|
||||||
|
}
|
||||||
|
swift.PackageVersionMetadata(ctx)
|
||||||
}
|
}
|
||||||
ctx.SetParams("version", version[:len(version)-4])
|
})
|
||||||
swift.DownloadPackageFile(ctx)
|
|
||||||
} else {
|
|
||||||
swift.CheckAcceptMediaType(swift.AcceptJSON)(ctx)
|
|
||||||
if ctx.Written() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if strings.HasSuffix(version, ".json") {
|
|
||||||
ctx.SetParams("version", version[:len(version)-5])
|
|
||||||
}
|
|
||||||
swift.PackageVersionMetadata(ctx)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
r.Get("/identifiers", swift.CheckAcceptMediaType(swift.AcceptJSON), swift.LookupPackageIdentifiers)
|
||||||
r.Get("/identifiers", swift.CheckAcceptMediaType(swift.AcceptJSON), swift.LookupPackageIdentifiers)
|
}, reqPackageAccess(perm.AccessModeRead))
|
||||||
}, reqPackageAccess(perm.AccessModeRead))
|
})
|
||||||
r.Group("/vagrant", func() {
|
r.Group("/vagrant", func() {
|
||||||
r.Group("/authenticate", func() {
|
r.Group("/authenticate", func() {
|
||||||
r.Get("", vagrant.CheckAuthenticate)
|
r.Get("", vagrant.CheckAuthenticate)
|
||||||
|
|
|
@ -27,7 +27,7 @@ import (
|
||||||
"github.com/hashicorp/go-version"
|
"github.com/hashicorp/go-version"
|
||||||
)
|
)
|
||||||
|
|
||||||
// https://github.com/apple/swift-package-manager/blob/main/Documentation/Registry.md#35-api-versioning
|
// https://github.com/swiftlang/swift-package-manager/blob/main/Documentation/PackageRegistry/Registry.md#35-api-versioning
|
||||||
const (
|
const (
|
||||||
AcceptJSON = "application/vnd.swift.registry.v1+json"
|
AcceptJSON = "application/vnd.swift.registry.v1+json"
|
||||||
AcceptSwift = "application/vnd.swift.registry.v1+swift"
|
AcceptSwift = "application/vnd.swift.registry.v1+swift"
|
||||||
|
@ -35,9 +35,9 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// https://github.com/apple/swift-package-manager/blob/main/Documentation/Registry.md#361-package-scope
|
// https://github.com/swiftlang/swift-package-manager/blob/main/Documentation/PackageRegistry/Registry.md#361-package-scope
|
||||||
scopePattern = regexp.MustCompile(`\A[a-zA-Z0-9][a-zA-Z0-9-]{0,38}\z`)
|
scopePattern = regexp.MustCompile(`\A[a-zA-Z0-9][a-zA-Z0-9-]{0,38}\z`)
|
||||||
// https://github.com/apple/swift-package-manager/blob/main/Documentation/Registry.md#362-package-name
|
// https://github.com/swiftlang/swift-package-manager/blob/main/Documentation/PackageRegistry/Registry.md#362-package-name
|
||||||
namePattern = regexp.MustCompile(`\A[a-zA-Z0-9][a-zA-Z0-9-_]{0,99}\z`)
|
namePattern = regexp.MustCompile(`\A[a-zA-Z0-9][a-zA-Z0-9-_]{0,99}\z`)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ type headers struct {
|
||||||
Link string
|
Link string
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/apple/swift-package-manager/blob/main/Documentation/Registry.md#35-api-versioning
|
// https://github.com/swiftlang/swift-package-manager/blob/main/Documentation/PackageRegistry/Registry.md#35-api-versioning
|
||||||
func setResponseHeaders(resp http.ResponseWriter, h *headers) {
|
func setResponseHeaders(resp http.ResponseWriter, h *headers) {
|
||||||
if h.ContentType != "" {
|
if h.ContentType != "" {
|
||||||
resp.Header().Set("Content-Type", h.ContentType)
|
resp.Header().Set("Content-Type", h.ContentType)
|
||||||
|
@ -69,7 +69,7 @@ func setResponseHeaders(resp http.ResponseWriter, h *headers) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/apple/swift-package-manager/blob/main/Documentation/Registry.md#33-error-handling
|
// https://github.com/swiftlang/swift-package-manager/blob/main/Documentation/PackageRegistry/Registry.md#33-error-handling
|
||||||
func apiError(ctx *context.Context, status int, obj any) {
|
func apiError(ctx *context.Context, status int, obj any) {
|
||||||
// https://www.rfc-editor.org/rfc/rfc7807
|
// https://www.rfc-editor.org/rfc/rfc7807
|
||||||
type Problem struct {
|
type Problem struct {
|
||||||
|
@ -91,7 +91,7 @@ func apiError(ctx *context.Context, status int, obj any) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/apple/swift-package-manager/blob/main/Documentation/Registry.md#35-api-versioning
|
// https://github.com/swiftlang/swift-package-manager/blob/main/Documentation/PackageRegistry/Registry.md#35-api-versioning
|
||||||
func CheckAcceptMediaType(requiredAcceptHeader string) func(ctx *context.Context) {
|
func CheckAcceptMediaType(requiredAcceptHeader string) func(ctx *context.Context) {
|
||||||
return func(ctx *context.Context) {
|
return func(ctx *context.Context) {
|
||||||
accept := ctx.Req.Header.Get("Accept")
|
accept := ctx.Req.Header.Get("Accept")
|
||||||
|
@ -101,6 +101,16 @@ func CheckAcceptMediaType(requiredAcceptHeader string) func(ctx *context.Context
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://github.com/swiftlang/swift-package-manager/blob/main/Documentation/PackageRegistry/PackageRegistryUsage.md#registry-authentication
|
||||||
|
func CheckAuthenticate(ctx *context.Context) {
|
||||||
|
if ctx.Doer == nil {
|
||||||
|
apiError(ctx, http.StatusUnauthorized, nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.Status(http.StatusOK)
|
||||||
|
}
|
||||||
|
|
||||||
func buildPackageID(scope, name string) string {
|
func buildPackageID(scope, name string) string {
|
||||||
return scope + "." + name
|
return scope + "." + name
|
||||||
}
|
}
|
||||||
|
@ -113,7 +123,7 @@ type EnumeratePackageVersionsResponse struct {
|
||||||
Releases map[string]Release `json:"releases"`
|
Releases map[string]Release `json:"releases"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/apple/swift-package-manager/blob/main/Documentation/Registry.md#41-list-package-releases
|
// https://github.com/swiftlang/swift-package-manager/blob/main/Documentation/PackageRegistry/Registry.md#41-list-package-releases
|
||||||
func EnumeratePackageVersions(ctx *context.Context) {
|
func EnumeratePackageVersions(ctx *context.Context) {
|
||||||
packageScope := ctx.Params("scope")
|
packageScope := ctx.Params("scope")
|
||||||
packageName := ctx.Params("name")
|
packageName := ctx.Params("name")
|
||||||
|
@ -170,7 +180,7 @@ type PackageVersionMetadataResponse struct {
|
||||||
Metadata *swift_module.SoftwareSourceCode `json:"metadata"`
|
Metadata *swift_module.SoftwareSourceCode `json:"metadata"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/apple/swift-package-manager/blob/main/Documentation/Registry.md#endpoint-2
|
// https://github.com/swiftlang/swift-package-manager/blob/main/Documentation/PackageRegistry/Registry.md#endpoint-2
|
||||||
func PackageVersionMetadata(ctx *context.Context) {
|
func PackageVersionMetadata(ctx *context.Context) {
|
||||||
id := buildPackageID(ctx.Params("scope"), ctx.Params("name"))
|
id := buildPackageID(ctx.Params("scope"), ctx.Params("name"))
|
||||||
|
|
||||||
|
@ -228,7 +238,7 @@ func PackageVersionMetadata(ctx *context.Context) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/apple/swift-package-manager/blob/main/Documentation/Registry.md#43-fetch-manifest-for-a-package-release
|
// https://github.com/swiftlang/swift-package-manager/blob/main/Documentation/PackageRegistry/Registry.md#43-fetch-manifest-for-a-package-release
|
||||||
func DownloadManifest(ctx *context.Context) {
|
func DownloadManifest(ctx *context.Context) {
|
||||||
packageScope := ctx.Params("scope")
|
packageScope := ctx.Params("scope")
|
||||||
packageName := ctx.Params("name")
|
packageName := ctx.Params("name")
|
||||||
|
@ -280,7 +290,7 @@ func DownloadManifest(ctx *context.Context) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/apple/swift-package-manager/blob/main/Documentation/Registry.md#endpoint-6
|
// https://github.com/swiftlang/swift-package-manager/blob/main/Documentation/PackageRegistry/Registry.md#endpoint-6
|
||||||
func UploadPackageFile(ctx *context.Context) {
|
func UploadPackageFile(ctx *context.Context) {
|
||||||
packageScope := ctx.Params("scope")
|
packageScope := ctx.Params("scope")
|
||||||
packageName := ctx.Params("name")
|
packageName := ctx.Params("name")
|
||||||
|
@ -379,7 +389,7 @@ func UploadPackageFile(ctx *context.Context) {
|
||||||
ctx.Status(http.StatusCreated)
|
ctx.Status(http.StatusCreated)
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/apple/swift-package-manager/blob/main/Documentation/Registry.md#endpoint-4
|
// https://github.com/swiftlang/swift-package-manager/blob/main/Documentation/PackageRegistry/Registry.md#endpoint-4
|
||||||
func DownloadPackageFile(ctx *context.Context) {
|
func DownloadPackageFile(ctx *context.Context) {
|
||||||
pv, err := packages_model.GetVersionByNameAndVersion(ctx, ctx.Package.Owner.ID, packages_model.TypeSwift, buildPackageID(ctx.Params("scope"), ctx.Params("name")), ctx.Params("version"))
|
pv, err := packages_model.GetVersionByNameAndVersion(ctx, ctx.Package.Owner.ID, packages_model.TypeSwift, buildPackageID(ctx.Params("scope"), ctx.Params("name")), ctx.Params("version"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -420,7 +430,7 @@ type LookupPackageIdentifiersResponse struct {
|
||||||
Identifiers []string `json:"identifiers"`
|
Identifiers []string `json:"identifiers"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/apple/swift-package-manager/blob/main/Documentation/Registry.md#endpoint-5
|
// https://github.com/swiftlang/swift-package-manager/blob/main/Documentation/PackageRegistry/Registry.md#endpoint-5
|
||||||
func LookupPackageIdentifiers(ctx *context.Context) {
|
func LookupPackageIdentifiers(ctx *context.Context) {
|
||||||
url := ctx.FormTrim("url")
|
url := ctx.FormTrim("url")
|
||||||
if url == "" {
|
if url == "" {
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"html/template"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
@ -25,6 +26,7 @@ import (
|
||||||
"code.gitea.io/gitea/modules/base"
|
"code.gitea.io/gitea/modules/base"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/storage"
|
"code.gitea.io/gitea/modules/storage"
|
||||||
|
"code.gitea.io/gitea/modules/templates"
|
||||||
"code.gitea.io/gitea/modules/timeutil"
|
"code.gitea.io/gitea/modules/timeutil"
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
"code.gitea.io/gitea/modules/web"
|
"code.gitea.io/gitea/modules/web"
|
||||||
|
@ -108,16 +110,17 @@ type ViewRequest struct {
|
||||||
type ViewResponse struct {
|
type ViewResponse struct {
|
||||||
State struct {
|
State struct {
|
||||||
Run struct {
|
Run struct {
|
||||||
Link string `json:"link"`
|
Link string `json:"link"`
|
||||||
Title string `json:"title"`
|
Title string `json:"title"`
|
||||||
Status string `json:"status"`
|
TitleHTML template.HTML `json:"titleHTML"`
|
||||||
CanCancel bool `json:"canCancel"`
|
Status string `json:"status"`
|
||||||
CanApprove bool `json:"canApprove"` // the run needs an approval and the doer has permission to approve
|
CanCancel bool `json:"canCancel"`
|
||||||
CanRerun bool `json:"canRerun"`
|
CanApprove bool `json:"canApprove"` // the run needs an approval and the doer has permission to approve
|
||||||
CanDeleteArtifact bool `json:"canDeleteArtifact"`
|
CanRerun bool `json:"canRerun"`
|
||||||
Done bool `json:"done"`
|
CanDeleteArtifact bool `json:"canDeleteArtifact"`
|
||||||
Jobs []*ViewJob `json:"jobs"`
|
Done bool `json:"done"`
|
||||||
Commit ViewCommit `json:"commit"`
|
Jobs []*ViewJob `json:"jobs"`
|
||||||
|
Commit ViewCommit `json:"commit"`
|
||||||
} `json:"run"`
|
} `json:"run"`
|
||||||
CurrentJob struct {
|
CurrentJob struct {
|
||||||
Title string `json:"title"`
|
Title string `json:"title"`
|
||||||
|
@ -194,7 +197,10 @@ func ViewPost(ctx *context_module.Context) {
|
||||||
|
|
||||||
resp := &ViewResponse{}
|
resp := &ViewResponse{}
|
||||||
|
|
||||||
|
metas := ctx.Repo.Repository.ComposeMetas(ctx)
|
||||||
|
|
||||||
resp.State.Run.Title = run.Title
|
resp.State.Run.Title = run.Title
|
||||||
|
resp.State.Run.TitleHTML = templates.RenderCommitMessage(ctx, run.Title, metas)
|
||||||
resp.State.Run.Link = run.Link()
|
resp.State.Run.Link = run.Link()
|
||||||
resp.State.Run.CanCancel = !run.Status.IsDone() && ctx.Repo.CanWrite(unit.TypeActions)
|
resp.State.Run.CanCancel = !run.Status.IsDone() && ctx.Repo.CanWrite(unit.TypeActions)
|
||||||
resp.State.Run.CanApprove = run.NeedApproval && ctx.Repo.CanWrite(unit.TypeActions)
|
resp.State.Run.CanApprove = run.NeedApproval && ctx.Repo.CanWrite(unit.TypeActions)
|
||||||
|
|
|
@ -363,6 +363,7 @@ func ViewProject(ctx *context.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx.Data["Title"] = project.Title
|
||||||
ctx.Data["IsProjectsPage"] = true
|
ctx.Data["IsProjectsPage"] = true
|
||||||
ctx.Data["CanWriteProjects"] = ctx.Repo.Permission.CanWrite(unit.TypeProjects)
|
ctx.Data["CanWriteProjects"] = ctx.Repo.Permission.CanWrite(unit.TypeProjects)
|
||||||
ctx.Data["Project"] = project
|
ctx.Data["Project"] = project
|
||||||
|
|
|
@ -6,6 +6,7 @@ package repo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
gocontext "context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
@ -598,22 +599,32 @@ func WikiPages(ctx *context.Context) {
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
entries, err := commit.ListEntries()
|
treePath := "" // To support list sub folders' pages in the future
|
||||||
|
tree, err := commit.SubTree(treePath)
|
||||||
|
if err != nil {
|
||||||
|
ctx.ServerError("SubTree", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
allEntries, err := tree.ListEntries()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("ListEntries", err)
|
ctx.ServerError("ListEntries", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
allEntries.CustomSort(base.NaturalSortLess)
|
||||||
|
|
||||||
|
entries, _, err := allEntries.GetCommitsInfo(gocontext.Context(ctx), commit, treePath)
|
||||||
|
if err != nil {
|
||||||
|
ctx.ServerError("GetCommitsInfo", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
pages := make([]PageMeta, 0, len(entries))
|
pages := make([]PageMeta, 0, len(entries))
|
||||||
for _, entry := range entries {
|
for _, entry := range entries {
|
||||||
if !entry.IsRegular() {
|
if !entry.Entry.IsRegular() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
c, err := wikiRepo.GetCommitByPath(entry.Name())
|
wikiName, err := wiki_service.GitPathToWebPath(entry.Entry.Name())
|
||||||
if err != nil {
|
|
||||||
ctx.ServerError("GetCommit", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
wikiName, err := wiki_service.GitPathToWebPath(entry.Name())
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if repo_model.IsErrWikiInvalidFileName(err) {
|
if repo_model.IsErrWikiInvalidFileName(err) {
|
||||||
continue
|
continue
|
||||||
|
@ -625,8 +636,8 @@ func WikiPages(ctx *context.Context) {
|
||||||
pages = append(pages, PageMeta{
|
pages = append(pages, PageMeta{
|
||||||
Name: displayName,
|
Name: displayName,
|
||||||
SubURL: wiki_service.WebPathToURLPath(wikiName),
|
SubURL: wiki_service.WebPathToURLPath(wikiName),
|
||||||
GitEntryName: entry.Name(),
|
GitEntryName: entry.Entry.Name(),
|
||||||
UpdatedUnix: timeutil.TimeStamp(c.Author.When.Unix()),
|
UpdatedUnix: timeutil.TimeStamp(entry.Commit.Author.When.Unix()),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
ctx.Data["Pages"] = pages
|
ctx.Data["Pages"] = pages
|
||||||
|
|
|
@ -43,6 +43,24 @@ func TestPackageSwift(t *testing.T) {
|
||||||
|
|
||||||
url := fmt.Sprintf("/api/packages/%s/swift", user.Name)
|
url := fmt.Sprintf("/api/packages/%s/swift", user.Name)
|
||||||
|
|
||||||
|
t.Run("CheckLogin", func(t *testing.T) {
|
||||||
|
defer tests.PrintCurrentTest(t)()
|
||||||
|
|
||||||
|
req := NewRequestWithBody(t, "POST", url, strings.NewReader(""))
|
||||||
|
MakeRequest(t, req, http.StatusUnauthorized)
|
||||||
|
|
||||||
|
req = NewRequestWithBody(t, "POST", url, strings.NewReader("")).
|
||||||
|
AddBasicAuth(user.Name)
|
||||||
|
MakeRequest(t, req, http.StatusOK)
|
||||||
|
|
||||||
|
req = NewRequestWithBody(t, "POST", url+"/login", strings.NewReader(""))
|
||||||
|
MakeRequest(t, req, http.StatusUnauthorized)
|
||||||
|
|
||||||
|
req = NewRequestWithBody(t, "POST", url+"/login", strings.NewReader("")).
|
||||||
|
AddBasicAuth(user.Name)
|
||||||
|
MakeRequest(t, req, http.StatusOK)
|
||||||
|
})
|
||||||
|
|
||||||
t.Run("CheckAcceptMediaType", func(t *testing.T) {
|
t.Run("CheckAcceptMediaType", func(t *testing.T) {
|
||||||
defer tests.PrintCurrentTest(t)()
|
defer tests.PrintCurrentTest(t)()
|
||||||
|
|
||||||
|
|
|
@ -6,14 +6,18 @@ package integration
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
|
"code.gitea.io/gitea/tests"
|
||||||
|
|
||||||
|
"github.com/PuerkitoBio/goquery"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
@ -47,3 +51,23 @@ func TestRepoCloneWiki(t *testing.T) {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_RepoWikiPages(t *testing.T) {
|
||||||
|
defer tests.PrepareTestEnv(t)()
|
||||||
|
|
||||||
|
url := "/user2/repo1/wiki/?action=_pages"
|
||||||
|
req := NewRequest(t, "GET", url)
|
||||||
|
resp := MakeRequest(t, req, http.StatusOK)
|
||||||
|
|
||||||
|
doc := NewHTMLParser(t, resp.Body)
|
||||||
|
expectedPagePaths := []string{
|
||||||
|
"Home", "Long-Page", "Page-With-Image", "Page-With-Spaced-Name", "Unescaped-File",
|
||||||
|
}
|
||||||
|
doc.Find("tr").Each(func(i int, s *goquery.Selection) {
|
||||||
|
firstAnchor := s.Find("a").First()
|
||||||
|
href, _ := firstAnchor.Attr("href")
|
||||||
|
pagePath := strings.TrimPrefix(href, "/user2/repo1/wiki/")
|
||||||
|
|
||||||
|
assert.EqualValues(t, expectedPagePaths[i], pagePath)
|
||||||
|
})
|
||||||
|
}
|
|
@ -42,6 +42,7 @@ const sfc = {
|
||||||
run: {
|
run: {
|
||||||
link: '',
|
link: '',
|
||||||
title: '',
|
title: '',
|
||||||
|
titleHTML: '',
|
||||||
status: '',
|
status: '',
|
||||||
canCancel: false,
|
canCancel: false,
|
||||||
canApprove: false,
|
canApprove: false,
|
||||||
|
@ -424,9 +425,8 @@ export function initRepositoryActionView() {
|
||||||
<div class="action-info-summary">
|
<div class="action-info-summary">
|
||||||
<div class="action-info-summary-title">
|
<div class="action-info-summary-title">
|
||||||
<ActionRunStatus :locale-status="locale.status[run.status]" :status="run.status" :size="20"/>
|
<ActionRunStatus :locale-status="locale.status[run.status]" :status="run.status" :size="20"/>
|
||||||
<h2 class="action-info-summary-title-text">
|
<!-- eslint-disable-next-line vue/no-v-html -->
|
||||||
{{ run.title }}
|
<h2 class="action-info-summary-title-text" v-html="run.titleHTML"/>
|
||||||
</h2>
|
|
||||||
</div>
|
</div>
|
||||||
<button class="ui basic small compact button primary" @click="approveRun()" v-if="run.canApprove">
|
<button class="ui basic small compact button primary" @click="approveRun()" v-if="run.canApprove">
|
||||||
{{ locale.approve }}
|
{{ locale.approve }}
|
||||||
|
|
Loading…
Reference in a new issue