mirror of
https://github.com/go-gitea/gitea.git
synced 2025-11-05 18:32:41 +09:00
Compare commits
43 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4bc6bfb476 | ||
|
|
5999349ce7 | ||
|
|
e301e26d7a | ||
|
|
d2efd2bf73 | ||
|
|
89297c9355 | ||
|
|
d2328c4051 | ||
|
|
af5d66b341 | ||
|
|
912a418920 | ||
|
|
cc7a4f17e0 | ||
|
|
5f82011b7c | ||
|
|
1bbbeb24ef | ||
|
|
1254a8271e | ||
|
|
ef3e3afc05 | ||
|
|
b1094ff28c | ||
|
|
8044d87c18 | ||
|
|
1b8e36587e | ||
|
|
a2f52f3561 | ||
|
|
65de747b13 | ||
|
|
7e86dffc35 | ||
|
|
7297cceda7 | ||
|
|
077160b838 | ||
|
|
da4448421e | ||
|
|
5ccb626cda | ||
|
|
b00f7c3c54 | ||
|
|
51fd730147 | ||
|
|
7117355169 | ||
|
|
d5f2c9d74d | ||
|
|
95c2cb4b79 | ||
|
|
7d717e22a8 | ||
|
|
dc66ceadac | ||
|
|
8cd5483e8a | ||
|
|
2e6e5bc9c9 | ||
|
|
f134229bf2 | ||
|
|
3d3c740636 | ||
|
|
c4f569b9a5 | ||
|
|
03b6e7900b | ||
|
|
463e144d97 | ||
|
|
2b32f8b95f | ||
|
|
94fbd44bac | ||
|
|
494e373292 | ||
|
|
10f93995e9 | ||
|
|
67a73dd05f | ||
|
|
893c97dd71 |
47
CHANGELOG.md
47
CHANGELOG.md
@@ -4,6 +4,53 @@ 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.19.2](https://github.com/go-gitea/gitea/releases/tag/1.19.2) - 2023-04-26
|
||||||
|
|
||||||
|
* SECURITY
|
||||||
|
* Require repo scope for PATs for private repos and basic authentication (#24362) (#24364)
|
||||||
|
* Only delete secrets belonging to its owner (#24284) (#24286)
|
||||||
|
* API
|
||||||
|
* Fix typo in API route (#24310) (#24332)
|
||||||
|
* Fix access token issue on some public endpoints (#24194) (#24259)
|
||||||
|
* ENHANCEMENTS
|
||||||
|
* Fix broken clone script on an empty archived repo (#24339) (#24348)
|
||||||
|
* Fix Monaco IOS keyboard button (#24341) (#24347)
|
||||||
|
* Don't set meta `theme-color` by default (#24340) (#24346)
|
||||||
|
* Wrap too long push mirror addresses (#21120) (#24334)
|
||||||
|
* Add --font-weight-bold and set previous bold to 601 (#24307) (#24331)
|
||||||
|
* Unify nightly naming across binaries and docker images (#24116) (#24308)
|
||||||
|
* Fix footer display (#24251) (#24269)
|
||||||
|
* Fix label color, fix divider in dropdown (#24215) (#24244)
|
||||||
|
* Vertical widths of containers removed (#24184) (#24211)
|
||||||
|
* Use correct locale key for forks page (#24172) (#24175)
|
||||||
|
* Sort repo topic labels by name (#24123) (#24153)
|
||||||
|
* Highlight selected file in the PR file tree (#23947) (#24126)
|
||||||
|
* BUGFIXES
|
||||||
|
* Fix auth check bug (#24382) (#24387)
|
||||||
|
* Add tags list for repos whose release setting is disabled (#23465) (#24369)
|
||||||
|
* Fix wrong error info in RepoRefForAPI (#24344) (#24351)
|
||||||
|
* Fix no edit/close/delete button in org repo project view page (#24349)
|
||||||
|
* Respect the REGISTER_MANUAL_CONFIRM setting when registering via OIDC (#24035) (#24333)
|
||||||
|
* Remove org users who belong to no teams (#24247) (#24313)
|
||||||
|
* Fix bug when deleting wiki with no code write permission (#24274) (#24295)
|
||||||
|
* Handle canceled workflow as a warning instead of a fail (#24282) (#24292)
|
||||||
|
* Load reviewer for comments when dismissing a review (#24281) (#24288)
|
||||||
|
* Show commit history for closed/merged PRs (#24238) (#24261)
|
||||||
|
* Fix owner team access mode value in team_unit table (#24224)
|
||||||
|
* Fix issue attachment handling (#24202) (#24221)
|
||||||
|
* Fix incorrect CORS default values (#24206) (#24217)
|
||||||
|
* Fix template error in pull request with deleted head repo (#24192) (#24216)
|
||||||
|
* Don't list root repository on compare page if pulls not allowed (#24183) (#24210)
|
||||||
|
* Fix calReleaseNumCommitsBehind (#24148) (#24197)
|
||||||
|
* Fix Org edit page bugs: renaming detection, maxlength (#24161) (#24171)
|
||||||
|
* Update redis library to support redis v7 (#24114) (#24156)
|
||||||
|
* Use 1.18's aria role for dropdown menus (#24144) (#24155)
|
||||||
|
* Fix 2-dot direct compare to use the right base commit (#24133) (#24150)
|
||||||
|
* Fix incorrect server error content in RunnersList (#24118) (#24121)
|
||||||
|
* Fix mismatch between hook events and github event types (#24048) (#24091)
|
||||||
|
* BUILD
|
||||||
|
* Support converting varchar to nvarchar for mssql database (#24105) (#24168)
|
||||||
|
|
||||||
## [1.19.1](https://github.com/go-gitea/gitea/releases/tag/v1.19.1) - 2023-04-12
|
## [1.19.1](https://github.com/go-gitea/gitea/releases/tag/v1.19.1) - 2023-04-12
|
||||||
|
|
||||||
* BREAKING
|
* BREAKING
|
||||||
|
|||||||
5
Makefile
5
Makefile
@@ -97,6 +97,11 @@ else
|
|||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# if version = "main" then update version to "nightly"
|
||||||
|
ifeq ($(VERSION),main)
|
||||||
|
VERSION := main-nightly
|
||||||
|
endif
|
||||||
|
|
||||||
LDFLAGS := $(LDFLAGS) -X "main.MakeVersion=$(MAKE_VERSION)" -X "main.Version=$(GITEA_VERSION)" -X "main.Tags=$(TAGS)"
|
LDFLAGS := $(LDFLAGS) -X "main.MakeVersion=$(MAKE_VERSION)" -X "main.Version=$(GITEA_VERSION)" -X "main.Tags=$(TAGS)"
|
||||||
|
|
||||||
LINUX_ARCHS ?= linux/amd64,linux/386,linux/arm-5,linux/arm-6,linux/arm64
|
LINUX_ARCHS ?= linux/amd64,linux/386,linux/arm-5,linux/arm-6,linux/arm64
|
||||||
|
|||||||
10
assets/go-licenses.json
generated
10
assets/go-licenses.json
generated
File diff suppressed because one or more lines are too long
@@ -17,7 +17,7 @@ import (
|
|||||||
var CmdConvert = cli.Command{
|
var CmdConvert = cli.Command{
|
||||||
Name: "convert",
|
Name: "convert",
|
||||||
Usage: "Convert the database",
|
Usage: "Convert the database",
|
||||||
Description: "A command to convert an existing MySQL database from utf8 to utf8mb4",
|
Description: "A command to convert an existing MySQL database from utf8 to utf8mb4 or MSSQL database from varchar to nvarchar",
|
||||||
Action: runConvert,
|
Action: runConvert,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -35,17 +35,22 @@ func runConvert(ctx *cli.Context) error {
|
|||||||
log.Info("Log path: %s", setting.Log.RootPath)
|
log.Info("Log path: %s", setting.Log.RootPath)
|
||||||
log.Info("Configuration file: %s", setting.CustomConf)
|
log.Info("Configuration file: %s", setting.CustomConf)
|
||||||
|
|
||||||
if !setting.Database.Type.IsMySQL() {
|
switch {
|
||||||
fmt.Println("This command can only be used with a MySQL database")
|
case setting.Database.Type.IsMySQL():
|
||||||
return nil
|
if err := db.ConvertUtf8ToUtf8mb4(); err != nil {
|
||||||
|
log.Fatal("Failed to convert database from utf8 to utf8mb4: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Println("Converted successfully, please confirm your database's character set is now utf8mb4")
|
||||||
|
case setting.Database.Type.IsMSSQL():
|
||||||
|
if err := db.ConvertVarcharToNVarchar(); err != nil {
|
||||||
|
log.Fatal("Failed to convert database from varchar to nvarchar: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Println("Converted successfully, please confirm your database's all columns character is NVARCHAR now")
|
||||||
|
default:
|
||||||
|
fmt.Println("This command can only be used with a MySQL or MSSQL database")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := db.ConvertUtf8ToUtf8mb4(); err != nil {
|
|
||||||
log.Fatal("Failed to convert database from utf8 to utf8mb4: %v", err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println("Converted successfully, please confirm your database's character set is now utf8mb4")
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1191,10 +1191,9 @@ ROUTER = console
|
|||||||
;; Number of line of codes shown for a code comment
|
;; Number of line of codes shown for a code comment
|
||||||
;CODE_COMMENT_LINES = 4
|
;CODE_COMMENT_LINES = 4
|
||||||
;;
|
;;
|
||||||
;; Value of `theme-color` meta tag, used by Android >= 5.0
|
;; Value of `theme-color` meta tag, used by some mobile browers for chrome and
|
||||||
;; An invalid color like "none" or "disable" will have the default style
|
;; out-of-viewport areas. Default is unset which uses body color.
|
||||||
;; More info: https://developers.google.com/web/updates/2014/11/Support-for-theme-color-in-Chrome-39-for-Android
|
;THEME_COLOR_META_TAG =
|
||||||
;THEME_COLOR_META_TAG = `#6cc644`
|
|
||||||
;;
|
;;
|
||||||
;; Max size of files to be displayed (default is 8MiB)
|
;; Max size of files to be displayed (default is 8MiB)
|
||||||
;MAX_DISPLAY_FILE_SIZE = 8388608
|
;MAX_DISPLAY_FILE_SIZE = 8388608
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}{{#if (hasPrefix "refs/heads/release/v" build.ref)}}{{trimPrefix "refs/heads/release/v" build.ref}}-{{/if}}dev{{/if}}-rootless
|
image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}{{#if (hasPrefix "refs/heads/release/v" build.ref)}}{{trimPrefix "refs/heads/release/v" build.ref}}-{{/if}}nightly{{/if}}-rootless
|
||||||
{{#if build.tags}}
|
{{#if build.tags}}
|
||||||
{{#unless (contains "-rc" build.tag)}}
|
{{#unless (contains "-rc" build.tag)}}
|
||||||
tags:
|
tags:
|
||||||
@@ -10,12 +10,12 @@ tags:
|
|||||||
{{/if}}
|
{{/if}}
|
||||||
manifests:
|
manifests:
|
||||||
-
|
-
|
||||||
image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}{{#if (hasPrefix "refs/heads/release/v" build.ref)}}{{trimPrefix "refs/heads/release/v" build.ref}}-{{/if}}dev{{/if}}-linux-amd64-rootless
|
image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}{{#if (hasPrefix "refs/heads/release/v" build.ref)}}{{trimPrefix "refs/heads/release/v" build.ref}}-{{/if}}nightly{{/if}}-linux-amd64-rootless
|
||||||
platform:
|
platform:
|
||||||
architecture: amd64
|
architecture: amd64
|
||||||
os: linux
|
os: linux
|
||||||
-
|
-
|
||||||
image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}{{#if (hasPrefix "refs/heads/release/v" build.ref)}}{{trimPrefix "refs/heads/release/v" build.ref}}-{{/if}}dev{{/if}}-linux-arm64-rootless
|
image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}{{#if (hasPrefix "refs/heads/release/v" build.ref)}}{{trimPrefix "refs/heads/release/v" build.ref}}-{{/if}}nightly{{/if}}-linux-arm64-rootless
|
||||||
platform:
|
platform:
|
||||||
architecture: arm64
|
architecture: arm64
|
||||||
os: linux
|
os: linux
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}{{#if (hasPrefix "refs/heads/release/v" build.ref)}}{{trimPrefix "refs/heads/release/v" build.ref}}-{{/if}}dev{{/if}}
|
image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}{{#if (hasPrefix "refs/heads/release/v" build.ref)}}{{trimPrefix "refs/heads/release/v" build.ref}}-{{/if}}nightly{{/if}}
|
||||||
{{#if build.tags}}
|
{{#if build.tags}}
|
||||||
{{#unless (contains "-rc" build.tag)}}
|
{{#unless (contains "-rc" build.tag)}}
|
||||||
tags:
|
tags:
|
||||||
@@ -10,12 +10,12 @@ tags:
|
|||||||
{{/if}}
|
{{/if}}
|
||||||
manifests:
|
manifests:
|
||||||
-
|
-
|
||||||
image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}{{#if (hasPrefix "refs/heads/release/v" build.ref)}}{{trimPrefix "refs/heads/release/v" build.ref}}-{{/if}}dev{{/if}}-linux-amd64
|
image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}{{#if (hasPrefix "refs/heads/release/v" build.ref)}}{{trimPrefix "refs/heads/release/v" build.ref}}-{{/if}}nightly{{/if}}-linux-amd64
|
||||||
platform:
|
platform:
|
||||||
architecture: amd64
|
architecture: amd64
|
||||||
os: linux
|
os: linux
|
||||||
-
|
-
|
||||||
image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}{{#if (hasPrefix "refs/heads/release/v" build.ref)}}{{trimPrefix "refs/heads/release/v" build.ref}}-{{/if}}dev{{/if}}-linux-arm64
|
image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}{{#if (hasPrefix "refs/heads/release/v" build.ref)}}{{trimPrefix "refs/heads/release/v" build.ref}}-{{/if}}nightly{{/if}}-linux-arm64
|
||||||
platform:
|
platform:
|
||||||
architecture: arm64
|
architecture: arm64
|
||||||
os: linux
|
os: linux
|
||||||
|
|||||||
@@ -220,7 +220,7 @@ The following configuration set `Content-Type: application/vnd.android.package-a
|
|||||||
- `SHOW_USER_EMAIL`: **true**: Whether the email of the user should be shown in the Explore Users page.
|
- `SHOW_USER_EMAIL`: **true**: Whether the email of the user should be shown in the Explore Users page.
|
||||||
- `THEMES`: **auto,gitea,arc-green**: All available themes. Allow users select personalized themes.
|
- `THEMES`: **auto,gitea,arc-green**: All available themes. Allow users select personalized themes.
|
||||||
regardless of the value of `DEFAULT_THEME`.
|
regardless of the value of `DEFAULT_THEME`.
|
||||||
- `THEME_COLOR_META_TAG`: **#6cc644**: Value of `theme-color` meta tag, used by Android >= 5.0. An invalid color like "none" or "disable" will have the default style. More info: https://developers.google.com/web/updates/2014/11/Support-for-theme-color-in-Chrome-39-for-Android
|
- `THEME_COLOR_META_TAG`: **\<empty\>**: Value of `theme-color` meta tag, used by some mobile browers for chrome and out-of-viewport areas. Default is unset which uses body color.
|
||||||
- `MAX_DISPLAY_FILE_SIZE`: **8388608**: Max size of files to be displayed (default is 8MiB)
|
- `MAX_DISPLAY_FILE_SIZE`: **8388608**: Max size of files to be displayed (default is 8MiB)
|
||||||
- `REACTIONS`: All available reactions users can choose on issues/prs and comments
|
- `REACTIONS`: All available reactions users can choose on issues/prs and comments
|
||||||
Values can be emoji alias (:smile:) or a unicode emoji.
|
Values can be emoji alias (:smile:) or a unicode emoji.
|
||||||
|
|||||||
12
go.mod
12
go.mod
@@ -44,7 +44,6 @@ require (
|
|||||||
github.com/go-git/go-billy/v5 v5.4.1
|
github.com/go-git/go-billy/v5 v5.4.1
|
||||||
github.com/go-git/go-git/v5 v5.5.2
|
github.com/go-git/go-git/v5 v5.5.2
|
||||||
github.com/go-ldap/ldap/v3 v3.4.4
|
github.com/go-ldap/ldap/v3 v3.4.4
|
||||||
github.com/go-redis/redis/v8 v8.11.5
|
|
||||||
github.com/go-sql-driver/mysql v1.7.0
|
github.com/go-sql-driver/mysql v1.7.0
|
||||||
github.com/go-swagger/go-swagger v0.30.3
|
github.com/go-swagger/go-swagger v0.30.3
|
||||||
github.com/go-testfixtures/testfixtures/v3 v3.8.1
|
github.com/go-testfixtures/testfixtures/v3 v3.8.1
|
||||||
@@ -88,8 +87,9 @@ require (
|
|||||||
github.com/pquerna/otp v1.4.0
|
github.com/pquerna/otp v1.4.0
|
||||||
github.com/prometheus/client_golang v1.14.0
|
github.com/prometheus/client_golang v1.14.0
|
||||||
github.com/quasoft/websspi v1.1.2
|
github.com/quasoft/websspi v1.1.2
|
||||||
github.com/santhosh-tekuri/jsonschema/v5 v5.1.1
|
github.com/redis/go-redis/v9 v9.0.3
|
||||||
github.com/sergi/go-diff v1.2.0
|
github.com/santhosh-tekuri/jsonschema/v5 v5.2.0
|
||||||
|
github.com/sergi/go-diff v1.3.1
|
||||||
github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546
|
github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546
|
||||||
github.com/stretchr/testify v1.8.1
|
github.com/stretchr/testify v1.8.1
|
||||||
github.com/syndtr/goleveldb v1.0.0
|
github.com/syndtr/goleveldb v1.0.0
|
||||||
@@ -155,7 +155,7 @@ require (
|
|||||||
github.com/boombuler/barcode v1.0.1 // indirect
|
github.com/boombuler/barcode v1.0.1 // indirect
|
||||||
github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b // indirect
|
github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b // indirect
|
||||||
github.com/cention-sany/utf7 v0.0.0-20170124080048-26cad61bd60a // indirect
|
github.com/cention-sany/utf7 v0.0.0-20170124080048-26cad61bd60a // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||||
github.com/cloudflare/circl v1.2.0 // indirect
|
github.com/cloudflare/circl v1.2.0 // indirect
|
||||||
github.com/couchbase/go-couchbase v0.0.0-20210224140812-5740cd35f448 // indirect
|
github.com/couchbase/go-couchbase v0.0.0-20210224140812-5740cd35f448 // indirect
|
||||||
github.com/couchbase/gomemcached v0.1.2 // indirect
|
github.com/couchbase/gomemcached v0.1.2 // indirect
|
||||||
@@ -230,6 +230,8 @@ require (
|
|||||||
github.com/nwaples/rardecode v1.1.3 // indirect
|
github.com/nwaples/rardecode v1.1.3 // indirect
|
||||||
github.com/oklog/ulid v1.3.1 // indirect
|
github.com/oklog/ulid v1.3.1 // indirect
|
||||||
github.com/olekukonko/tablewriter v0.0.5 // indirect
|
github.com/olekukonko/tablewriter v0.0.5 // indirect
|
||||||
|
github.com/onsi/ginkgo v1.16.5 // indirect
|
||||||
|
github.com/onsi/gomega v1.18.1 // indirect
|
||||||
github.com/pelletier/go-toml v1.9.5 // indirect
|
github.com/pelletier/go-toml v1.9.5 // indirect
|
||||||
github.com/pelletier/go-toml/v2 v2.0.1 // indirect
|
github.com/pelletier/go-toml/v2 v2.0.1 // indirect
|
||||||
github.com/pierrec/lz4/v4 v4.1.17 // indirect
|
github.com/pierrec/lz4/v4 v4.1.17 // indirect
|
||||||
@@ -285,7 +287,7 @@ replace github.com/shurcooL/vfsgen => github.com/lunny/vfsgen v0.0.0-20220105142
|
|||||||
|
|
||||||
replace github.com/blevesearch/zapx/v15 v15.3.6 => github.com/zeripath/zapx/v15 v15.3.6-alignment-fix
|
replace github.com/blevesearch/zapx/v15 v15.3.6 => github.com/zeripath/zapx/v15 v15.3.6-alignment-fix
|
||||||
|
|
||||||
replace github.com/nektos/act => gitea.com/gitea/act v0.243.3-0.20230407083103-5c4a96bcb797
|
replace github.com/nektos/act => gitea.com/gitea/act v0.243.4
|
||||||
|
|
||||||
exclude github.com/gofrs/uuid v3.2.0+incompatible
|
exclude github.com/gofrs/uuid v3.2.0+incompatible
|
||||||
|
|
||||||
|
|||||||
32
go.sum
32
go.sum
@@ -70,8 +70,8 @@ codeberg.org/gusted/mcaptcha v0.0.0-20220723083913-4f3072e1d570/go.mod h1:IIAjsi
|
|||||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||||
git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078 h1:cliQ4HHsCo6xi2oWZYKWW4bly/Ory9FuTpFPRxj/mAg=
|
git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078 h1:cliQ4HHsCo6xi2oWZYKWW4bly/Ory9FuTpFPRxj/mAg=
|
||||||
git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078/go.mod h1:g/V2Hjas6Z1UHUp4yIx6bATpNzJ7DYtD0FG3+xARWxs=
|
git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078/go.mod h1:g/V2Hjas6Z1UHUp4yIx6bATpNzJ7DYtD0FG3+xARWxs=
|
||||||
gitea.com/gitea/act v0.243.3-0.20230407083103-5c4a96bcb797 h1:QdQ+pHxpbIi2qsgZbYVxqYV7trfW3P5M/T4AfpoM7iw=
|
gitea.com/gitea/act v0.243.4 h1:MuBHBLCJfpa6mzwwvs4xqQynrSP2RRzpHpWfTV16PmI=
|
||||||
gitea.com/gitea/act v0.243.3-0.20230407083103-5c4a96bcb797/go.mod h1:mabw6AZAiDgxGlK83orWLrNERSPvgBJzEUS3S7u2bHI=
|
gitea.com/gitea/act v0.243.4/go.mod h1:mabw6AZAiDgxGlK83orWLrNERSPvgBJzEUS3S7u2bHI=
|
||||||
gitea.com/go-chi/binding v0.0.0-20221013104517-b29891619681 h1:MMSPgnVULVwV9kEBgvyEUhC9v/uviZ55hPJEMjpbNR4=
|
gitea.com/go-chi/binding v0.0.0-20221013104517-b29891619681 h1:MMSPgnVULVwV9kEBgvyEUhC9v/uviZ55hPJEMjpbNR4=
|
||||||
gitea.com/go-chi/binding v0.0.0-20221013104517-b29891619681/go.mod h1:77TZu701zMXWJFvB8gvTbQ92zQ3DQq/H7l5wAEjQRKc=
|
gitea.com/go-chi/binding v0.0.0-20221013104517-b29891619681/go.mod h1:77TZu701zMXWJFvB8gvTbQ92zQ3DQq/H7l5wAEjQRKc=
|
||||||
gitea.com/go-chi/cache v0.0.0-20210110083709-82c4c9ce2d5e/go.mod h1:k2V/gPDEtXGjjMGuBJiapffAXTv76H4snSmlJRLUhH0=
|
gitea.com/go-chi/cache v0.0.0-20210110083709-82c4c9ce2d5e/go.mod h1:k2V/gPDEtXGjjMGuBJiapffAXTv76H4snSmlJRLUhH0=
|
||||||
@@ -229,6 +229,8 @@ github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl
|
|||||||
github.com/bradfitz/gomemcache v0.0.0-20190329173943-551aad21a668/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA=
|
github.com/bradfitz/gomemcache v0.0.0-20190329173943-551aad21a668/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA=
|
||||||
github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b h1:L/QXpzIa3pOvUGt1D1lA5KjYhPBAN/3iWdP7xeFS9F0=
|
github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b h1:L/QXpzIa3pOvUGt1D1lA5KjYhPBAN/3iWdP7xeFS9F0=
|
||||||
github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA=
|
github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA=
|
||||||
|
github.com/bsm/ginkgo/v2 v2.7.0 h1:ItPMPH90RbmZJt5GtkcNvIRuGEdwlBItdNVoyzaNQao=
|
||||||
|
github.com/bsm/gomega v1.26.0 h1:LhQm+AFcgV2M0WyKroMASzAzCAJVpAxQXv4SaI9a69Y=
|
||||||
github.com/bufbuild/connect-go v1.3.1 h1:doJP6Q8Ypg6haUT2IAZJPWHUN9rAUp+F9MfK7yhu1zs=
|
github.com/bufbuild/connect-go v1.3.1 h1:doJP6Q8Ypg6haUT2IAZJPWHUN9rAUp+F9MfK7yhu1zs=
|
||||||
github.com/bufbuild/connect-go v1.3.1/go.mod h1:9iNvh/NOsfhNBUH5CtvXeVUskQO1xsrEviH7ZArwZ3I=
|
github.com/bufbuild/connect-go v1.3.1/go.mod h1:9iNvh/NOsfhNBUH5CtvXeVUskQO1xsrEviH7ZArwZ3I=
|
||||||
github.com/buildkite/terminal-to-html/v3 v3.7.0 h1:chdLUSpiOj/A4v3dzxyOqixXI6aw7IDA6Dk77FXsvNU=
|
github.com/buildkite/terminal-to-html/v3 v3.7.0 h1:chdLUSpiOj/A4v3dzxyOqixXI6aw7IDA6Dk77FXsvNU=
|
||||||
@@ -244,8 +246,9 @@ github.com/cention-sany/utf7 v0.0.0-20170124080048-26cad61bd60a h1:MISbI8sU/PSK/
|
|||||||
github.com/cention-sany/utf7 v0.0.0-20170124080048-26cad61bd60a/go.mod h1:2GxOXOlEPAMFPfp014mK1SWq8G8BN8o7/dfYqJrVGn8=
|
github.com/cention-sany/utf7 v0.0.0-20170124080048-26cad61bd60a/go.mod h1:2GxOXOlEPAMFPfp014mK1SWq8G8BN8o7/dfYqJrVGn8=
|
||||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
|
|
||||||
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
|
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
|
||||||
|
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
github.com/chi-middleware/proxy v1.1.1 h1:4HaXUp8o2+bhHr1OhVy+VjN0+L7/07JDcn6v7YrTjrQ=
|
github.com/chi-middleware/proxy v1.1.1 h1:4HaXUp8o2+bhHr1OhVy+VjN0+L7/07JDcn6v7YrTjrQ=
|
||||||
github.com/chi-middleware/proxy v1.1.1/go.mod h1:jQwMEJct2tz9VmtCELxvnXoMfa+SOdikvbVJVHv/M+0=
|
github.com/chi-middleware/proxy v1.1.1/go.mod h1:jQwMEJct2tz9VmtCELxvnXoMfa+SOdikvbVJVHv/M+0=
|
||||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||||
@@ -463,8 +466,6 @@ github.com/go-openapi/validate v0.22.0 h1:b0QecH6VslW/TxtpKgzpO1SNG7GU2FsaqKdP1E
|
|||||||
github.com/go-openapi/validate v0.22.0/go.mod h1:rjnrwK57VJ7A8xqfpAOEKRH8yQSGUriMu5/zuPSQ1hg=
|
github.com/go-openapi/validate v0.22.0/go.mod h1:rjnrwK57VJ7A8xqfpAOEKRH8yQSGUriMu5/zuPSQ1hg=
|
||||||
github.com/go-redis/redis v6.15.2+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
|
github.com/go-redis/redis v6.15.2+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
|
||||||
github.com/go-redis/redis/v8 v8.4.0/go.mod h1:A1tbYoHSa1fXwN+//ljcCYYJeLmVrwL9hbQN45Jdy0M=
|
github.com/go-redis/redis/v8 v8.4.0/go.mod h1:A1tbYoHSa1fXwN+//ljcCYYJeLmVrwL9hbQN45Jdy0M=
|
||||||
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
|
|
||||||
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
|
|
||||||
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||||
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||||
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||||
@@ -475,6 +476,7 @@ github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP
|
|||||||
github.com/go-swagger/go-swagger v0.30.3 h1:HuzvdMRed/9Q8vmzVcfNBQByZVtT79DNZxZ18OprdoI=
|
github.com/go-swagger/go-swagger v0.30.3 h1:HuzvdMRed/9Q8vmzVcfNBQByZVtT79DNZxZ18OprdoI=
|
||||||
github.com/go-swagger/go-swagger v0.30.3/go.mod h1:neDPes8r8PCz2JPvHRDj8BTULLh4VJUt7n6MpQqxhHM=
|
github.com/go-swagger/go-swagger v0.30.3/go.mod h1:neDPes8r8PCz2JPvHRDj8BTULLh4VJUt7n6MpQqxhHM=
|
||||||
github.com/go-swagger/scan-repo-boundary v0.0.0-20180623220736-973b3573c013 h1:l9rI6sNaZgNC0LnF3MiE+qTmyBA/tZAg1rtyrGbUMK0=
|
github.com/go-swagger/scan-repo-boundary v0.0.0-20180623220736-973b3573c013 h1:l9rI6sNaZgNC0LnF3MiE+qTmyBA/tZAg1rtyrGbUMK0=
|
||||||
|
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||||
github.com/go-test/deep v1.0.7 h1:/VSMRlnY/JSyqxQUzQLKVMAskpY/NZKFA5j2P+0pP2M=
|
github.com/go-test/deep v1.0.7 h1:/VSMRlnY/JSyqxQUzQLKVMAskpY/NZKFA5j2P+0pP2M=
|
||||||
github.com/go-test/deep v1.0.7/go.mod h1:QV8Hv/iy04NyLBxAdO9njL0iVPN1S4d/A3NVv1V36o8=
|
github.com/go-test/deep v1.0.7/go.mod h1:QV8Hv/iy04NyLBxAdO9njL0iVPN1S4d/A3NVv1V36o8=
|
||||||
github.com/go-testfixtures/testfixtures/v3 v3.8.1 h1:uonwvepqRvSgddcrReZQhojTlWlmOlHkYAb9ZaOMWgU=
|
github.com/go-testfixtures/testfixtures/v3 v3.8.1 h1:uonwvepqRvSgddcrReZQhojTlWlmOlHkYAb9ZaOMWgU=
|
||||||
@@ -621,6 +623,7 @@ github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLe
|
|||||||
github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
|
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
@@ -984,6 +987,7 @@ github.com/nwaples/rardecode v1.1.3 h1:cWCaZwfM5H7nAD6PyEdcVnczzV8i/JtotnyW/dD9l
|
|||||||
github.com/nwaples/rardecode v1.1.3/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=
|
github.com/nwaples/rardecode v1.1.3/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=
|
||||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||||
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
||||||
|
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
||||||
github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs=
|
github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs=
|
||||||
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
|
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
|
||||||
github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4=
|
github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4=
|
||||||
@@ -1000,13 +1004,18 @@ github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W
|
|||||||
github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||||
github.com/onsi/ginkgo v1.14.2/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
|
github.com/onsi/ginkgo v1.14.2/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
|
||||||
|
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
|
||||||
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
|
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
|
||||||
|
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
|
||||||
|
github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
|
||||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||||
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||||
github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc=
|
github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc=
|
||||||
|
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
|
||||||
github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
|
github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
|
||||||
|
github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs=
|
||||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
|
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
|
||||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||||
@@ -1096,6 +1105,8 @@ github.com/quasoft/websspi v1.1.2 h1:/mA4w0LxWlE3novvsoEL6BBA1WnjJATbjkh1kFrTidw
|
|||||||
github.com/quasoft/websspi v1.1.2/go.mod h1:HmVdl939dQ0WIXZhyik+ARdI03M6bQzaSEKcgpFmewk=
|
github.com/quasoft/websspi v1.1.2/go.mod h1:HmVdl939dQ0WIXZhyik+ARdI03M6bQzaSEKcgpFmewk=
|
||||||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||||
github.com/rcrowley/go-metrics v0.0.0-20190826022208-cac0b30c2563/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
github.com/rcrowley/go-metrics v0.0.0-20190826022208-cac0b30c2563/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||||
|
github.com/redis/go-redis/v9 v9.0.3 h1:+7mmR26M0IvyLxGZUHxu4GiBkJkVDid0Un+j4ScYu4k=
|
||||||
|
github.com/redis/go-redis/v9 v9.0.3/go.mod h1:WqMKv5vnQbRuZstUwxQI195wHy+t4PuXDOjzMvcuQHk=
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk=
|
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk=
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||||
github.com/rhysd/actionlint v1.6.23 h1:041VOXgZddfvSJa9Il+WT3Iwuo/j0Nmu4bhpAScrds4=
|
github.com/rhysd/actionlint v1.6.23 h1:041VOXgZddfvSJa9Il+WT3Iwuo/j0Nmu4bhpAScrds4=
|
||||||
@@ -1127,12 +1138,12 @@ github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf
|
|||||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||||
github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
|
github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
|
||||||
github.com/santhosh-tekuri/jsonschema/v5 v5.1.1 h1:lEOLY2vyGIqKWUI9nzsOJRV3mb3WC9dXYORsLEUcoeY=
|
github.com/santhosh-tekuri/jsonschema/v5 v5.2.0 h1:WCcC4vZDS1tYNxjWlwRJZQy28r8CMoggKnxNzxsVDMQ=
|
||||||
github.com/santhosh-tekuri/jsonschema/v5 v5.1.1/go.mod h1:FKdcjfQW6rpZSnxxUvEA5H/cDPdvJ/SZJQLWWXWGrZ0=
|
github.com/santhosh-tekuri/jsonschema/v5 v5.2.0/go.mod h1:FKdcjfQW6rpZSnxxUvEA5H/cDPdvJ/SZJQLWWXWGrZ0=
|
||||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||||
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||||
github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
|
github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
|
||||||
github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I=
|
||||||
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4=
|
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4=
|
||||||
github.com/shopspring/decimal v0.0.0-20200227202807-02e2044944cc/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
github.com/shopspring/decimal v0.0.0-20200227202807-02e2044944cc/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
||||||
github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ=
|
github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ=
|
||||||
@@ -1445,6 +1456,7 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
|
|||||||
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
|
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
|
||||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||||
golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM=
|
golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM=
|
||||||
|
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
|
||||||
golang.org/x/net v0.0.0-20210501142056-aec3718b3fa0/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
|
golang.org/x/net v0.0.0-20210501142056-aec3718b3fa0/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
|
||||||
golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
@@ -1562,6 +1574,7 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20201126233918-771906719818/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201126233918-771906719818/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@@ -1695,6 +1708,7 @@ golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4f
|
|||||||
golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
|
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||||
|
|||||||
@@ -42,6 +42,33 @@ func ConvertUtf8ToUtf8mb4() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ConvertVarcharToNVarchar converts database and tables from varchar to nvarchar if it's mssql
|
||||||
|
func ConvertVarcharToNVarchar() error {
|
||||||
|
if x.Dialect().URI().DBType != schemas.MSSQL {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
sess := x.NewSession()
|
||||||
|
defer sess.Close()
|
||||||
|
res, err := sess.QuerySliceString(`SELECT 'ALTER TABLE ' + OBJECT_NAME(SC.object_id) + ' MODIFY SC.name NVARCHAR(' + CONVERT(VARCHAR(5),SC.max_length) + ')'
|
||||||
|
FROM SYS.columns SC
|
||||||
|
JOIN SYS.types ST
|
||||||
|
ON SC.system_type_id = ST.system_type_id
|
||||||
|
AND SC.user_type_id = ST.user_type_id
|
||||||
|
WHERE ST.name ='varchar'`)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, row := range res {
|
||||||
|
if len(row) == 1 {
|
||||||
|
if _, err = sess.Exec(row[0]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// Cell2Int64 converts a xorm.Cell type to int64,
|
// Cell2Int64 converts a xorm.Cell type to int64,
|
||||||
// and handles possible irregular cases.
|
// and handles possible irregular cases.
|
||||||
func Cell2Int64(val xorm.Cell) int64 {
|
func Cell2Int64(val xorm.Cell) int64 {
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ func TestIterate(t *testing.T) {
|
|||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.EqualValues(t, 83, repoCnt)
|
assert.EqualValues(t, 88, repoCnt)
|
||||||
|
|
||||||
err = db.Iterate(db.DefaultContext, nil, func(ctx context.Context, repoUnit *repo_model.RepoUnit) error {
|
err = db.Iterate(db.DefaultContext, nil, func(ctx context.Context, repoUnit *repo_model.RepoUnit) error {
|
||||||
reopUnit2 := repo_model.RepoUnit{ID: repoUnit.ID}
|
reopUnit2 := repo_model.RepoUnit{ID: repoUnit.ID}
|
||||||
|
|||||||
@@ -35,11 +35,11 @@ func TestFind(t *testing.T) {
|
|||||||
var repoUnits []repo_model.RepoUnit
|
var repoUnits []repo_model.RepoUnit
|
||||||
err := db.Find(db.DefaultContext, &opts, &repoUnits)
|
err := db.Find(db.DefaultContext, &opts, &repoUnits)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.EqualValues(t, 83, len(repoUnits))
|
assert.EqualValues(t, 88, len(repoUnits))
|
||||||
|
|
||||||
cnt, err := db.Count(db.DefaultContext, &opts, new(repo_model.RepoUnit))
|
cnt, err := db.Count(db.DefaultContext, &opts, new(repo_model.RepoUnit))
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.EqualValues(t, 83, cnt)
|
assert.EqualValues(t, 88, cnt)
|
||||||
|
|
||||||
repoUnits = make([]repo_model.RepoUnit, 0, 10)
|
repoUnits = make([]repo_model.RepoUnit, 0, 10)
|
||||||
newCnt, err := db.FindAndCount(db.DefaultContext, &opts, &repoUnits)
|
newCnt, err := db.FindAndCount(db.DefaultContext, &opts, &repoUnits)
|
||||||
|
|||||||
@@ -66,3 +66,45 @@
|
|||||||
is_prerelease: true
|
is_prerelease: true
|
||||||
is_tag: false
|
is_tag: false
|
||||||
created_unix: 946684800
|
created_unix: 946684800
|
||||||
|
|
||||||
|
- id: 6
|
||||||
|
repo_id: 57
|
||||||
|
publisher_id: 2
|
||||||
|
tag_name: "v1.0"
|
||||||
|
lower_tag_name: "v1.0"
|
||||||
|
target: "main"
|
||||||
|
title: "v1.0"
|
||||||
|
sha1: "a8a700e8c644c783ba2c6e742bb81bf91e244bff"
|
||||||
|
num_commits: 3
|
||||||
|
is_draft: false
|
||||||
|
is_prerelease: false
|
||||||
|
is_tag: false
|
||||||
|
created_unix: 946684801
|
||||||
|
|
||||||
|
- id: 7
|
||||||
|
repo_id: 57
|
||||||
|
publisher_id: 2
|
||||||
|
tag_name: "v1.1"
|
||||||
|
lower_tag_name: "v1.1"
|
||||||
|
target: "main"
|
||||||
|
title: "v1.1"
|
||||||
|
sha1: "cef06e48f2642cd0dc9597b4bea09f4b3f74aad6"
|
||||||
|
num_commits: 5
|
||||||
|
is_draft: false
|
||||||
|
is_prerelease: false
|
||||||
|
is_tag: false
|
||||||
|
created_unix: 946684802
|
||||||
|
|
||||||
|
- id: 8
|
||||||
|
repo_id: 57
|
||||||
|
publisher_id: 2
|
||||||
|
tag_name: "v2.0"
|
||||||
|
lower_tag_name: "v2.0"
|
||||||
|
target: "main"
|
||||||
|
title: "v2.0"
|
||||||
|
sha1: "7197b56fdc75b453f47c9110938cb46a303579fd"
|
||||||
|
num_commits: 6
|
||||||
|
is_draft: false
|
||||||
|
is_prerelease: false
|
||||||
|
is_tag: false
|
||||||
|
created_unix: 946684803
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
# See models/unit/unit.go for the meaning of the type
|
||||||
-
|
-
|
||||||
id: 1
|
id: 1
|
||||||
repo_id: 1
|
repo_id: 1
|
||||||
@@ -569,3 +570,29 @@
|
|||||||
type: 3
|
type: 3
|
||||||
config: "{\"IgnoreWhitespaceConflicts\":false,\"AllowMerge\":true,\"AllowRebase\":true,\"AllowRebaseMerge\":true,\"AllowSquash\":true}"
|
config: "{\"IgnoreWhitespaceConflicts\":false,\"AllowMerge\":true,\"AllowRebase\":true,\"AllowRebaseMerge\":true,\"AllowSquash\":true}"
|
||||||
created_unix: 946684810
|
created_unix: 946684810
|
||||||
|
|
||||||
|
-
|
||||||
|
id: 85
|
||||||
|
repo_id: 57
|
||||||
|
type: 1
|
||||||
|
created_unix: 946684810
|
||||||
|
-
|
||||||
|
id: 86
|
||||||
|
repo_id: 57
|
||||||
|
type: 2
|
||||||
|
created_unix: 946684810
|
||||||
|
-
|
||||||
|
id: 87
|
||||||
|
repo_id: 57
|
||||||
|
type: 3
|
||||||
|
created_unix: 946684810
|
||||||
|
-
|
||||||
|
id: 88
|
||||||
|
repo_id: 57
|
||||||
|
type: 4
|
||||||
|
created_unix: 946684810
|
||||||
|
-
|
||||||
|
id: 89
|
||||||
|
repo_id: 57
|
||||||
|
type: 5
|
||||||
|
created_unix: 946684810
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
# don't forget to add fixtures in repo_unit.yml
|
||||||
-
|
-
|
||||||
id: 1
|
id: 1
|
||||||
owner_id: 2
|
owner_id: 2
|
||||||
@@ -1634,3 +1635,16 @@
|
|||||||
is_private: true
|
is_private: true
|
||||||
num_issues: 1
|
num_issues: 1
|
||||||
status: 0
|
status: 0
|
||||||
|
|
||||||
|
-
|
||||||
|
id: 57
|
||||||
|
owner_id: 2
|
||||||
|
owner_name: user2
|
||||||
|
lower_name: repo-release
|
||||||
|
name: repo-release
|
||||||
|
default_branch: main
|
||||||
|
is_empty: false
|
||||||
|
is_archived: false
|
||||||
|
is_private: false
|
||||||
|
status: 0
|
||||||
|
num_issues: 0
|
||||||
|
|||||||
@@ -66,7 +66,7 @@
|
|||||||
num_followers: 2
|
num_followers: 2
|
||||||
num_following: 1
|
num_following: 1
|
||||||
num_stars: 2
|
num_stars: 2
|
||||||
num_repos: 11
|
num_repos: 12
|
||||||
num_teams: 0
|
num_teams: 0
|
||||||
num_members: 0
|
num_members: 0
|
||||||
visibility: 0
|
visibility: 0
|
||||||
|
|||||||
@@ -52,84 +52,61 @@ func (err ErrCommentNotExist) Unwrap() error {
|
|||||||
// CommentType defines whether a comment is just a simple comment, an action (like close) or a reference.
|
// CommentType defines whether a comment is just a simple comment, an action (like close) or a reference.
|
||||||
type CommentType int
|
type CommentType int
|
||||||
|
|
||||||
// define unknown comment type
|
// CommentTypeUndefined is used to search for comments of any type
|
||||||
const (
|
const CommentTypeUndefined CommentType = -1
|
||||||
CommentTypeUnknown CommentType = -1
|
|
||||||
)
|
|
||||||
|
|
||||||
// Enumerate all the comment types
|
|
||||||
const (
|
const (
|
||||||
// 0 Plain comment, can be associated with a commit (CommitID > 0) and a line (LineNum > 0)
|
CommentTypeComment CommentType = iota // 0 Plain comment, can be associated with a commit (CommitID > 0) and a line (LineNum > 0)
|
||||||
CommentTypeComment CommentType = iota
|
|
||||||
CommentTypeReopen // 1
|
CommentTypeReopen // 1
|
||||||
CommentTypeClose // 2
|
CommentTypeClose // 2
|
||||||
|
|
||||||
|
CommentTypeIssueRef // 3 References.
|
||||||
|
CommentTypeCommitRef // 4 Reference from a commit (not part of a pull request)
|
||||||
|
CommentTypeCommentRef // 5 Reference from a comment
|
||||||
|
CommentTypePullRef // 6 Reference from a pull request
|
||||||
|
|
||||||
|
CommentTypeLabel // 7 Labels changed
|
||||||
|
CommentTypeMilestone // 8 Milestone changed
|
||||||
|
CommentTypeAssignees // 9 Assignees changed
|
||||||
|
CommentTypeChangeTitle // 10 Change Title
|
||||||
|
CommentTypeDeleteBranch // 11 Delete Branch
|
||||||
|
|
||||||
|
CommentTypeStartTracking // 12 Start a stopwatch for time tracking
|
||||||
|
CommentTypeStopTracking // 13 Stop a stopwatch for time tracking
|
||||||
|
CommentTypeAddTimeManual // 14 Add time manual for time tracking
|
||||||
|
CommentTypeCancelTracking // 15 Cancel a stopwatch for time tracking
|
||||||
|
CommentTypeAddedDeadline // 16 Added a due date
|
||||||
|
CommentTypeModifiedDeadline // 17 Modified the due date
|
||||||
|
CommentTypeRemovedDeadline // 18 Removed a due date
|
||||||
|
|
||||||
|
CommentTypeAddDependency // 19 Dependency added
|
||||||
|
CommentTypeRemoveDependency // 20 Dependency removed
|
||||||
|
|
||||||
|
CommentTypeCode // 21 Comment a line of code
|
||||||
|
CommentTypeReview // 22 Reviews a pull request by giving general feedback
|
||||||
|
|
||||||
|
CommentTypeLock // 23 Lock an issue, giving only collaborators access
|
||||||
|
CommentTypeUnlock // 24 Unlocks a previously locked issue
|
||||||
|
|
||||||
|
CommentTypeChangeTargetBranch // 25 Change pull request's target branch
|
||||||
|
|
||||||
|
CommentTypeDeleteTimeManual // 26 Delete time manual for time tracking
|
||||||
|
|
||||||
|
CommentTypeReviewRequest // 27 add or remove Request from one
|
||||||
|
CommentTypeMergePull // 28 merge pull request
|
||||||
|
CommentTypePullRequestPush // 29 push to PR head branch
|
||||||
|
|
||||||
|
CommentTypeProject // 30 Project changed
|
||||||
|
CommentTypeProjectBoard // 31 Project board changed
|
||||||
|
|
||||||
|
CommentTypeDismissReview // 32 Dismiss Review
|
||||||
|
|
||||||
|
CommentTypeChangeIssueRef // 33 Change issue ref
|
||||||
|
|
||||||
|
CommentTypePRScheduledToAutoMerge // 34 pr was scheduled to auto merge when checks succeed
|
||||||
|
CommentTypePRUnScheduledToAutoMerge // 35 pr was un scheduled to auto merge when checks succeed
|
||||||
|
|
||||||
// 3 References.
|
|
||||||
CommentTypeIssueRef
|
|
||||||
// 4 Reference from a commit (not part of a pull request)
|
|
||||||
CommentTypeCommitRef
|
|
||||||
// 5 Reference from a comment
|
|
||||||
CommentTypeCommentRef
|
|
||||||
// 6 Reference from a pull request
|
|
||||||
CommentTypePullRef
|
|
||||||
// 7 Labels changed
|
|
||||||
CommentTypeLabel
|
|
||||||
// 8 Milestone changed
|
|
||||||
CommentTypeMilestone
|
|
||||||
// 9 Assignees changed
|
|
||||||
CommentTypeAssignees
|
|
||||||
// 10 Change Title
|
|
||||||
CommentTypeChangeTitle
|
|
||||||
// 11 Delete Branch
|
|
||||||
CommentTypeDeleteBranch
|
|
||||||
// 12 Start a stopwatch for time tracking
|
|
||||||
CommentTypeStartTracking
|
|
||||||
// 13 Stop a stopwatch for time tracking
|
|
||||||
CommentTypeStopTracking
|
|
||||||
// 14 Add time manual for time tracking
|
|
||||||
CommentTypeAddTimeManual
|
|
||||||
// 15 Cancel a stopwatch for time tracking
|
|
||||||
CommentTypeCancelTracking
|
|
||||||
// 16 Added a due date
|
|
||||||
CommentTypeAddedDeadline
|
|
||||||
// 17 Modified the due date
|
|
||||||
CommentTypeModifiedDeadline
|
|
||||||
// 18 Removed a due date
|
|
||||||
CommentTypeRemovedDeadline
|
|
||||||
// 19 Dependency added
|
|
||||||
CommentTypeAddDependency
|
|
||||||
// 20 Dependency removed
|
|
||||||
CommentTypeRemoveDependency
|
|
||||||
// 21 Comment a line of code
|
|
||||||
CommentTypeCode
|
|
||||||
// 22 Reviews a pull request by giving general feedback
|
|
||||||
CommentTypeReview
|
|
||||||
// 23 Lock an issue, giving only collaborators access
|
|
||||||
CommentTypeLock
|
|
||||||
// 24 Unlocks a previously locked issue
|
|
||||||
CommentTypeUnlock
|
|
||||||
// 25 Change pull request's target branch
|
|
||||||
CommentTypeChangeTargetBranch
|
|
||||||
// 26 Delete time manual for time tracking
|
|
||||||
CommentTypeDeleteTimeManual
|
|
||||||
// 27 add or remove Request from one
|
|
||||||
CommentTypeReviewRequest
|
|
||||||
// 28 merge pull request
|
|
||||||
CommentTypeMergePull
|
|
||||||
// 29 push to PR head branch
|
|
||||||
CommentTypePullRequestPush
|
|
||||||
// 30 Project changed
|
|
||||||
CommentTypeProject
|
|
||||||
// 31 Project board changed
|
|
||||||
CommentTypeProjectBoard
|
|
||||||
// 32 Dismiss Review
|
|
||||||
CommentTypeDismissReview
|
|
||||||
// 33 Change issue ref
|
|
||||||
CommentTypeChangeIssueRef
|
|
||||||
// 34 pr was scheduled to auto merge when checks succeed
|
|
||||||
CommentTypePRScheduledToAutoMerge
|
|
||||||
// 35 pr was un scheduled to auto merge when checks succeed
|
|
||||||
CommentTypePRUnScheduledToAutoMerge
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var commentStrings = []string{
|
var commentStrings = []string{
|
||||||
@@ -181,7 +158,23 @@ func AsCommentType(typeName string) CommentType {
|
|||||||
return CommentType(index)
|
return CommentType(index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return CommentTypeUnknown
|
return CommentTypeUndefined
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t CommentType) HasContentSupport() bool {
|
||||||
|
switch t {
|
||||||
|
case CommentTypeComment, CommentTypeCode, CommentTypeReview:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t CommentType) HasAttachmentSupport() bool {
|
||||||
|
switch t {
|
||||||
|
case CommentTypeComment, CommentTypeCode, CommentTypeReview:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// RoleDescriptor defines comment tag type
|
// RoleDescriptor defines comment tag type
|
||||||
@@ -1039,7 +1032,7 @@ func (opts *FindCommentsOptions) ToConds() builder.Cond {
|
|||||||
if opts.Before > 0 {
|
if opts.Before > 0 {
|
||||||
cond = cond.And(builder.Lte{"comment.updated_unix": opts.Before})
|
cond = cond.And(builder.Lte{"comment.updated_unix": opts.Before})
|
||||||
}
|
}
|
||||||
if opts.Type != CommentTypeUnknown {
|
if opts.Type != CommentTypeUndefined {
|
||||||
cond = cond.And(builder.Eq{"comment.type": opts.Type})
|
cond = cond.And(builder.Eq{"comment.type": opts.Type})
|
||||||
}
|
}
|
||||||
if opts.Line != 0 {
|
if opts.Line != 0 {
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ func (comments CommentList) getLabelIDs() []int64 {
|
|||||||
return ids.Values()
|
return ids.Values()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (comments CommentList) loadLabels(ctx context.Context) error { //nolint
|
func (comments CommentList) loadLabels(ctx context.Context) error {
|
||||||
if len(comments) == 0 {
|
if len(comments) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -415,7 +415,7 @@ func (comments CommentList) getReviewIDs() []int64 {
|
|||||||
return ids.Values()
|
return ids.Values()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (comments CommentList) loadReviews(ctx context.Context) error { //nolint
|
func (comments CommentList) loadReviews(ctx context.Context) error {
|
||||||
if len(comments) == 0 {
|
if len(comments) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -453,6 +453,14 @@ func (comments CommentList) loadReviews(ctx context.Context) error { //nolint
|
|||||||
|
|
||||||
for _, comment := range comments {
|
for _, comment := range comments {
|
||||||
comment.Review = reviews[comment.ReviewID]
|
comment.Review = reviews[comment.ReviewID]
|
||||||
|
|
||||||
|
// If the comment dismisses a review, we need to load the reviewer to show whose review has been dismissed.
|
||||||
|
// Otherwise, the reviewer is the poster of the comment, so we don't need to load it.
|
||||||
|
if comment.Type == CommentTypeDismissReview {
|
||||||
|
if err := comment.Review.LoadReviewer(ctx); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,8 +64,9 @@ func TestFetchCodeComments(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestAsCommentType(t *testing.T) {
|
func TestAsCommentType(t *testing.T) {
|
||||||
assert.Equal(t, issues_model.CommentTypeUnknown, issues_model.AsCommentType(""))
|
assert.Equal(t, issues_model.CommentType(0), issues_model.CommentTypeComment)
|
||||||
assert.Equal(t, issues_model.CommentTypeUnknown, issues_model.AsCommentType("nonsense"))
|
assert.Equal(t, issues_model.CommentTypeUndefined, issues_model.AsCommentType(""))
|
||||||
|
assert.Equal(t, issues_model.CommentTypeUndefined, issues_model.AsCommentType("nonsense"))
|
||||||
assert.Equal(t, issues_model.CommentTypeComment, issues_model.AsCommentType("comment"))
|
assert.Equal(t, issues_model.CommentTypeComment, issues_model.AsCommentType("comment"))
|
||||||
assert.Equal(t, issues_model.CommentTypePRUnScheduledToAutoMerge, issues_model.AsCommentType("pull_cancel_scheduled_merge"))
|
assert.Equal(t, issues_model.CommentTypePRUnScheduledToAutoMerge, issues_model.AsCommentType("pull_cancel_scheduled_merge"))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -267,7 +267,7 @@ func (issue *Issue) LoadPullRequest(ctx context.Context) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (issue *Issue) loadComments(ctx context.Context) (err error) {
|
func (issue *Issue) loadComments(ctx context.Context) (err error) {
|
||||||
return issue.loadCommentsByType(ctx, CommentTypeUnknown)
|
return issue.loadCommentsByType(ctx, CommentTypeUndefined)
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadDiscussComments loads discuss comments
|
// LoadDiscussComments loads discuss comments
|
||||||
|
|||||||
@@ -418,6 +418,12 @@ func DeleteTeam(t *organization.Team) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, tm := range t.Members {
|
||||||
|
if err := removeInvalidOrgUser(ctx, tm.ID, t.OrgID); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Update organization number of teams.
|
// Update organization number of teams.
|
||||||
if _, err := db.Exec(ctx, "UPDATE `user` SET num_teams=num_teams-1 WHERE id=?", t.OrgID); err != nil {
|
if _, err := db.Exec(ctx, "UPDATE `user` SET num_teams=num_teams-1 WHERE id=?", t.OrgID); err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -567,16 +573,19 @@ func removeTeamMember(ctx context.Context, team *organization.Team, userID int64
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return removeInvalidOrgUser(ctx, userID, team.OrgID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func removeInvalidOrgUser(ctx context.Context, userID, orgID int64) error {
|
||||||
// Check if the user is a member of any team in the organization.
|
// Check if the user is a member of any team in the organization.
|
||||||
if count, err := e.Count(&organization.TeamUser{
|
if count, err := db.GetEngine(ctx).Count(&organization.TeamUser{
|
||||||
UID: userID,
|
UID: userID,
|
||||||
OrgID: team.OrgID,
|
OrgID: orgID,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return err
|
return err
|
||||||
} else if count == 0 {
|
} else if count == 0 {
|
||||||
return removeOrgUser(ctx, team.OrgID, userID)
|
return removeOrgUser(ctx, orgID, userID)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -338,9 +338,10 @@ func CreateOrganization(org *Organization, owner *user_model.User) (err error) {
|
|||||||
units := make([]TeamUnit, 0, len(unit.AllRepoUnitTypes))
|
units := make([]TeamUnit, 0, len(unit.AllRepoUnitTypes))
|
||||||
for _, tp := range unit.AllRepoUnitTypes {
|
for _, tp := range unit.AllRepoUnitTypes {
|
||||||
units = append(units, TeamUnit{
|
units = append(units, TeamUnit{
|
||||||
OrgID: org.ID,
|
OrgID: org.ID,
|
||||||
TeamID: t.ID,
|
TeamID: t.ID,
|
||||||
Type: tp,
|
Type: tp,
|
||||||
|
AccessMode: perm.AccessModeOwner,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -235,12 +235,12 @@ func TestSearchRepository(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "AllPublic/PublicRepositoriesOfUserIncludingCollaborative",
|
name: "AllPublic/PublicRepositoriesOfUserIncludingCollaborative",
|
||||||
opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 15, AllPublic: true, Template: util.OptionalBoolFalse},
|
opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 15, AllPublic: true, Template: util.OptionalBoolFalse},
|
||||||
count: 29,
|
count: 30,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "AllPublic/PublicAndPrivateRepositoriesOfUserIncludingCollaborative",
|
name: "AllPublic/PublicAndPrivateRepositoriesOfUserIncludingCollaborative",
|
||||||
opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 15, Private: true, AllPublic: true, AllLimited: true, Template: util.OptionalBoolFalse},
|
opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 15, Private: true, AllPublic: true, AllLimited: true, Template: util.OptionalBoolFalse},
|
||||||
count: 34,
|
count: 35,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "AllPublic/PublicAndPrivateRepositoriesOfUserIncludingCollaborativeByName",
|
name: "AllPublic/PublicAndPrivateRepositoriesOfUserIncludingCollaborativeByName",
|
||||||
@@ -255,7 +255,7 @@ func TestSearchRepository(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "AllPublic/PublicRepositoriesOfOrganization",
|
name: "AllPublic/PublicRepositoriesOfOrganization",
|
||||||
opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 17, AllPublic: true, Collaborate: util.OptionalBoolFalse, Template: util.OptionalBoolFalse},
|
opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 17, AllPublic: true, Collaborate: util.OptionalBoolFalse, Template: util.OptionalBoolFalse},
|
||||||
count: 29,
|
count: 30,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "AllTemplates",
|
name: "AllTemplates",
|
||||||
|
|||||||
@@ -194,14 +194,16 @@ func (opts *FindTopicOptions) toConds() builder.Cond {
|
|||||||
// FindTopics retrieves the topics via FindTopicOptions
|
// FindTopics retrieves the topics via FindTopicOptions
|
||||||
func FindTopics(opts *FindTopicOptions) ([]*Topic, int64, error) {
|
func FindTopics(opts *FindTopicOptions) ([]*Topic, int64, error) {
|
||||||
sess := db.GetEngine(db.DefaultContext).Select("topic.*").Where(opts.toConds())
|
sess := db.GetEngine(db.DefaultContext).Select("topic.*").Where(opts.toConds())
|
||||||
|
orderBy := "topic.repo_count DESC"
|
||||||
if opts.RepoID > 0 {
|
if opts.RepoID > 0 {
|
||||||
sess.Join("INNER", "repo_topic", "repo_topic.topic_id = topic.id")
|
sess.Join("INNER", "repo_topic", "repo_topic.topic_id = topic.id")
|
||||||
|
orderBy = "topic.name" // when render topics for a repo, it's better to sort them by name, to get consistent result
|
||||||
}
|
}
|
||||||
if opts.PageSize != 0 && opts.Page != 0 {
|
if opts.PageSize != 0 && opts.Page != 0 {
|
||||||
sess = db.SetSessionPagination(sess, opts)
|
sess = db.SetSessionPagination(sess, opts)
|
||||||
}
|
}
|
||||||
topics := make([]*Topic, 0, 10)
|
topics := make([]*Topic, 0, 10)
|
||||||
total, err := sess.Desc("topic.repo_count").FindAndCount(&topics)
|
total, err := sess.OrderBy(orderBy).FindAndCount(&topics)
|
||||||
return topics, total, err
|
return topics, total, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -99,40 +99,60 @@ func detectMatched(commit *git.Commit, triggedEvent webhook_module.HookEventType
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch triggedEvent {
|
switch triggedEvent {
|
||||||
case webhook_module.HookEventCreate,
|
case // events with no activity types
|
||||||
|
webhook_module.HookEventCreate,
|
||||||
webhook_module.HookEventDelete,
|
webhook_module.HookEventDelete,
|
||||||
webhook_module.HookEventFork,
|
webhook_module.HookEventFork,
|
||||||
webhook_module.HookEventIssueAssign,
|
// FIXME: `wiki` event should match `gollum` event
|
||||||
webhook_module.HookEventIssueLabel,
|
// See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#gollum
|
||||||
webhook_module.HookEventIssueMilestone,
|
webhook_module.HookEventWiki:
|
||||||
webhook_module.HookEventPullRequestAssign,
|
|
||||||
webhook_module.HookEventPullRequestLabel,
|
|
||||||
webhook_module.HookEventPullRequestMilestone,
|
|
||||||
webhook_module.HookEventPullRequestComment,
|
|
||||||
webhook_module.HookEventPullRequestReviewApproved,
|
|
||||||
webhook_module.HookEventPullRequestReviewRejected,
|
|
||||||
webhook_module.HookEventPullRequestReviewComment,
|
|
||||||
webhook_module.HookEventWiki,
|
|
||||||
webhook_module.HookEventRepository,
|
|
||||||
webhook_module.HookEventRelease,
|
|
||||||
webhook_module.HookEventPackage:
|
|
||||||
if len(evt.Acts()) != 0 {
|
if len(evt.Acts()) != 0 {
|
||||||
log.Warn("Ignore unsupported %s event arguments %v", triggedEvent, evt.Acts())
|
log.Warn("Ignore unsupported %s event arguments %v", triggedEvent, evt.Acts())
|
||||||
}
|
}
|
||||||
// no special filter parameters for these events, just return true if name matched
|
// no special filter parameters for these events, just return true if name matched
|
||||||
return true
|
return true
|
||||||
|
|
||||||
case webhook_module.HookEventPush:
|
case // push
|
||||||
|
webhook_module.HookEventPush:
|
||||||
return matchPushEvent(commit, payload.(*api.PushPayload), evt)
|
return matchPushEvent(commit, payload.(*api.PushPayload), evt)
|
||||||
|
|
||||||
case webhook_module.HookEventIssues:
|
case // issues
|
||||||
|
webhook_module.HookEventIssues,
|
||||||
|
webhook_module.HookEventIssueAssign,
|
||||||
|
webhook_module.HookEventIssueLabel,
|
||||||
|
webhook_module.HookEventIssueMilestone:
|
||||||
return matchIssuesEvent(commit, payload.(*api.IssuePayload), evt)
|
return matchIssuesEvent(commit, payload.(*api.IssuePayload), evt)
|
||||||
|
|
||||||
case webhook_module.HookEventPullRequest, webhook_module.HookEventPullRequestSync:
|
case // issue_comment
|
||||||
|
webhook_module.HookEventIssueComment,
|
||||||
|
// `pull_request_comment` is same as `issue_comment`
|
||||||
|
// See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_comment-use-issue_comment
|
||||||
|
webhook_module.HookEventPullRequestComment:
|
||||||
|
return matchIssueCommentEvent(commit, payload.(*api.IssueCommentPayload), evt)
|
||||||
|
|
||||||
|
case // pull_request
|
||||||
|
webhook_module.HookEventPullRequest,
|
||||||
|
webhook_module.HookEventPullRequestSync,
|
||||||
|
webhook_module.HookEventPullRequestAssign,
|
||||||
|
webhook_module.HookEventPullRequestLabel:
|
||||||
return matchPullRequestEvent(commit, payload.(*api.PullRequestPayload), evt)
|
return matchPullRequestEvent(commit, payload.(*api.PullRequestPayload), evt)
|
||||||
|
|
||||||
case webhook_module.HookEventIssueComment:
|
case // pull_request_review
|
||||||
return matchIssueCommentEvent(commit, payload.(*api.IssueCommentPayload), evt)
|
webhook_module.HookEventPullRequestReviewApproved,
|
||||||
|
webhook_module.HookEventPullRequestReviewRejected:
|
||||||
|
return matchPullRequestReviewEvent(commit, payload.(*api.PullRequestPayload), evt)
|
||||||
|
|
||||||
|
case // pull_request_review_comment
|
||||||
|
webhook_module.HookEventPullRequestReviewComment:
|
||||||
|
return matchPullRequestReviewCommentEvent(commit, payload.(*api.PullRequestPayload), evt)
|
||||||
|
|
||||||
|
case // release
|
||||||
|
webhook_module.HookEventRelease:
|
||||||
|
return matchReleaseEvent(commit, payload.(*api.ReleasePayload), evt)
|
||||||
|
|
||||||
|
case // registry_package
|
||||||
|
webhook_module.HookEventPackage:
|
||||||
|
return matchPackageEvent(commit, payload.(*api.PackagePayload), evt)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
log.Warn("unsupported event %q", triggedEvent)
|
log.Warn("unsupported event %q", triggedEvent)
|
||||||
@@ -249,8 +269,24 @@ func matchIssuesEvent(commit *git.Commit, issuePayload *api.IssuePayload, evt *j
|
|||||||
for cond, vals := range evt.Acts() {
|
for cond, vals := range evt.Acts() {
|
||||||
switch cond {
|
switch cond {
|
||||||
case "types":
|
case "types":
|
||||||
|
// See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#issues
|
||||||
|
// Actions with the same name:
|
||||||
|
// opened, edited, closed, reopened, assigned, unassigned, milestoned, demilestoned
|
||||||
|
// Actions need to be converted:
|
||||||
|
// label_updated -> labeled
|
||||||
|
// label_cleared -> unlabeled
|
||||||
|
// Unsupported activity types:
|
||||||
|
// deleted, transferred, pinned, unpinned, locked, unlocked
|
||||||
|
|
||||||
|
action := issuePayload.Action
|
||||||
|
switch action {
|
||||||
|
case api.HookIssueLabelUpdated:
|
||||||
|
action = "labeled"
|
||||||
|
case api.HookIssueLabelCleared:
|
||||||
|
action = "unlabeled"
|
||||||
|
}
|
||||||
for _, val := range vals {
|
for _, val := range vals {
|
||||||
if glob.MustCompile(val, '/').Match(string(issuePayload.Action)) {
|
if glob.MustCompile(val, '/').Match(string(action)) {
|
||||||
matchTimes++
|
matchTimes++
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -265,8 +301,9 @@ func matchIssuesEvent(commit *git.Commit, issuePayload *api.IssuePayload, evt *j
|
|||||||
func matchPullRequestEvent(commit *git.Commit, prPayload *api.PullRequestPayload, evt *jobparser.Event) bool {
|
func matchPullRequestEvent(commit *git.Commit, prPayload *api.PullRequestPayload, evt *jobparser.Event) bool {
|
||||||
// with no special filter parameters
|
// with no special filter parameters
|
||||||
if len(evt.Acts()) == 0 {
|
if len(evt.Acts()) == 0 {
|
||||||
// defaultly, only pull request opened and synchronized will trigger workflow
|
// defaultly, only pull request `opened`, `reopened` and `synchronized` will trigger workflow
|
||||||
return prPayload.Action == api.HookIssueSynchronized || prPayload.Action == api.HookIssueOpened
|
// See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request
|
||||||
|
return prPayload.Action == api.HookIssueSynchronized || prPayload.Action == api.HookIssueOpened || prPayload.Action == api.HookIssueReOpened
|
||||||
}
|
}
|
||||||
|
|
||||||
matchTimes := 0
|
matchTimes := 0
|
||||||
@@ -274,9 +311,24 @@ func matchPullRequestEvent(commit *git.Commit, prPayload *api.PullRequestPayload
|
|||||||
for cond, vals := range evt.Acts() {
|
for cond, vals := range evt.Acts() {
|
||||||
switch cond {
|
switch cond {
|
||||||
case "types":
|
case "types":
|
||||||
|
// See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request
|
||||||
|
// Actions with the same name:
|
||||||
|
// opened, edited, closed, reopened, assigned, unassigned
|
||||||
|
// Actions need to be converted:
|
||||||
|
// synchronized -> synchronize
|
||||||
|
// label_updated -> labeled
|
||||||
|
// label_cleared -> unlabeled
|
||||||
|
// Unsupported activity types:
|
||||||
|
// converted_to_draft, ready_for_review, locked, unlocked, review_requested, review_request_removed, auto_merge_enabled, auto_merge_disabled
|
||||||
|
|
||||||
action := prPayload.Action
|
action := prPayload.Action
|
||||||
if prPayload.Action == api.HookIssueSynchronized {
|
switch action {
|
||||||
|
case api.HookIssueSynchronized:
|
||||||
action = "synchronize"
|
action = "synchronize"
|
||||||
|
case api.HookIssueLabelUpdated:
|
||||||
|
action = "labeled"
|
||||||
|
case api.HookIssueLabelCleared:
|
||||||
|
action = "unlabeled"
|
||||||
}
|
}
|
||||||
log.Trace("matching pull_request %s with %v", action, vals)
|
log.Trace("matching pull_request %s with %v", action, vals)
|
||||||
for _, val := range vals {
|
for _, val := range vals {
|
||||||
@@ -347,6 +399,14 @@ func matchIssueCommentEvent(commit *git.Commit, issueCommentPayload *api.IssueCo
|
|||||||
for cond, vals := range evt.Acts() {
|
for cond, vals := range evt.Acts() {
|
||||||
switch cond {
|
switch cond {
|
||||||
case "types":
|
case "types":
|
||||||
|
// See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#issue_comment
|
||||||
|
// Actions with the same name:
|
||||||
|
// created, edited, deleted
|
||||||
|
// Actions need to be converted:
|
||||||
|
// NONE
|
||||||
|
// Unsupported activity types:
|
||||||
|
// NONE
|
||||||
|
|
||||||
for _, val := range vals {
|
for _, val := range vals {
|
||||||
if glob.MustCompile(val, '/').Match(string(issueCommentPayload.Action)) {
|
if glob.MustCompile(val, '/').Match(string(issueCommentPayload.Action)) {
|
||||||
matchTimes++
|
matchTimes++
|
||||||
@@ -354,7 +414,179 @@ func matchIssueCommentEvent(commit *git.Commit, issueCommentPayload *api.IssueCo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
log.Warn("issue comment unsupported condition %q", cond)
|
log.Warn("issue comment event unsupported condition %q", cond)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return matchTimes == len(evt.Acts())
|
||||||
|
}
|
||||||
|
|
||||||
|
func matchPullRequestReviewEvent(commit *git.Commit, prPayload *api.PullRequestPayload, evt *jobparser.Event) bool {
|
||||||
|
// with no special filter parameters
|
||||||
|
if len(evt.Acts()) == 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
matchTimes := 0
|
||||||
|
// all acts conditions should be satisfied
|
||||||
|
for cond, vals := range evt.Acts() {
|
||||||
|
switch cond {
|
||||||
|
case "types":
|
||||||
|
// See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_review
|
||||||
|
// Activity types with the same name:
|
||||||
|
// NONE
|
||||||
|
// Activity types need to be converted:
|
||||||
|
// reviewed -> submitted
|
||||||
|
// reviewed -> edited
|
||||||
|
// Unsupported activity types:
|
||||||
|
// dismissed
|
||||||
|
|
||||||
|
actions := make([]string, 0)
|
||||||
|
if prPayload.Action == api.HookIssueReviewed {
|
||||||
|
// the `reviewed` HookIssueAction can match the two activity types: `submitted` and `edited`
|
||||||
|
// See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_review
|
||||||
|
actions = append(actions, "submitted", "edited")
|
||||||
|
}
|
||||||
|
|
||||||
|
matched := false
|
||||||
|
for _, val := range vals {
|
||||||
|
for _, action := range actions {
|
||||||
|
if glob.MustCompile(val, '/').Match(action) {
|
||||||
|
matched = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if matched {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if matched {
|
||||||
|
matchTimes++
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
log.Warn("pull request review event unsupported condition %q", cond)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return matchTimes == len(evt.Acts())
|
||||||
|
}
|
||||||
|
|
||||||
|
func matchPullRequestReviewCommentEvent(commit *git.Commit, prPayload *api.PullRequestPayload, evt *jobparser.Event) bool {
|
||||||
|
// with no special filter parameters
|
||||||
|
if len(evt.Acts()) == 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
matchTimes := 0
|
||||||
|
// all acts conditions should be satisfied
|
||||||
|
for cond, vals := range evt.Acts() {
|
||||||
|
switch cond {
|
||||||
|
case "types":
|
||||||
|
// See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_review_comment
|
||||||
|
// Activity types with the same name:
|
||||||
|
// NONE
|
||||||
|
// Activity types need to be converted:
|
||||||
|
// reviewed -> created
|
||||||
|
// reviewed -> edited
|
||||||
|
// Unsupported activity types:
|
||||||
|
// deleted
|
||||||
|
|
||||||
|
actions := make([]string, 0)
|
||||||
|
if prPayload.Action == api.HookIssueReviewed {
|
||||||
|
// the `reviewed` HookIssueAction can match the two activity types: `created` and `edited`
|
||||||
|
// See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_review_comment
|
||||||
|
actions = append(actions, "created", "edited")
|
||||||
|
}
|
||||||
|
|
||||||
|
matched := false
|
||||||
|
for _, val := range vals {
|
||||||
|
for _, action := range actions {
|
||||||
|
if glob.MustCompile(val, '/').Match(action) {
|
||||||
|
matched = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if matched {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if matched {
|
||||||
|
matchTimes++
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
log.Warn("pull request review comment event unsupported condition %q", cond)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return matchTimes == len(evt.Acts())
|
||||||
|
}
|
||||||
|
|
||||||
|
func matchReleaseEvent(commit *git.Commit, payload *api.ReleasePayload, evt *jobparser.Event) bool {
|
||||||
|
// with no special filter parameters
|
||||||
|
if len(evt.Acts()) == 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
matchTimes := 0
|
||||||
|
// all acts conditions should be satisfied
|
||||||
|
for cond, vals := range evt.Acts() {
|
||||||
|
switch cond {
|
||||||
|
case "types":
|
||||||
|
// See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#release
|
||||||
|
// Activity types with the same name:
|
||||||
|
// published
|
||||||
|
// Activity types need to be converted:
|
||||||
|
// updated -> edited
|
||||||
|
// Unsupported activity types:
|
||||||
|
// unpublished, created, deleted, prereleased, released
|
||||||
|
|
||||||
|
action := payload.Action
|
||||||
|
switch action {
|
||||||
|
case api.HookReleaseUpdated:
|
||||||
|
action = "edited"
|
||||||
|
}
|
||||||
|
for _, val := range vals {
|
||||||
|
if glob.MustCompile(val, '/').Match(string(action)) {
|
||||||
|
matchTimes++
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
log.Warn("release event unsupported condition %q", cond)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return matchTimes == len(evt.Acts())
|
||||||
|
}
|
||||||
|
|
||||||
|
func matchPackageEvent(commit *git.Commit, payload *api.PackagePayload, evt *jobparser.Event) bool {
|
||||||
|
// with no special filter parameters
|
||||||
|
if len(evt.Acts()) == 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
matchTimes := 0
|
||||||
|
// all acts conditions should be satisfied
|
||||||
|
for cond, vals := range evt.Acts() {
|
||||||
|
switch cond {
|
||||||
|
case "types":
|
||||||
|
// See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#registry_package
|
||||||
|
// Activity types with the same name:
|
||||||
|
// NONE
|
||||||
|
// Activity types need to be converted:
|
||||||
|
// created -> published
|
||||||
|
// Unsupported activity types:
|
||||||
|
// updated
|
||||||
|
|
||||||
|
action := payload.Action
|
||||||
|
switch action {
|
||||||
|
case api.HookPackageCreated:
|
||||||
|
action = "published"
|
||||||
|
}
|
||||||
|
for _, val := range vals {
|
||||||
|
if glob.MustCompile(val, '/').Match(string(action)) {
|
||||||
|
matchTimes++
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
log.Warn("package event unsupported condition %q", cond)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return matchTimes == len(evt.Acts())
|
return matchTimes == len(evt.Acts())
|
||||||
|
|||||||
111
modules/actions/workflows_test.go
Normal file
111
modules/actions/workflows_test.go
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package actions
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/modules/git"
|
||||||
|
api "code.gitea.io/gitea/modules/structs"
|
||||||
|
webhook_module "code.gitea.io/gitea/modules/webhook"
|
||||||
|
|
||||||
|
"github.com/nektos/act/pkg/jobparser"
|
||||||
|
"github.com/nektos/act/pkg/model"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDetectMatched(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
desc string
|
||||||
|
commit *git.Commit
|
||||||
|
triggedEvent webhook_module.HookEventType
|
||||||
|
payload api.Payloader
|
||||||
|
yamlOn string
|
||||||
|
expected bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
desc: "HookEventCreate(create) matches githubEventCreate(create)",
|
||||||
|
triggedEvent: webhook_module.HookEventCreate,
|
||||||
|
payload: nil,
|
||||||
|
yamlOn: "on: create",
|
||||||
|
expected: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "HookEventIssues(issues) `opened` action matches githubEventIssues(issues)",
|
||||||
|
triggedEvent: webhook_module.HookEventIssues,
|
||||||
|
payload: &api.IssuePayload{Action: api.HookIssueOpened},
|
||||||
|
yamlOn: "on: issues",
|
||||||
|
expected: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "HookEventIssues(issues) `milestoned` action matches githubEventIssues(issues)",
|
||||||
|
triggedEvent: webhook_module.HookEventIssues,
|
||||||
|
payload: &api.IssuePayload{Action: api.HookIssueMilestoned},
|
||||||
|
yamlOn: "on: issues",
|
||||||
|
expected: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "HookEventPullRequestSync(pull_request_sync) matches githubEventPullRequest(pull_request)",
|
||||||
|
triggedEvent: webhook_module.HookEventPullRequestSync,
|
||||||
|
payload: &api.PullRequestPayload{Action: api.HookIssueSynchronized},
|
||||||
|
yamlOn: "on: pull_request",
|
||||||
|
expected: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "HookEventPullRequest(pull_request) `label_updated` action doesn't match githubEventPullRequest(pull_request) with no activity type",
|
||||||
|
triggedEvent: webhook_module.HookEventPullRequest,
|
||||||
|
payload: &api.PullRequestPayload{Action: api.HookIssueLabelUpdated},
|
||||||
|
yamlOn: "on: pull_request",
|
||||||
|
expected: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "HookEventPullRequest(pull_request) `label_updated` action matches githubEventPullRequest(pull_request) with `label` activity type",
|
||||||
|
triggedEvent: webhook_module.HookEventPullRequest,
|
||||||
|
payload: &api.PullRequestPayload{Action: api.HookIssueLabelUpdated},
|
||||||
|
yamlOn: "on:\n pull_request:\n types: [labeled]",
|
||||||
|
expected: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "HookEventPullRequestReviewComment(pull_request_review_comment) matches githubEventPullRequestReviewComment(pull_request_review_comment)",
|
||||||
|
triggedEvent: webhook_module.HookEventPullRequestReviewComment,
|
||||||
|
payload: &api.PullRequestPayload{Action: api.HookIssueReviewed},
|
||||||
|
yamlOn: "on:\n pull_request_review_comment:\n types: [created]",
|
||||||
|
expected: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "HookEventPullRequestReviewRejected(pull_request_review_rejected) doesn't match githubEventPullRequestReview(pull_request_review) with `dismissed` activity type (we don't support `dismissed` at present)",
|
||||||
|
triggedEvent: webhook_module.HookEventPullRequestReviewRejected,
|
||||||
|
payload: &api.PullRequestPayload{Action: api.HookIssueReviewed},
|
||||||
|
yamlOn: "on:\n pull_request_review:\n types: [dismissed]",
|
||||||
|
expected: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "HookEventRelease(release) `published` action matches githubEventRelease(release) with `published` activity type",
|
||||||
|
triggedEvent: webhook_module.HookEventRelease,
|
||||||
|
payload: &api.ReleasePayload{Action: api.HookReleasePublished},
|
||||||
|
yamlOn: "on:\n release:\n types: [published]",
|
||||||
|
expected: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "HookEventPackage(package) `created` action doesn't match githubEventRegistryPackage(registry_package) with `updated` activity type",
|
||||||
|
triggedEvent: webhook_module.HookEventPackage,
|
||||||
|
payload: &api.PackagePayload{Action: api.HookPackageCreated},
|
||||||
|
yamlOn: "on:\n registry_package:\n types: [updated]",
|
||||||
|
expected: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.desc, func(t *testing.T) {
|
||||||
|
workflow, err := model.ReadWorkflow(bytes.NewReader([]byte(tc.yamlOn)))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
evts, err := jobparser.ParseRawOn(&workflow.RawOn)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Len(t, evts, 1)
|
||||||
|
assert.Equal(t, tc.expected, detectMatched(tc.commit, tc.triggedEvent, tc.payload, evts[0]))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
2
modules/cache/cache_redis.go
vendored
2
modules/cache/cache_redis.go
vendored
@@ -12,7 +12,7 @@ import (
|
|||||||
"code.gitea.io/gitea/modules/nosql"
|
"code.gitea.io/gitea/modules/nosql"
|
||||||
|
|
||||||
"gitea.com/go-chi/cache"
|
"gitea.com/go-chi/cache"
|
||||||
"github.com/go-redis/redis/v8"
|
"github.com/redis/go-redis/v9"
|
||||||
)
|
)
|
||||||
|
|
||||||
// RedisCacher represents a redis cache adapter implementation.
|
// RedisCacher represents a redis cache adapter implementation.
|
||||||
|
|||||||
@@ -337,7 +337,7 @@ func RepoRefForAPI(next http.Handler) http.Handler {
|
|||||||
if git.IsErrNotExist(err) {
|
if git.IsErrNotExist(err) {
|
||||||
ctx.NotFound()
|
ctx.NotFound()
|
||||||
} else {
|
} else {
|
||||||
ctx.Error(http.StatusInternalServerError, "GetBlobByPath", err)
|
ctx.Error(http.StatusInternalServerError, "GetCommit", err)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,10 @@
|
|||||||
package context
|
package context
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
auth_model "code.gitea.io/gitea/models/auth"
|
||||||
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/models/unit"
|
"code.gitea.io/gitea/models/unit"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
)
|
)
|
||||||
@@ -106,3 +110,32 @@ func RequireRepoReaderOr(unitTypes ...unit.Type) func(ctx *Context) {
|
|||||||
ctx.NotFound(ctx.Req.URL.RequestURI(), nil)
|
ctx.NotFound(ctx.Req.URL.RequestURI(), nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RequireRepoScopedToken check whether personal access token has repo scope
|
||||||
|
func CheckRepoScopedToken(ctx *Context, repo *repo_model.Repository) {
|
||||||
|
if !ctx.IsBasicAuth || ctx.Data["IsApiToken"] != true {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
scope, ok := ctx.Data["ApiTokenScope"].(auth_model.AccessTokenScope)
|
||||||
|
if ok { // it's a personal access token but not oauth2 token
|
||||||
|
var scopeMatched bool
|
||||||
|
scopeMatched, err = scope.HasScope(auth_model.AccessTokenScopeRepo)
|
||||||
|
if err != nil {
|
||||||
|
ctx.ServerError("HasScope", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !scopeMatched && !repo.IsPrivate {
|
||||||
|
scopeMatched, err = scope.HasScope(auth_model.AccessTokenScopePublicRepo)
|
||||||
|
if err != nil {
|
||||||
|
ctx.ServerError("HasScope", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !scopeMatched {
|
||||||
|
ctx.Error(http.StatusForbidden)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import (
|
|||||||
|
|
||||||
"code.gitea.io/gitea/modules/process"
|
"code.gitea.io/gitea/modules/process"
|
||||||
|
|
||||||
"github.com/go-redis/redis/v8"
|
"github.com/redis/go-redis/v9"
|
||||||
"github.com/syndtr/goleveldb/leveldb"
|
"github.com/syndtr/goleveldb/leveldb"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import (
|
|||||||
|
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
|
||||||
"github.com/go-redis/redis/v8"
|
"github.com/redis/go-redis/v9"
|
||||||
)
|
)
|
||||||
|
|
||||||
var replacer = strings.NewReplacer("_", "", "-", "")
|
var replacer = strings.NewReplacer("_", "", "-", "")
|
||||||
@@ -193,10 +193,6 @@ func getRedisOptions(uri *url.URL) *redis.UniversalOptions {
|
|||||||
opts.MinIdleConns, _ = strconv.Atoi(v[0])
|
opts.MinIdleConns, _ = strconv.Atoi(v[0])
|
||||||
case "pooltimeout":
|
case "pooltimeout":
|
||||||
opts.PoolTimeout = valToTimeDuration(v)
|
opts.PoolTimeout = valToTimeDuration(v)
|
||||||
case "idletimeout":
|
|
||||||
opts.IdleTimeout = valToTimeDuration(v)
|
|
||||||
case "idlecheckfrequency":
|
|
||||||
opts.IdleCheckFrequency = valToTimeDuration(v)
|
|
||||||
case "maxredirects":
|
case "maxredirects":
|
||||||
opts.MaxRedirects, _ = strconv.Atoi(v[0])
|
opts.MaxRedirects, _ = strconv.Atoi(v[0])
|
||||||
case "readonly":
|
case "readonly":
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import (
|
|||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/nosql"
|
"code.gitea.io/gitea/modules/nosql"
|
||||||
|
|
||||||
"github.com/go-redis/redis/v8"
|
"github.com/redis/go-redis/v9"
|
||||||
)
|
)
|
||||||
|
|
||||||
// RedisQueueType is the type for redis queue
|
// RedisQueueType is the type for redis queue
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ package queue
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/go-redis/redis/v8"
|
"github.com/redis/go-redis/v9"
|
||||||
)
|
)
|
||||||
|
|
||||||
// RedisUniqueQueueType is the type for redis queue
|
// RedisUniqueQueueType is the type for redis queue
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ import (
|
|||||||
"code.gitea.io/gitea/modules/nosql"
|
"code.gitea.io/gitea/modules/nosql"
|
||||||
|
|
||||||
"gitea.com/go-chi/session"
|
"gitea.com/go-chi/session"
|
||||||
"github.com/go-redis/redis/v8"
|
"github.com/redis/go-redis/v9"
|
||||||
)
|
)
|
||||||
|
|
||||||
// RedisStore represents a redis session store implementation.
|
// RedisStore represents a redis session store implementation.
|
||||||
|
|||||||
@@ -21,9 +21,10 @@ var CORSConfig = struct {
|
|||||||
Headers []string
|
Headers []string
|
||||||
XFrameOptions string
|
XFrameOptions string
|
||||||
}{
|
}{
|
||||||
Enabled: false,
|
AllowDomain: []string{"*"},
|
||||||
MaxAge: 10 * time.Minute,
|
Methods: []string{"GET", "HEAD", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"},
|
||||||
Headers: []string{"Content-Type", "User-Agent"},
|
Headers: []string{"Content-Type", "User-Agent"},
|
||||||
|
MaxAge: 10 * time.Minute,
|
||||||
XFrameOptions: "SAMEORIGIN",
|
XFrameOptions: "SAMEORIGIN",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ var UI = struct {
|
|||||||
GraphMaxCommitNum: 100,
|
GraphMaxCommitNum: 100,
|
||||||
CodeCommentLines: 4,
|
CodeCommentLines: 4,
|
||||||
ReactionMaxUserNum: 10,
|
ReactionMaxUserNum: 10,
|
||||||
ThemeColorMetaTag: `#6cc644`,
|
ThemeColorMetaTag: ``,
|
||||||
MaxDisplayFileSize: 8388608,
|
MaxDisplayFileSize: 8388608,
|
||||||
DefaultTheme: `auto`,
|
DefaultTheme: `auto`,
|
||||||
Themes: []string{`auto`, `gitea`, `arc-green`},
|
Themes: []string{`auto`, `gitea`, `arc-green`},
|
||||||
|
|||||||
@@ -30,8 +30,8 @@ type OrganizationPermissions struct {
|
|||||||
// CreateOrgOption options for creating an organization
|
// CreateOrgOption options for creating an organization
|
||||||
type CreateOrgOption struct {
|
type CreateOrgOption struct {
|
||||||
// required: true
|
// required: true
|
||||||
UserName string `json:"username" binding:"Required"`
|
UserName string `json:"username" binding:"Required;Username;MaxSize(40)"`
|
||||||
FullName string `json:"full_name"`
|
FullName string `json:"full_name" binding:"MaxSize(100)"`
|
||||||
Description string `json:"description" binding:"MaxSize(255)"`
|
Description string `json:"description" binding:"MaxSize(255)"`
|
||||||
Website string `json:"website" binding:"ValidUrl;MaxSize(255)"`
|
Website string `json:"website" binding:"ValidUrl;MaxSize(255)"`
|
||||||
Location string `json:"location" binding:"MaxSize(50)"`
|
Location string `json:"location" binding:"MaxSize(50)"`
|
||||||
@@ -45,7 +45,7 @@ type CreateOrgOption struct {
|
|||||||
|
|
||||||
// EditOrgOption options for editing an organization
|
// EditOrgOption options for editing an organization
|
||||||
type EditOrgOption struct {
|
type EditOrgOption struct {
|
||||||
FullName string `json:"full_name"`
|
FullName string `json:"full_name" binding:"MaxSize(100)"`
|
||||||
Description string `json:"description" binding:"MaxSize(255)"`
|
Description string `json:"description" binding:"MaxSize(255)"`
|
||||||
Website string `json:"website" binding:"ValidUrl;MaxSize(255)"`
|
Website string `json:"website" binding:"ValidUrl;MaxSize(255)"`
|
||||||
Location string `json:"location" binding:"MaxSize(50)"`
|
Location string `json:"location" binding:"MaxSize(50)"`
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
auth_model "code.gitea.io/gitea/models/auth"
|
||||||
"code.gitea.io/gitea/models/perm"
|
"code.gitea.io/gitea/models/perm"
|
||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
@@ -35,6 +36,32 @@ import (
|
|||||||
|
|
||||||
func reqPackageAccess(accessMode perm.AccessMode) func(ctx *context.Context) {
|
func reqPackageAccess(accessMode perm.AccessMode) func(ctx *context.Context) {
|
||||||
return func(ctx *context.Context) {
|
return func(ctx *context.Context) {
|
||||||
|
if ctx.Data["IsApiToken"] == true {
|
||||||
|
scope, ok := ctx.Data["ApiTokenScope"].(auth_model.AccessTokenScope)
|
||||||
|
if ok { // it's a personal access token but not oauth2 token
|
||||||
|
scopeMatched := false
|
||||||
|
var err error
|
||||||
|
if accessMode == perm.AccessModeRead {
|
||||||
|
scopeMatched, err = scope.HasScope(auth_model.AccessTokenScopeReadPackage)
|
||||||
|
if err != nil {
|
||||||
|
ctx.Error(http.StatusInternalServerError, "HasScope", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else if accessMode == perm.AccessModeWrite {
|
||||||
|
scopeMatched, err = scope.HasScope(auth_model.AccessTokenScopeWritePackage)
|
||||||
|
if err != nil {
|
||||||
|
ctx.Error(http.StatusInternalServerError, "HasScope", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !scopeMatched {
|
||||||
|
ctx.Resp.Header().Set("WWW-Authenticate", `Basic realm="Gitea Package API"`)
|
||||||
|
ctx.Error(http.StatusUnauthorized, "reqPackageAccess", "user should have specific permission or be a site admin")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ctx.Package.AccessMode < accessMode && !ctx.IsUserSiteAdmin() {
|
if ctx.Package.AccessMode < accessMode && !ctx.IsUserSiteAdmin() {
|
||||||
ctx.Resp.Header().Set("WWW-Authenticate", `Basic realm="Gitea Package API"`)
|
ctx.Resp.Header().Set("WWW-Authenticate", `Basic realm="Gitea Package API"`)
|
||||||
ctx.Error(http.StatusUnauthorized, "reqPackageAccess", "user should have specific permission or be a site admin")
|
ctx.Error(http.StatusUnauthorized, "reqPackageAccess", "user should have specific permission or be a site admin")
|
||||||
|
|||||||
@@ -145,7 +145,7 @@ func EditHook(ctx *context.APIContext) {
|
|||||||
|
|
||||||
// DeleteHook delete a system hook
|
// DeleteHook delete a system hook
|
||||||
func DeleteHook(ctx *context.APIContext) {
|
func DeleteHook(ctx *context.APIContext) {
|
||||||
// swagger:operation DELETE /amdin/hooks/{id} admin adminDeleteHook
|
// swagger:operation DELETE /admin/hooks/{id} admin adminDeleteHook
|
||||||
// ---
|
// ---
|
||||||
// summary: Delete a hook
|
// summary: Delete a hook
|
||||||
// produces:
|
// produces:
|
||||||
|
|||||||
@@ -1178,12 +1178,12 @@ func Routes(ctx gocontext.Context) *web.Route {
|
|||||||
m.Get("/{org}/permissions", reqToken(auth_model.AccessTokenScopeReadOrg), org.GetUserOrgsPermissions)
|
m.Get("/{org}/permissions", reqToken(auth_model.AccessTokenScopeReadOrg), org.GetUserOrgsPermissions)
|
||||||
}, context_service.UserAssignmentAPI())
|
}, context_service.UserAssignmentAPI())
|
||||||
m.Post("/orgs", reqToken(auth_model.AccessTokenScopeWriteOrg), bind(api.CreateOrgOption{}), org.Create)
|
m.Post("/orgs", reqToken(auth_model.AccessTokenScopeWriteOrg), bind(api.CreateOrgOption{}), org.Create)
|
||||||
m.Get("/orgs", reqToken(auth_model.AccessTokenScopeReadOrg), org.GetAll)
|
m.Get("/orgs", org.GetAll)
|
||||||
m.Group("/orgs/{org}", func() {
|
m.Group("/orgs/{org}", func() {
|
||||||
m.Combo("").Get(reqToken(auth_model.AccessTokenScopeReadOrg), org.Get).
|
m.Combo("").Get(org.Get).
|
||||||
Patch(reqToken(auth_model.AccessTokenScopeWriteOrg), reqOrgOwnership(), bind(api.EditOrgOption{}), org.Edit).
|
Patch(reqToken(auth_model.AccessTokenScopeWriteOrg), reqOrgOwnership(), bind(api.EditOrgOption{}), org.Edit).
|
||||||
Delete(reqToken(auth_model.AccessTokenScopeWriteOrg), reqOrgOwnership(), org.Delete)
|
Delete(reqToken(auth_model.AccessTokenScopeWriteOrg), reqOrgOwnership(), org.Delete)
|
||||||
m.Combo("/repos").Get(reqToken(auth_model.AccessTokenScopeReadOrg), user.ListOrgRepos).
|
m.Combo("/repos").Get(user.ListOrgRepos).
|
||||||
Post(reqToken(auth_model.AccessTokenScopeWriteOrg), bind(api.CreateRepoOption{}), repo.CreateOrgRepo)
|
Post(reqToken(auth_model.AccessTokenScopeWriteOrg), bind(api.CreateRepoOption{}), repo.CreateOrgRepo)
|
||||||
m.Group("/members", func() {
|
m.Group("/members", func() {
|
||||||
m.Get("", reqToken(auth_model.AccessTokenScopeReadOrg), org.ListMembers)
|
m.Get("", reqToken(auth_model.AccessTokenScopeReadOrg), org.ListMembers)
|
||||||
@@ -1191,8 +1191,8 @@ func Routes(ctx gocontext.Context) *web.Route {
|
|||||||
Delete(reqToken(auth_model.AccessTokenScopeWriteOrg), reqOrgOwnership(), org.DeleteMember)
|
Delete(reqToken(auth_model.AccessTokenScopeWriteOrg), reqOrgOwnership(), org.DeleteMember)
|
||||||
})
|
})
|
||||||
m.Group("/public_members", func() {
|
m.Group("/public_members", func() {
|
||||||
m.Get("", reqToken(auth_model.AccessTokenScopeReadOrg), org.ListPublicMembers)
|
m.Get("", org.ListPublicMembers)
|
||||||
m.Combo("/{username}").Get(reqToken(auth_model.AccessTokenScopeReadOrg), org.IsPublicMember).
|
m.Combo("/{username}").Get(org.IsPublicMember).
|
||||||
Put(reqToken(auth_model.AccessTokenScopeWriteOrg), reqOrgMembership(), org.PublicizeMember).
|
Put(reqToken(auth_model.AccessTokenScopeWriteOrg), reqOrgMembership(), org.PublicizeMember).
|
||||||
Delete(reqToken(auth_model.AccessTokenScopeWriteOrg), reqOrgMembership(), org.ConcealMember)
|
Delete(reqToken(auth_model.AccessTokenScopeWriteOrg), reqOrgMembership(), org.ConcealMember)
|
||||||
})
|
})
|
||||||
@@ -1202,7 +1202,7 @@ func Routes(ctx gocontext.Context) *web.Route {
|
|||||||
m.Get("/search", reqToken(auth_model.AccessTokenScopeReadOrg), org.SearchTeam)
|
m.Get("/search", reqToken(auth_model.AccessTokenScopeReadOrg), org.SearchTeam)
|
||||||
}, reqOrgMembership())
|
}, reqOrgMembership())
|
||||||
m.Group("/labels", func() {
|
m.Group("/labels", func() {
|
||||||
m.Get("", reqToken(auth_model.AccessTokenScopeReadOrg), org.ListLabels)
|
m.Get("", org.ListLabels)
|
||||||
m.Post("", reqToken(auth_model.AccessTokenScopeWriteOrg), reqOrgOwnership(), bind(api.CreateLabelOption{}), org.CreateLabel)
|
m.Post("", reqToken(auth_model.AccessTokenScopeWriteOrg), reqOrgOwnership(), bind(api.CreateLabelOption{}), org.CreateLabel)
|
||||||
m.Combo("/{id}").Get(reqToken(auth_model.AccessTokenScopeReadOrg), org.GetLabel).
|
m.Combo("/{id}").Get(reqToken(auth_model.AccessTokenScopeReadOrg), org.GetLabel).
|
||||||
Patch(reqToken(auth_model.AccessTokenScopeWriteOrg), reqOrgOwnership(), bind(api.EditLabelOption{}), org.EditLabel).
|
Patch(reqToken(auth_model.AccessTokenScopeWriteOrg), reqOrgOwnership(), bind(api.EditLabelOption{}), org.EditLabel).
|
||||||
|
|||||||
@@ -173,7 +173,7 @@ func ListIssueCommentsAndTimeline(ctx *context.APIContext) {
|
|||||||
IssueID: issue.ID,
|
IssueID: issue.ID,
|
||||||
Since: since,
|
Since: since,
|
||||||
Before: before,
|
Before: before,
|
||||||
Type: issues_model.CommentTypeUnknown,
|
Type: issues_model.CommentTypeUndefined,
|
||||||
}
|
}
|
||||||
|
|
||||||
comments, err := issues_model.FindComments(ctx, opts)
|
comments, err := issues_model.FindComments(ctx, opts)
|
||||||
@@ -549,7 +549,7 @@ func editIssueComment(ctx *context.APIContext, form api.EditIssueCommentOption)
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if comment.Type != issues_model.CommentTypeComment && comment.Type != issues_model.CommentTypeReview && comment.Type != issues_model.CommentTypeCode {
|
if !comment.Type.HasContentSupport() {
|
||||||
ctx.Status(http.StatusNoContent)
|
ctx.Status(http.StatusNoContent)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -963,7 +963,7 @@ func SignInOAuthCallback(ctx *context.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
overwriteDefault := &user_model.CreateUserOverwriteOptions{
|
overwriteDefault := &user_model.CreateUserOverwriteOptions{
|
||||||
IsActive: util.OptionalBoolOf(!setting.OAuth2Client.RegisterEmailConfirm),
|
IsActive: util.OptionalBoolOf(!setting.OAuth2Client.RegisterEmailConfirm && !setting.Service.RegisterManualConfirm),
|
||||||
}
|
}
|
||||||
|
|
||||||
source := authSource.Cfg.(*oauth2.Source)
|
source := authSource.Cfg.(*oauth2.Source)
|
||||||
|
|||||||
@@ -43,6 +43,8 @@ func SecretsPost(ctx *context.Context) {
|
|||||||
func SecretsDelete(ctx *context.Context) {
|
func SecretsDelete(ctx *context.Context) {
|
||||||
shared.PerformSecretsDelete(
|
shared.PerformSecretsDelete(
|
||||||
ctx,
|
ctx,
|
||||||
|
ctx.ContextUser.ID,
|
||||||
|
0,
|
||||||
ctx.Org.OrgLink+"/settings/secrets",
|
ctx.Org.OrgLink+"/settings/secrets",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ type ViewResponse 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"`
|
||||||
CanCancel bool `json:"canCancel"`
|
CanCancel bool `json:"canCancel"`
|
||||||
Done bool `json:"done"`
|
Done bool `json:"done"`
|
||||||
Jobs []*ViewJob `json:"jobs"`
|
Jobs []*ViewJob `json:"jobs"`
|
||||||
@@ -109,6 +110,7 @@ func ViewPost(ctx *context_module.Context) {
|
|||||||
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.Done = run.Status.IsDone()
|
resp.State.Run.Done = run.Status.IsDone()
|
||||||
resp.State.Run.Jobs = make([]*ViewJob, 0, len(jobs)) // marshal to '[]' instead fo 'null' in json
|
resp.State.Run.Jobs = make([]*ViewJob, 0, len(jobs)) // marshal to '[]' instead fo 'null' in json
|
||||||
|
resp.State.Run.Status = run.Status.String()
|
||||||
for _, v := range jobs {
|
for _, v := range jobs {
|
||||||
resp.State.Run.Jobs = append(resp.State.Run.Jobs, &ViewJob{
|
resp.State.Run.Jobs = append(resp.State.Run.Jobs, &ViewJob{
|
||||||
ID: v.ID,
|
ID: v.ID,
|
||||||
|
|||||||
@@ -110,6 +110,11 @@ func GetAttachment(ctx *context.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else { // If we have the repository we check access
|
} else { // If we have the repository we check access
|
||||||
|
context.CheckRepoScopedToken(ctx, repository)
|
||||||
|
if ctx.Written() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
perm, err := access_model.GetUserRepoPermission(ctx, repository, ctx.Doer)
|
perm, err := access_model.GetUserRepoPermission(ctx, repository, ctx.Doer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Error(http.StatusInternalServerError, "GetUserRepoPermission", err.Error())
|
ctx.Error(http.StatusInternalServerError, "GetUserRepoPermission", err.Error())
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import (
|
|||||||
|
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/base"
|
|
||||||
"code.gitea.io/gitea/modules/charset"
|
"code.gitea.io/gitea/modules/charset"
|
||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
@@ -23,10 +22,6 @@ import (
|
|||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
tplBlame base.TplName = "repo/home"
|
|
||||||
)
|
|
||||||
|
|
||||||
type blameRow struct {
|
type blameRow struct {
|
||||||
RowNumber int
|
RowNumber int
|
||||||
Avatar gotemplate.HTML
|
Avatar gotemplate.HTML
|
||||||
@@ -140,7 +135,7 @@ func RefBlame(ctx *context.Context) {
|
|||||||
|
|
||||||
renderBlame(ctx, blameParts, commitNames, previousCommits)
|
renderBlame(ctx, blameParts, commitNames, previousCommits)
|
||||||
|
|
||||||
ctx.HTML(http.StatusOK, tplBlame)
|
ctx.HTML(http.StatusOK, tplRepoHome)
|
||||||
}
|
}
|
||||||
|
|
||||||
func processBlameParts(ctx *context.Context, blameParts []git.BlamePart) (map[string]*user_model.UserCommit, map[string]string) {
|
func processBlameParts(ctx *context.Context, blameParts []git.BlamePart) (map[string]*user_model.UserCommit, map[string]string) {
|
||||||
|
|||||||
@@ -459,7 +459,7 @@ func ParseCompareInfo(ctx *context.Context) *CompareInfo {
|
|||||||
rootRepo.ID != ci.HeadRepo.ID &&
|
rootRepo.ID != ci.HeadRepo.ID &&
|
||||||
rootRepo.ID != baseRepo.ID {
|
rootRepo.ID != baseRepo.ID {
|
||||||
canRead := access_model.CheckRepoUnitUser(ctx, rootRepo, ctx.Doer, unit.TypeCode)
|
canRead := access_model.CheckRepoUnitUser(ctx, rootRepo, ctx.Doer, unit.TypeCode)
|
||||||
if canRead {
|
if canRead && rootRepo.AllowsPulls() {
|
||||||
ctx.Data["RootRepo"] = rootRepo
|
ctx.Data["RootRepo"] = rootRepo
|
||||||
if !fileOnly {
|
if !fileOnly {
|
||||||
branches, tags, err := getBranchesAndTagsForRepo(ctx, rootRepo)
|
branches, tags, err := getBranchesAndTagsForRepo(ctx, rootRepo)
|
||||||
@@ -551,7 +551,11 @@ func ParseCompareInfo(ctx *context.Context) *CompareInfo {
|
|||||||
ctx.ServerError("GetCompareInfo", err)
|
ctx.ServerError("GetCompareInfo", err)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
ctx.Data["BeforeCommitID"] = ci.CompareInfo.MergeBase
|
if ci.DirectComparison {
|
||||||
|
ctx.Data["BeforeCommitID"] = ci.CompareInfo.BaseCommitID
|
||||||
|
} else {
|
||||||
|
ctx.Data["BeforeCommitID"] = ci.CompareInfo.MergeBase
|
||||||
|
}
|
||||||
|
|
||||||
return ci
|
return ci
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
actions_model "code.gitea.io/gitea/models/actions"
|
actions_model "code.gitea.io/gitea/models/actions"
|
||||||
"code.gitea.io/gitea/models/auth"
|
auth_model "code.gitea.io/gitea/models/auth"
|
||||||
"code.gitea.io/gitea/models/perm"
|
"code.gitea.io/gitea/models/perm"
|
||||||
access_model "code.gitea.io/gitea/models/perm/access"
|
access_model "code.gitea.io/gitea/models/perm/access"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
@@ -164,13 +164,18 @@ func httpBase(ctx *context.Context) (h *serviceHandler) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
context.CheckRepoScopedToken(ctx, repo)
|
||||||
|
if ctx.Written() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if ctx.IsBasicAuth && ctx.Data["IsApiToken"] != true && ctx.Data["IsActionsToken"] != true {
|
if ctx.IsBasicAuth && ctx.Data["IsApiToken"] != true && ctx.Data["IsActionsToken"] != true {
|
||||||
_, err = auth.GetTwoFactorByUID(ctx.Doer.ID)
|
_, err = auth_model.GetTwoFactorByUID(ctx.Doer.ID)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
// TODO: This response should be changed to "invalid credentials" for security reasons once the expectation behind it (creating an app token to authenticate) is properly documented
|
// TODO: This response should be changed to "invalid credentials" for security reasons once the expectation behind it (creating an app token to authenticate) is properly documented
|
||||||
ctx.PlainText(http.StatusUnauthorized, "Users with two-factor authentication enabled cannot perform HTTP/HTTPS operations via plain username and password. Please create and use a personal access token on the user settings page")
|
ctx.PlainText(http.StatusUnauthorized, "Users with two-factor authentication enabled cannot perform HTTP/HTTPS operations via plain username and password. Please create and use a personal access token on the user settings page")
|
||||||
return
|
return
|
||||||
} else if !auth.IsErrTwoFactorNotEnrolled(err) {
|
} else if !auth_model.IsErrTwoFactorNotEnrolled(err) {
|
||||||
ctx.ServerError("IsErrTwoFactorNotEnrolled", err)
|
ctx.ServerError("IsErrTwoFactorNotEnrolled", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1563,7 +1563,7 @@ func ViewIssue(ctx *context.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if comment.Type == issues_model.CommentTypeCode || comment.Type == issues_model.CommentTypeReview || comment.Type == issues_model.CommentTypeDismissReview {
|
} else if comment.Type.HasContentSupport() {
|
||||||
comment.RenderedContent, err = markdown.RenderString(&markup.RenderContext{
|
comment.RenderedContent, err = markdown.RenderString(&markup.RenderContext{
|
||||||
URLPrefix: ctx.Repo.RepoLink,
|
URLPrefix: ctx.Repo.RepoLink,
|
||||||
Metas: ctx.Repo.Repository.ComposeMetas(),
|
Metas: ctx.Repo.Repository.ComposeMetas(),
|
||||||
@@ -1627,8 +1627,10 @@ func ViewIssue(ctx *context.Context) {
|
|||||||
comment.Type == issues_model.CommentTypeStopTracking {
|
comment.Type == issues_model.CommentTypeStopTracking {
|
||||||
// drop error since times could be pruned from DB..
|
// drop error since times could be pruned from DB..
|
||||||
_ = comment.LoadTime()
|
_ = comment.LoadTime()
|
||||||
} else if comment.Type == issues_model.CommentTypeClose {
|
}
|
||||||
// record ID of latest closed comment.
|
|
||||||
|
if comment.Type == issues_model.CommentTypeClose || comment.Type == issues_model.CommentTypeMergePull {
|
||||||
|
// record ID of the latest closed/merged comment.
|
||||||
// if PR is closed, the comments whose type is CommentTypePullRequestPush(29) after latestCloseCommentID won't be rendered.
|
// if PR is closed, the comments whose type is CommentTypePullRequestPush(29) after latestCloseCommentID won't be rendered.
|
||||||
latestCloseCommentID = comment.ID
|
latestCloseCommentID = comment.ID
|
||||||
}
|
}
|
||||||
@@ -2800,7 +2802,7 @@ func UpdateCommentContent(ctx *context.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if comment.Type != issues_model.CommentTypeComment && comment.Type != issues_model.CommentTypeReview && comment.Type != issues_model.CommentTypeCode {
|
if !comment.Type.HasContentSupport() {
|
||||||
ctx.Error(http.StatusNoContent)
|
ctx.Error(http.StatusNoContent)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -2864,7 +2866,7 @@ func DeleteComment(ctx *context.Context) {
|
|||||||
if !ctx.IsSigned || (ctx.Doer.ID != comment.PosterID && !ctx.Repo.CanWriteIssuesOrPulls(comment.Issue.IsPull)) {
|
if !ctx.IsSigned || (ctx.Doer.ID != comment.PosterID && !ctx.Repo.CanWriteIssuesOrPulls(comment.Issue.IsPull)) {
|
||||||
ctx.Error(http.StatusForbidden)
|
ctx.Error(http.StatusForbidden)
|
||||||
return
|
return
|
||||||
} else if comment.Type != issues_model.CommentTypeComment && comment.Type != issues_model.CommentTypeCode {
|
} else if !comment.Type.HasContentSupport() {
|
||||||
ctx.Error(http.StatusNoContent)
|
ctx.Error(http.StatusNoContent)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -3010,7 +3012,7 @@ func ChangeCommentReaction(ctx *context.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if comment.Type != issues_model.CommentTypeComment && comment.Type != issues_model.CommentTypeCode && comment.Type != issues_model.CommentTypeReview {
|
if !comment.Type.HasContentSupport() {
|
||||||
ctx.Error(http.StatusNoContent)
|
ctx.Error(http.StatusNoContent)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -3126,15 +3128,19 @@ func GetCommentAttachments(ctx *context.Context) {
|
|||||||
ctx.NotFoundOrServerError("GetCommentByID", issues_model.IsErrCommentNotExist, err)
|
ctx.NotFoundOrServerError("GetCommentByID", issues_model.IsErrCommentNotExist, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !comment.Type.HasAttachmentSupport() {
|
||||||
|
ctx.ServerError("GetCommentAttachments", fmt.Errorf("comment type %v does not support attachments", comment.Type))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
attachments := make([]*api.Attachment, 0)
|
attachments := make([]*api.Attachment, 0)
|
||||||
if comment.Type == issues_model.CommentTypeComment {
|
if err := comment.LoadAttachments(ctx); err != nil {
|
||||||
if err := comment.LoadAttachments(ctx); err != nil {
|
ctx.ServerError("LoadAttachments", err)
|
||||||
ctx.ServerError("LoadAttachments", err)
|
return
|
||||||
return
|
}
|
||||||
}
|
for i := 0; i < len(comment.Attachments); i++ {
|
||||||
for i := 0; i < len(comment.Attachments); i++ {
|
attachments = append(attachments, convert.ToAttachment(comment.Attachments[i]))
|
||||||
attachments = append(attachments, convert.ToAttachment(comment.Attachments[i]))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ctx.JSON(http.StatusOK, attachments)
|
ctx.JSON(http.StatusOK, attachments)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,21 +29,17 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
tplReleases base.TplName = "repo/release/list"
|
tplReleasesList base.TplName = "repo/release/list"
|
||||||
tplReleaseNew base.TplName = "repo/release/new"
|
tplReleaseNew base.TplName = "repo/release/new"
|
||||||
|
tplTagsList base.TplName = "repo/tag/list"
|
||||||
)
|
)
|
||||||
|
|
||||||
// calReleaseNumCommitsBehind calculates given release has how many commits behind release target.
|
// calReleaseNumCommitsBehind calculates given release has how many commits behind release target.
|
||||||
func calReleaseNumCommitsBehind(repoCtx *context.Repository, release *repo_model.Release, countCache map[string]int64) error {
|
func calReleaseNumCommitsBehind(repoCtx *context.Repository, release *repo_model.Release, countCache map[string]int64) error {
|
||||||
// Fast return if release target is same as default branch.
|
|
||||||
if repoCtx.BranchName == release.Target {
|
|
||||||
release.NumCommitsBehind = repoCtx.CommitsCount - release.NumCommits
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get count if not exists
|
// Get count if not exists
|
||||||
if _, ok := countCache[release.Target]; !ok {
|
if _, ok := countCache[release.Target]; !ok {
|
||||||
if repoCtx.GitRepo.IsBranchExist(release.Target) {
|
// short-circuit for the default branch
|
||||||
|
if repoCtx.Repository.DefaultBranch == release.Target || repoCtx.GitRepo.IsBranchExist(release.Target) {
|
||||||
commit, err := repoCtx.GitRepo.GetBranchCommit(release.Target)
|
commit, err := repoCtx.GitRepo.GetBranchCommit(release.Target)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("GetBranchCommit: %w", err)
|
return fmt.Errorf("GetBranchCommit: %w", err)
|
||||||
@@ -63,16 +59,19 @@ func calReleaseNumCommitsBehind(repoCtx *context.Repository, release *repo_model
|
|||||||
|
|
||||||
// Releases render releases list page
|
// Releases render releases list page
|
||||||
func Releases(ctx *context.Context) {
|
func Releases(ctx *context.Context) {
|
||||||
|
ctx.Data["PageIsReleaseList"] = true
|
||||||
|
ctx.Data["Title"] = ctx.Tr("repo.release.releases")
|
||||||
releasesOrTags(ctx, false)
|
releasesOrTags(ctx, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TagsList render tags list page
|
// TagsList render tags list page
|
||||||
func TagsList(ctx *context.Context) {
|
func TagsList(ctx *context.Context) {
|
||||||
|
ctx.Data["PageIsTagList"] = true
|
||||||
|
ctx.Data["Title"] = ctx.Tr("repo.release.tags")
|
||||||
releasesOrTags(ctx, true)
|
releasesOrTags(ctx, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func releasesOrTags(ctx *context.Context, isTagList bool) {
|
func releasesOrTags(ctx *context.Context, isTagList bool) {
|
||||||
ctx.Data["PageIsReleaseList"] = true
|
|
||||||
ctx.Data["DefaultBranch"] = ctx.Repo.Repository.DefaultBranch
|
ctx.Data["DefaultBranch"] = ctx.Repo.Repository.DefaultBranch
|
||||||
ctx.Data["IsViewBranch"] = false
|
ctx.Data["IsViewBranch"] = false
|
||||||
ctx.Data["IsViewTag"] = true
|
ctx.Data["IsViewTag"] = true
|
||||||
@@ -80,14 +79,6 @@ func releasesOrTags(ctx *context.Context, isTagList bool) {
|
|||||||
ctx.Data["CanCreateBranch"] = false
|
ctx.Data["CanCreateBranch"] = false
|
||||||
ctx.Data["HideBranchesInDropdown"] = true
|
ctx.Data["HideBranchesInDropdown"] = true
|
||||||
|
|
||||||
if isTagList {
|
|
||||||
ctx.Data["Title"] = ctx.Tr("repo.release.tags")
|
|
||||||
ctx.Data["PageIsTagList"] = true
|
|
||||||
} else {
|
|
||||||
ctx.Data["Title"] = ctx.Tr("repo.release.releases")
|
|
||||||
ctx.Data["PageIsTagList"] = false
|
|
||||||
}
|
|
||||||
|
|
||||||
listOptions := db.ListOptions{
|
listOptions := db.ListOptions{
|
||||||
Page: ctx.FormInt("page"),
|
Page: ctx.FormInt("page"),
|
||||||
PageSize: ctx.FormInt("limit"),
|
PageSize: ctx.FormInt("limit"),
|
||||||
@@ -197,7 +188,11 @@ func releasesOrTags(ctx *context.Context, isTagList bool) {
|
|||||||
pager.SetDefaultParams(ctx)
|
pager.SetDefaultParams(ctx)
|
||||||
ctx.Data["Page"] = pager
|
ctx.Data["Page"] = pager
|
||||||
|
|
||||||
ctx.HTML(http.StatusOK, tplReleases)
|
if isTagList {
|
||||||
|
ctx.HTML(http.StatusOK, tplTagsList)
|
||||||
|
} else {
|
||||||
|
ctx.HTML(http.StatusOK, tplReleasesList)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReleasesFeedRSS get feeds for releases in RSS format
|
// ReleasesFeedRSS get feeds for releases in RSS format
|
||||||
@@ -275,7 +270,7 @@ func SingleRelease(ctx *context.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ctx.Data["Releases"] = []*repo_model.Release{release}
|
ctx.Data["Releases"] = []*repo_model.Release{release}
|
||||||
ctx.HTML(http.StatusOK, tplReleases)
|
ctx.HTML(http.StatusOK, tplReleasesList)
|
||||||
}
|
}
|
||||||
|
|
||||||
// LatestRelease redirects to the latest release
|
// LatestRelease redirects to the latest release
|
||||||
|
|||||||
@@ -41,6 +41,8 @@ func SecretsPost(ctx *context.Context) {
|
|||||||
func DeleteSecret(ctx *context.Context) {
|
func DeleteSecret(ctx *context.Context) {
|
||||||
shared.PerformSecretsDelete(
|
shared.PerformSecretsDelete(
|
||||||
ctx,
|
ctx,
|
||||||
|
0,
|
||||||
|
ctx.Repo.Repository.ID,
|
||||||
ctx.Repo.RepoLink+"/settings/secrets",
|
ctx.Repo.RepoLink+"/settings/secrets",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1010,7 +1010,7 @@ func Stars(ctx *context.Context) {
|
|||||||
|
|
||||||
// Forks render repository's forked users
|
// Forks render repository's forked users
|
||||||
func Forks(ctx *context.Context) {
|
func Forks(ctx *context.Context) {
|
||||||
ctx.Data["Title"] = ctx.Tr("repos.forks")
|
ctx.Data["Title"] = ctx.Tr("repo.forks")
|
||||||
|
|
||||||
page := ctx.FormInt("page")
|
page := ctx.FormInt("page")
|
||||||
if page <= 0 {
|
if page <= 0 {
|
||||||
|
|||||||
@@ -22,13 +22,13 @@ import (
|
|||||||
func RunnersList(ctx *context.Context, tplName base.TplName, opts actions_model.FindRunnerOptions) {
|
func RunnersList(ctx *context.Context, tplName base.TplName, opts actions_model.FindRunnerOptions) {
|
||||||
count, err := actions_model.CountRunners(ctx, opts)
|
count, err := actions_model.CountRunners(ctx, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("AdminRunners", err)
|
ctx.ServerError("CountRunners", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
runners, err := actions_model.FindRunners(ctx, opts)
|
runners, err := actions_model.FindRunners(ctx, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("AdminRunners", err)
|
ctx.ServerError("FindRunners", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err := runners.LoadAttributes(ctx); err != nil {
|
if err := runners.LoadAttributes(ctx); err != nil {
|
||||||
|
|||||||
@@ -38,10 +38,10 @@ func PerformSecretsPost(ctx *context.Context, ownerID, repoID int64, redirectURL
|
|||||||
ctx.Redirect(redirectURL)
|
ctx.Redirect(redirectURL)
|
||||||
}
|
}
|
||||||
|
|
||||||
func PerformSecretsDelete(ctx *context.Context, redirectURL string) {
|
func PerformSecretsDelete(ctx *context.Context, ownerID, repoID int64, redirectURL string) {
|
||||||
id := ctx.FormInt64("id")
|
id := ctx.FormInt64("id")
|
||||||
|
|
||||||
if _, err := db.DeleteByBean(ctx, &secret_model.Secret{ID: id}); err != nil {
|
if _, err := db.DeleteByBean(ctx, &secret_model.Secret{ID: id, OwnerID: ownerID, RepoID: repoID}); err != nil {
|
||||||
log.Error("Delete secret %d failed: %v", id, err)
|
log.Error("Delete secret %d failed: %v", id, err)
|
||||||
ctx.Flash.Error(ctx.Tr("secrets.deletion.failed"))
|
ctx.Flash.Error(ctx.Tr("secrets.deletion.failed"))
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -40,6 +40,8 @@ func SecretsPost(ctx *context.Context) {
|
|||||||
func SecretsDelete(ctx *context.Context) {
|
func SecretsDelete(ctx *context.Context) {
|
||||||
shared.PerformSecretsDelete(
|
shared.PerformSecretsDelete(
|
||||||
ctx,
|
ctx,
|
||||||
|
ctx.Doer.ID,
|
||||||
|
0,
|
||||||
setting.AppSubURL+"/user/settings/secrets",
|
setting.AppSubURL+"/user/settings/secrets",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1215,7 +1215,7 @@ func RegisterRoutes(m *web.Route) {
|
|||||||
}, context.RepoMustNotBeArchived(), reqRepoCodeWriter, repo.MustBeNotEmpty)
|
}, context.RepoMustNotBeArchived(), reqRepoCodeWriter, repo.MustBeNotEmpty)
|
||||||
}, reqSignIn, context.RepoAssignment, context.UnitTypes())
|
}, reqSignIn, context.RepoAssignment, context.UnitTypes())
|
||||||
|
|
||||||
// Releases
|
// Tags
|
||||||
m.Group("/{username}/{reponame}", func() {
|
m.Group("/{username}/{reponame}", func() {
|
||||||
m.Group("/tags", func() {
|
m.Group("/tags", func() {
|
||||||
m.Get("", repo.TagsList)
|
m.Get("", repo.TagsList)
|
||||||
@@ -1224,6 +1224,12 @@ func RegisterRoutes(m *web.Route) {
|
|||||||
}, func(ctx *context.Context) {
|
}, func(ctx *context.Context) {
|
||||||
ctx.Data["EnableFeed"] = setting.EnableFeed
|
ctx.Data["EnableFeed"] = setting.EnableFeed
|
||||||
}, repo.MustBeNotEmpty, reqRepoCodeReader, context.RepoRefByType(context.RepoRefTag, true))
|
}, repo.MustBeNotEmpty, reqRepoCodeReader, context.RepoRefByType(context.RepoRefTag, true))
|
||||||
|
m.Post("/tags/delete", repo.DeleteTag, reqSignIn,
|
||||||
|
repo.MustBeNotEmpty, context.RepoMustNotBeArchived(), reqRepoCodeWriter, context.RepoRef())
|
||||||
|
}, reqSignIn, context.RepoAssignment, context.UnitTypes())
|
||||||
|
|
||||||
|
// Releases
|
||||||
|
m.Group("/{username}/{reponame}", func() {
|
||||||
m.Group("/releases", func() {
|
m.Group("/releases", func() {
|
||||||
m.Get("/", repo.Releases)
|
m.Get("/", repo.Releases)
|
||||||
m.Get("/tag/*", repo.SingleRelease)
|
m.Get("/tag/*", repo.SingleRelease)
|
||||||
@@ -1241,8 +1247,6 @@ func RegisterRoutes(m *web.Route) {
|
|||||||
m.Post("/attachments", repo.UploadReleaseAttachment)
|
m.Post("/attachments", repo.UploadReleaseAttachment)
|
||||||
m.Post("/attachments/remove", repo.DeleteAttachment)
|
m.Post("/attachments/remove", repo.DeleteAttachment)
|
||||||
}, reqSignIn, repo.MustBeNotEmpty, context.RepoMustNotBeArchived(), reqRepoReleaseWriter, context.RepoRef())
|
}, reqSignIn, repo.MustBeNotEmpty, context.RepoMustNotBeArchived(), reqRepoReleaseWriter, context.RepoRef())
|
||||||
m.Post("/tags/delete", repo.DeleteTag, reqSignIn,
|
|
||||||
repo.MustBeNotEmpty, context.RepoMustNotBeArchived(), reqRepoCodeWriter, context.RepoRef())
|
|
||||||
m.Group("/releases", func() {
|
m.Group("/releases", func() {
|
||||||
m.Get("/edit/*", repo.EditRelease)
|
m.Get("/edit/*", repo.EditRelease)
|
||||||
m.Post("/edit/*", web.Bind(forms.EditReleaseForm{}), repo.EditReleasePost)
|
m.Post("/edit/*", web.Bind(forms.EditReleaseForm{}), repo.EditReleasePost)
|
||||||
|
|||||||
@@ -137,8 +137,10 @@ func toCommitStatus(status actions_model.Status) api.CommitStatusState {
|
|||||||
switch status {
|
switch status {
|
||||||
case actions_model.StatusSuccess, actions_model.StatusSkipped:
|
case actions_model.StatusSuccess, actions_model.StatusSkipped:
|
||||||
return api.CommitStatusSuccess
|
return api.CommitStatusSuccess
|
||||||
case actions_model.StatusFailure, actions_model.StatusCancelled:
|
case actions_model.StatusFailure:
|
||||||
return api.CommitStatusFailure
|
return api.CommitStatusFailure
|
||||||
|
case actions_model.StatusCancelled:
|
||||||
|
return api.CommitStatusWarning
|
||||||
case actions_model.StatusWaiting, actions_model.StatusBlocked:
|
case actions_model.StatusWaiting, actions_model.StatusBlocked:
|
||||||
return api.CommitStatusPending
|
return api.CommitStatusPending
|
||||||
case actions_model.StatusRunning:
|
case actions_model.StatusRunning:
|
||||||
|
|||||||
@@ -102,6 +102,7 @@ func (b *Basic) Verify(req *http.Request, w http.ResponseWriter, store DataStore
|
|||||||
}
|
}
|
||||||
|
|
||||||
store.GetData()["IsApiToken"] = true
|
store.GetData()["IsApiToken"] = true
|
||||||
|
store.GetData()["ApiTokenScope"] = token.Scope
|
||||||
return u, nil
|
return u, nil
|
||||||
} else if !auth_model.IsErrAccessTokenNotExist(err) && !auth_model.IsErrAccessTokenEmpty(err) {
|
} else if !auth_model.IsErrAccessTokenNotExist(err) && !auth_model.IsErrAccessTokenEmpty(err) {
|
||||||
log.Error("GetAccessTokenBySha: %v", err)
|
log.Error("GetAccessTokenBySha: %v", err)
|
||||||
|
|||||||
@@ -90,8 +90,7 @@ func CreateIssueComment(ctx context.Context, doer *user_model.User, repo *repo_m
|
|||||||
|
|
||||||
// UpdateComment updates information of comment.
|
// UpdateComment updates information of comment.
|
||||||
func UpdateComment(ctx context.Context, c *issues_model.Comment, doer *user_model.User, oldContent string) error {
|
func UpdateComment(ctx context.Context, c *issues_model.Comment, doer *user_model.User, oldContent string) error {
|
||||||
needsContentHistory := c.Content != oldContent &&
|
needsContentHistory := c.Content != oldContent && c.Type.HasContentSupport()
|
||||||
(c.Type == issues_model.CommentTypeComment || c.Type == issues_model.CommentTypeReview || c.Type == issues_model.CommentTypeCode)
|
|
||||||
if needsContentHistory {
|
if needsContentHistory {
|
||||||
hasContentHistory, err := issues_model.HasIssueContentHistory(ctx, c.IssueID, c.ID)
|
hasContentHistory, err := issues_model.HasIssueContentHistory(ctx, c.IssueID, c.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -58,6 +58,11 @@ func GetListLockHandler(ctx *context.Context) {
|
|||||||
}
|
}
|
||||||
repository.MustOwner(ctx)
|
repository.MustOwner(ctx)
|
||||||
|
|
||||||
|
context.CheckRepoScopedToken(ctx, repository)
|
||||||
|
if ctx.Written() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
authenticated := authenticate(ctx, repository, rv.Authorization, true, false)
|
authenticated := authenticate(ctx, repository, rv.Authorization, true, false)
|
||||||
if !authenticated {
|
if !authenticated {
|
||||||
ctx.Resp.Header().Set("WWW-Authenticate", "Basic realm=gitea-lfs")
|
ctx.Resp.Header().Set("WWW-Authenticate", "Basic realm=gitea-lfs")
|
||||||
@@ -145,6 +150,11 @@ func PostLockHandler(ctx *context.Context) {
|
|||||||
}
|
}
|
||||||
repository.MustOwner(ctx)
|
repository.MustOwner(ctx)
|
||||||
|
|
||||||
|
context.CheckRepoScopedToken(ctx, repository)
|
||||||
|
if ctx.Written() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
authenticated := authenticate(ctx, repository, authorization, true, true)
|
authenticated := authenticate(ctx, repository, authorization, true, true)
|
||||||
if !authenticated {
|
if !authenticated {
|
||||||
ctx.Resp.Header().Set("WWW-Authenticate", "Basic realm=gitea-lfs")
|
ctx.Resp.Header().Set("WWW-Authenticate", "Basic realm=gitea-lfs")
|
||||||
@@ -212,6 +222,11 @@ func VerifyLockHandler(ctx *context.Context) {
|
|||||||
}
|
}
|
||||||
repository.MustOwner(ctx)
|
repository.MustOwner(ctx)
|
||||||
|
|
||||||
|
context.CheckRepoScopedToken(ctx, repository)
|
||||||
|
if ctx.Written() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
authenticated := authenticate(ctx, repository, authorization, true, true)
|
authenticated := authenticate(ctx, repository, authorization, true, true)
|
||||||
if !authenticated {
|
if !authenticated {
|
||||||
ctx.Resp.Header().Set("WWW-Authenticate", "Basic realm=gitea-lfs")
|
ctx.Resp.Header().Set("WWW-Authenticate", "Basic realm=gitea-lfs")
|
||||||
@@ -278,6 +293,11 @@ func UnLockHandler(ctx *context.Context) {
|
|||||||
}
|
}
|
||||||
repository.MustOwner(ctx)
|
repository.MustOwner(ctx)
|
||||||
|
|
||||||
|
context.CheckRepoScopedToken(ctx, repository)
|
||||||
|
if ctx.Written() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
authenticated := authenticate(ctx, repository, authorization, true, true)
|
authenticated := authenticate(ctx, repository, authorization, true, true)
|
||||||
if !authenticated {
|
if !authenticated {
|
||||||
ctx.Resp.Header().Set("WWW-Authenticate", "Basic realm=gitea-lfs")
|
ctx.Resp.Header().Set("WWW-Authenticate", "Basic realm=gitea-lfs")
|
||||||
|
|||||||
@@ -423,6 +423,11 @@ func getAuthenticatedRepository(ctx *context.Context, rc *requestContext, requir
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
context.CheckRepoScopedToken(ctx, repository)
|
||||||
|
if ctx.Written() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
return repository
|
return repository
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -366,7 +366,13 @@ func DeleteWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model
|
|||||||
if err := git.Push(gitRepo.Ctx, basePath, git.PushOptions{
|
if err := git.Push(gitRepo.Ctx, basePath, git.PushOptions{
|
||||||
Remote: DefaultRemote,
|
Remote: DefaultRemote,
|
||||||
Branch: fmt.Sprintf("%s:%s%s", commitHash.String(), git.BranchPrefix, DefaultBranch),
|
Branch: fmt.Sprintf("%s:%s%s", commitHash.String(), git.BranchPrefix, DefaultBranch),
|
||||||
Env: repo_module.PushingEnvironment(doer, repo),
|
Env: repo_module.FullPushingEnvironment(
|
||||||
|
doer,
|
||||||
|
doer,
|
||||||
|
repo,
|
||||||
|
repo.Name+".wiki",
|
||||||
|
0,
|
||||||
|
),
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
if git.IsErrPushOutOfDate(err) || git.IsErrPushRejected(err) {
|
if git.IsErrPushOutOfDate(err) || git.IsErrPushRejected(err) {
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -1,36 +1,34 @@
|
|||||||
<footer role="group" aria-label="{{.locale.Tr "aria.footer"}}">
|
<footer role="group" aria-label="{{.locale.Tr "aria.footer"}}">
|
||||||
<div class="ui container">
|
<div class="ui left" role="contentinfo" aria-label="{{.locale.Tr "aria.footer.software"}}">
|
||||||
<div class="ui left" role="contentinfo" aria-label="{{.locale.Tr "aria.footer.software"}}">
|
<a target="_blank" rel="noopener noreferrer" href="https://gitea.io">{{.locale.Tr "powered_by" "Gitea"}}</a>
|
||||||
<a target="_blank" rel="noopener noreferrer" href="https://gitea.io">{{.locale.Tr "powered_by" "Gitea"}}</a>
|
{{if (or .ShowFooterVersion .PageIsAdmin)}}
|
||||||
{{if (or .ShowFooterVersion .PageIsAdmin)}}
|
{{.locale.Tr "version"}}:
|
||||||
{{.locale.Tr "version"}}:
|
{{if .IsAdmin}}
|
||||||
{{if .IsAdmin}}
|
<a href="{{AppSubUrl}}/admin/config">{{AppVer}}</a>
|
||||||
<a href="{{AppSubUrl}}/admin/config">{{AppVer}}</a>
|
{{else}}
|
||||||
{{else}}
|
{{AppVer}}
|
||||||
{{AppVer}}
|
|
||||||
{{end}}
|
|
||||||
{{end}}
|
|
||||||
{{if and .TemplateLoadTimes ShowFooterTemplateLoadTime}}
|
|
||||||
{{.locale.Tr "page"}}: <strong>{{LoadTimes .PageStartTime}}</strong>
|
|
||||||
{{.locale.Tr "template"}}{{if .TemplateName}} {{.TemplateName}}{{end}}: <strong>{{call .TemplateLoadTimes}}</strong>
|
|
||||||
{{end}}
|
|
||||||
</div>
|
|
||||||
<div class="ui right links" role="group" aria-label="{{.locale.Tr "aria.footer.links"}}">
|
|
||||||
{{if .ShowFooterBranding}}
|
|
||||||
<a target="_blank" rel="noopener noreferrer" href="https://github.com/go-gitea/gitea">{{svg "octicon-mark-github"}}<span class="sr-only">GitHub</span></a>
|
|
||||||
{{end}}
|
{{end}}
|
||||||
|
{{end}}
|
||||||
|
{{if and .TemplateLoadTimes ShowFooterTemplateLoadTime}}
|
||||||
|
{{.locale.Tr "page"}}: <strong>{{LoadTimes .PageStartTime}}</strong>
|
||||||
|
{{.locale.Tr "template"}}{{if .TemplateName}} {{.TemplateName}}{{end}}: <strong>{{call .TemplateLoadTimes}}</strong>
|
||||||
|
{{end}}
|
||||||
|
</div>
|
||||||
|
<div class="ui right links" role="group" aria-label="{{.locale.Tr "aria.footer.links"}}">
|
||||||
|
{{if .ShowFooterBranding}}
|
||||||
|
<a target="_blank" rel="noopener noreferrer" href="https://github.com/go-gitea/gitea">{{svg "octicon-mark-github"}}<span class="sr-only">GitHub</span></a>
|
||||||
|
{{end}}
|
||||||
<div class="ui language bottom floating slide up dropdown link item">
|
<div class="ui language bottom floating slide up dropdown link item">
|
||||||
{{svg "octicon-globe"}}
|
{{svg "octicon-globe"}}
|
||||||
<span>{{.locale.LangName}}</span>
|
<span>{{.locale.LangName}}</span>
|
||||||
<div class="menu language-menu">
|
<div class="menu language-menu">
|
||||||
{{range .AllLangs}}
|
{{range .AllLangs}}
|
||||||
<a lang="{{.Lang}}" data-url="{{AppSubUrl}}/?lang={{.Lang}}" class="item {{if eq $.locale.Lang .Lang}}active selected{{end}}">{{.Name}}</a>
|
<a lang="{{.Lang}}" data-url="{{AppSubUrl}}/?lang={{.Lang}}" class="item {{if eq $.locale.Lang .Lang}}active selected{{end}}">{{.Name}}</a>
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<a href="{{AssetUrlPrefix}}/js/licenses.txt">{{.locale.Tr "licenses"}}</a>
|
|
||||||
{{if .EnableSwagger}}<a href="{{AppSubUrl}}/api/swagger">API</a>{{end}}
|
|
||||||
{{template "custom/extra_links_footer" .}}
|
|
||||||
</div>
|
</div>
|
||||||
|
<a href="{{AssetUrlPrefix}}/js/licenses.txt">{{.locale.Tr "licenses"}}</a>
|
||||||
|
{{if .EnableSwagger}}<a href="{{AppSubUrl}}/api/swagger">API</a>{{end}}
|
||||||
|
{{template "custom/extra_links_footer" .}}
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>{{if .Title}}{{.Title | RenderEmojiPlain}} - {{end}}{{if .Repository.Name}}{{.Repository.Name}} - {{end}}{{AppName}}</title>
|
<title>{{if .Title}}{{.Title | RenderEmojiPlain}} - {{end}}{{if .Repository.Name}}{{.Repository.Name}} - {{end}}{{AppName}}</title>
|
||||||
{{if .ManifestData}}<link rel="manifest" href="data:{{.ManifestData}}">{{end}}
|
{{if .ManifestData}}<link rel="manifest" href="data:{{.ManifestData}}">{{end}}
|
||||||
<meta name="theme-color" content="{{ThemeColorMetaTag}}">
|
{{if ThemeColorMetaTag}}<meta name="theme-color" content="{{ThemeColorMetaTag}}">{{end}}
|
||||||
<meta name="default-theme" content="{{DefaultTheme}}">
|
<meta name="default-theme" content="{{DefaultTheme}}">
|
||||||
<meta name="author" content="{{if .Repository}}{{.Owner.Name}}{{else}}{{MetaAuthor}}{{end}}">
|
<meta name="author" content="{{if .Repository}}{{.Owner.Name}}{{else}}{{MetaAuthor}}{{end}}">
|
||||||
<meta name="description" content="{{if .Repository}}{{.Repository.Name}}{{if .Repository.Description}} - {{.Repository.Description}}{{end}}{{else}}{{MetaDescription}}{{end}}">
|
<meta name="description" content="{{if .Repository}}{{.Repository.Name}}{{if .Repository.Description}} - {{.Repository.Description}}{{end}}{{else}}{{MetaDescription}}{{end}}">
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
{{template "base/alert" .}}
|
{{template "base/alert" .}}
|
||||||
<div class="inline required field {{if .Err_OrgName}}error{{end}}">
|
<div class="inline required field {{if .Err_OrgName}}error{{end}}">
|
||||||
<label for="org_name">{{.locale.Tr "org.org_name_holder"}}</label>
|
<label for="org_name">{{.locale.Tr "org.org_name_holder"}}</label>
|
||||||
<input id="org_name" name="org_name" value="{{.org_name}}" autofocus required>
|
<input id="org_name" name="org_name" value="{{.org_name}}" autofocus required maxlength="40">
|
||||||
<span class="help">{{.locale.Tr "org.org_name_helper"}}</span>
|
<span class="help">{{.locale.Tr "org.org_name_helper"}}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -14,26 +14,27 @@
|
|||||||
{{.CsrfTokenHtml}}
|
{{.CsrfTokenHtml}}
|
||||||
<div class="required field {{if .Err_Name}}error{{end}}">
|
<div class="required field {{if .Err_Name}}error{{end}}">
|
||||||
<label for="org_name">{{.locale.Tr "org.org_name_holder"}}
|
<label for="org_name">{{.locale.Tr "org.org_name_holder"}}
|
||||||
<span class="text red gt-hidden" id="org-name-change-prompt"> {{.locale.Tr "org.settings.change_orgname_prompt"}}</span>
|
<span class="text red gt-hidden" id="org-name-change-prompt">
|
||||||
<span class="text red gt-hidden" id="org-name-change-redirect-prompt"> {{.locale.Tr "org.settings.change_orgname_redirect_prompt"}}</span>
|
<br>{{.locale.Tr "org.settings.change_orgname_prompt"}}<br>{{.locale.Tr "org.settings.change_orgname_redirect_prompt"}}
|
||||||
|
</span>
|
||||||
</label>
|
</label>
|
||||||
<input id="org_name" name="name" value="{{.Org.Name}}" data-org-name="{{.Org.Name}}" autofocus required>
|
<input id="org_name" name="name" value="{{.Org.Name}}" data-org-name="{{.Org.Name}}" autofocus required maxlength="40">
|
||||||
</div>
|
</div>
|
||||||
<div class="field {{if .Err_FullName}}error{{end}}">
|
<div class="field {{if .Err_FullName}}error{{end}}">
|
||||||
<label for="full_name">{{.locale.Tr "org.org_full_name_holder"}}</label>
|
<label for="full_name">{{.locale.Tr "org.org_full_name_holder"}}</label>
|
||||||
<input id="full_name" name="full_name" value="{{.Org.FullName}}">
|
<input id="full_name" name="full_name" value="{{.Org.FullName}}" maxlength="100">
|
||||||
</div>
|
</div>
|
||||||
<div class="field {{if .Err_Description}}error{{end}}">
|
<div class="field {{if .Err_Description}}error{{end}}">
|
||||||
<label for="description">{{$.locale.Tr "org.org_desc"}}</label>
|
<label for="description">{{$.locale.Tr "org.org_desc"}}</label>
|
||||||
<textarea id="description" name="description" rows="2">{{.Org.Description}}</textarea>
|
<textarea id="description" name="description" rows="2" maxlength="255">{{.Org.Description}}</textarea>
|
||||||
</div>
|
</div>
|
||||||
<div class="field {{if .Err_Website}}error{{end}}">
|
<div class="field {{if .Err_Website}}error{{end}}">
|
||||||
<label for="website">{{.locale.Tr "org.settings.website"}}</label>
|
<label for="website">{{.locale.Tr "org.settings.website"}}</label>
|
||||||
<input id="website" name="website" type="url" value="{{.Org.Website}}">
|
<input id="website" name="website" type="url" value="{{.Org.Website}}" maxlength="255">
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label for="location">{{.locale.Tr "org.settings.location"}}</label>
|
<label for="location">{{.locale.Tr "org.settings.location"}}</label>
|
||||||
<input id="location" name="location" value="{{.Org.Location}}">
|
<input id="location" name="location" value="{{.Org.Location}}" maxlength="50">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="ui divider"></div>
|
<div class="ui divider"></div>
|
||||||
|
|||||||
@@ -50,13 +50,13 @@ git push -u origin {{.Repository.DefaultBranch}}</code></pre>
|
|||||||
git push -u origin {{.Repository.DefaultBranch}}</code></pre>
|
git push -u origin {{.Repository.DefaultBranch}}</code></pre>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{template "repo/clone_script" .}}
|
|
||||||
{{end}}
|
{{end}}
|
||||||
{{else}}
|
{{else}}
|
||||||
<div class="ui segment center">
|
<div class="ui segment center">
|
||||||
{{.locale.Tr "repo.empty_message"}}
|
{{.locale.Tr "repo.empty_message"}}
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
{{template "repo/clone_script" .}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
<div class="dropzone-attachments">
|
<div class="dropzone-attachments">
|
||||||
{{if .Attachments}}
|
{{if .Attachments}}
|
||||||
<div class="ui clearing divider"></div>
|
<div class="ui divider"></div>
|
||||||
{{end}}
|
{{end}}
|
||||||
<div class="ui middle aligned padded grid">
|
{{$hasThumbnails := false}}
|
||||||
{{$hasThumbnails := false}}
|
{{- range .Attachments -}}
|
||||||
{{- range .Attachments -}}
|
<div class="gt-df">
|
||||||
<div class="twelve wide column" style="padding: 6px;">
|
<div class="gt-f1 gt-p-3">
|
||||||
<a target="_blank" rel="noopener noreferrer" href="{{.DownloadURL}}" title='{{$.ctx.locale.Tr "repo.issues.attachment.open_tab" .Name}}'>
|
<a target="_blank" rel="noopener noreferrer" href="{{.DownloadURL}}" title='{{$.ctx.locale.Tr "repo.issues.attachment.open_tab" .Name}}'>
|
||||||
{{if FilenameIsImage .Name}}
|
{{if FilenameIsImage .Name}}
|
||||||
{{if not (containGeneric $.Content .UUID)}}
|
{{if not (containGeneric $.Content .UUID)}}
|
||||||
@@ -18,14 +18,14 @@
|
|||||||
<span><strong>{{.Name}}</strong></span>
|
<span><strong>{{.Name}}</strong></span>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="four wide column" style="padding: 0px;">
|
<div class="gt-p-3 gt-df gt-ac">
|
||||||
<span class="ui text grey right">{{.Size | FileSize}}</span>
|
<span class="ui text grey right">{{.Size | FileSize}}</span>
|
||||||
</div>
|
</div>
|
||||||
{{end -}}
|
</div>
|
||||||
</div>
|
{{end -}}
|
||||||
|
|
||||||
{{if $hasThumbnails}}
|
{{if $hasThumbnails}}
|
||||||
<div class="ui clearing divider"></div>
|
<div class="ui divider"></div>
|
||||||
<div class="ui small thumbnails">
|
<div class="ui small thumbnails">
|
||||||
{{- range .Attachments -}}
|
{{- range .Attachments -}}
|
||||||
{{if FilenameIsImage .Name}}
|
{{if FilenameIsImage .Name}}
|
||||||
|
|||||||
@@ -704,7 +704,7 @@
|
|||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
{{if and .Issue.IsPull .IsIssuePoster (not .Issue.IsClosed)}}
|
{{if and .Issue.IsPull .IsIssuePoster (not .Issue.IsClosed) .Issue.PullRequest.HeadRepo}}
|
||||||
{{if and (not (eq .Issue.PullRequest.HeadRepo.FullName .Issue.PullRequest.BaseRepo.FullName)) .CanWriteToHeadRepo}}
|
{{if and (not (eq .Issue.PullRequest.HeadRepo.FullName .Issue.PullRequest.BaseRepo.FullName)) .CanWriteToHeadRepo}}
|
||||||
<div class="ui divider"></div>
|
<div class="ui divider"></div>
|
||||||
<div class="inline field">
|
<div class="inline field">
|
||||||
|
|||||||
@@ -47,7 +47,7 @@
|
|||||||
<h2 class="project-title">{{$.Project.Title}}</h2>
|
<h2 class="project-title">{{$.Project.Title}}</h2>
|
||||||
<div class="content project-description">{{$.Project.RenderedContent|Str2html}}</div>
|
<div class="content project-description">{{$.Project.RenderedContent|Str2html}}</div>
|
||||||
</div>
|
</div>
|
||||||
{{if and (or $.CanWriteIssues $.CanWritePulls) (not $.Repository.IsArchived)}}
|
{{if and $.CanWriteProjects (not $.Repository.IsArchived)}}
|
||||||
<div class="column right aligned">
|
<div class="column right aligned">
|
||||||
<div class="ui compact right small menu">
|
<div class="ui compact right small menu">
|
||||||
<a class="item" href="{{$.RepoLink}}/projects/{{.Project.ID}}/edit?redirect=project" data-id={{$.Project.ID}} data-title={{$.Project.Title}}>
|
<a class="item" href="{{$.RepoLink}}/projects/{{.Project.ID}}/edit?redirect=project" data-id={{$.Project.ID}} data-title={{$.Project.Title}}>
|
||||||
@@ -267,7 +267,7 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{if or .CanWriteIssues .CanWritePulls}}
|
{{if .CanWriteProjects}}
|
||||||
<div class="ui small basic delete modal">
|
<div class="ui small basic delete modal">
|
||||||
<div class="ui icon header">
|
<div class="ui icon header">
|
||||||
{{svg "octicon-trash"}}
|
{{svg "octicon-trash"}}
|
||||||
|
|||||||
@@ -1,73 +1,15 @@
|
|||||||
{{template "base/head" .}}
|
{{template "base/head" .}}
|
||||||
<div role="main" aria-label="{{.Title}}" class="page-content repository release">
|
<div role="main" aria-label="{{.Title}}" class="page-content repository releases">
|
||||||
{{template "repo/header" .}}
|
{{template "repo/header" .}}
|
||||||
<div class="ui container">
|
<div class="ui container">
|
||||||
{{template "base/alert" .}}
|
{{template "base/alert" .}}
|
||||||
<h2 class="ui compact small menu header">
|
{{template "repo/sub_menu_release_tag" .}}
|
||||||
{{if .Permission.CanRead $.UnitTypeReleases}}
|
|
||||||
<a class="{{if (not .PageIsTagList)}}active {{end}}item" href="{{.RepoLink}}/releases">{{.locale.Tr "repo.release.releases"}}</a>
|
{{if .CanCreateRelease}}
|
||||||
{{end}}
|
|
||||||
{{if .Permission.CanRead $.UnitTypeCode}}
|
|
||||||
<a class="{{if .PageIsTagList}}active {{end}}item" href="{{.RepoLink}}/tags">{{.locale.Tr "repo.release.tags"}}</a>
|
|
||||||
{{end}}
|
|
||||||
</h2>
|
|
||||||
{{if .EnableFeed}}
|
|
||||||
<a href="{{.RepoLink}}/{{if .PageIsTagList}}tags{{else}}releases{{end}}.rss"><i class="ui grey icon tooltip gt-ml-3" data-content="{{.locale.Tr "rss_feed"}}" data-position="top center">{{svg "octicon-rss" 18}}</i></a>
|
|
||||||
{{end}}
|
|
||||||
{{if (and .CanCreateRelease (not .PageIsTagList))}}
|
|
||||||
<a class="ui right small green button" href="{{$.RepoLink}}/releases/new">
|
<a class="ui right small green button" href="{{$.RepoLink}}/releases/new">
|
||||||
{{.locale.Tr "repo.release.new_release"}}
|
{{.locale.Tr "repo.release.new_release"}}
|
||||||
</a>
|
</a>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{if .PageIsTagList}}
|
|
||||||
<div class="ui divider"></div>
|
|
||||||
{{if gt .ReleasesNum 0}}
|
|
||||||
<h4 class="ui top attached header">
|
|
||||||
<div class="five wide column gt-df gt-ac">
|
|
||||||
{{svg "octicon-tag" 16 "gt-mr-2"}}{{.locale.Tr "repo.release.tags"}}
|
|
||||||
</div>
|
|
||||||
</h4>
|
|
||||||
<div class="ui attached table segment">
|
|
||||||
<table class="ui very basic striped fixed table single line" id="tags-table">
|
|
||||||
<thead></thead>
|
|
||||||
<tbody class="tag-list">
|
|
||||||
{{range $idx, $release := .Releases}}
|
|
||||||
<tr>
|
|
||||||
<td class="tag">
|
|
||||||
<h3 class="release-tag-name gt-mb-3">
|
|
||||||
<a class="gt-df gt-ac" href="{{$.RepoLink}}/src/tag/{{.TagName | PathEscapeSegments}}" rel="nofollow">{{.TagName}}</a>
|
|
||||||
</h3>
|
|
||||||
<div class="download gt-df gt-ac">
|
|
||||||
{{if $.Permission.CanRead $.UnitTypeCode}}
|
|
||||||
{{if .CreatedUnix}}
|
|
||||||
<span class="gt-mr-3">{{svg "octicon-clock" 16 "gt-mr-2"}}{{TimeSinceUnix .CreatedUnix $.locale}}</span>
|
|
||||||
{{end}}
|
|
||||||
<a class="gt-mr-3 gt-mono muted" href="{{$.RepoLink}}/src/commit/{{.Sha1}}" rel="nofollow">{{svg "octicon-git-commit" 16 "gt-mr-2"}}{{ShortSha .Sha1}}</a>
|
|
||||||
{{if not $.DisableDownloadSourceArchives}}
|
|
||||||
<a class="archive-link gt-mr-3 muted" href="{{$.RepoLink}}/archive/{{.TagName | PathEscapeSegments}}.zip" rel="nofollow">{{svg "octicon-file-zip" 16 "gt-mr-2"}}ZIP</a>
|
|
||||||
<a class="archive-link gt-mr-3 muted" href="{{$.RepoLink}}/archive/{{.TagName | PathEscapeSegments}}.tar.gz" rel="nofollow">{{svg "octicon-file-zip" 16 "gt-mr-2"}}TAR.GZ</a>
|
|
||||||
{{end}}
|
|
||||||
{{if (and $.CanCreateRelease $release.IsTag)}}
|
|
||||||
<a class="gt-mr-3 muted" href="{{$.RepoLink}}/releases/new?tag={{.TagName}}">{{svg "octicon-tag" 16 "gt-mr-2"}}{{$.locale.Tr "repo.release.new_release"}}</a>
|
|
||||||
{{end}}
|
|
||||||
{{if (and ($.Permission.CanWrite $.UnitTypeCode) $release.IsTag)}}
|
|
||||||
<a class="ui delete-button gt-mr-3 muted" data-url="{{$.RepoLink}}/tags/delete" data-id="{{.ID}}">
|
|
||||||
{{svg "octicon-trash" 16 "gt-mr-2"}}{{$.locale.Tr "repo.release.delete_tag"}}
|
|
||||||
</a>
|
|
||||||
{{end}}
|
|
||||||
{{if (not $release.IsTag)}}
|
|
||||||
<a class="gt-mr-3 muted" href="{{$.RepoLink}}/releases/tag/{{.TagName | PathEscapeSegments}}">{{svg "octicon-tag" 16 "gt-mr-2"}}{{$.locale.Tr "repo.release.detail"}}</a>
|
|
||||||
{{end}}
|
|
||||||
{{end}}
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{{end}}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
{{end}}
|
|
||||||
{{else}}
|
|
||||||
<ul id="release-list">
|
<ul id="release-list">
|
||||||
{{range $idx, $release := .Releases}}
|
{{range $idx, $release := .Releases}}
|
||||||
<li class="ui grid">
|
<li class="ui grid">
|
||||||
@@ -196,7 +138,7 @@
|
|||||||
</li>
|
</li>
|
||||||
{{end}}
|
{{end}}
|
||||||
</ul>
|
</ul>
|
||||||
{{end}}
|
|
||||||
{{template "base/paginate" .}}
|
{{template "base/paginate" .}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -169,7 +169,7 @@
|
|||||||
{{range .PushMirrors}}
|
{{range .PushMirrors}}
|
||||||
<tr>
|
<tr>
|
||||||
{{$address := MirrorRemoteAddress $.Context $.Repository .GetRemoteName true}}
|
{{$address := MirrorRemoteAddress $.Context $.Repository .GetRemoteName true}}
|
||||||
<td>{{$address.Address}}</td>
|
<td class="gt-word-break">{{$address.Address}}</td>
|
||||||
<td>{{$.locale.Tr "repo.settings.mirror_settings.direction.push"}}</td>
|
<td>{{$.locale.Tr "repo.settings.mirror_settings.direction.push"}}</td>
|
||||||
<td>{{if .LastUpdateUnix}}<time data-format="date-time" datetime="{{.LastUpdateUnix.FormatLong}}">{{.LastUpdateUnix.AsTime}}</time>{{else}}{{$.locale.Tr "never"}}{{end}} {{if .LastError}}<div class="ui red label tooltip" data-content="{{.LastError}}">{{$.locale.Tr "error"}}</div>{{end}}</td>
|
<td>{{if .LastUpdateUnix}}<time data-format="date-time" datetime="{{.LastUpdateUnix.FormatLong}}">{{.LastUpdateUnix.AsTime}}</time>{{else}}{{$.locale.Tr "never"}}{{end}} {{if .LastError}}<div class="ui red label tooltip" data-content="{{.LastError}}">{{$.locale.Tr "error"}}</div>{{end}}</td>
|
||||||
<td class="right aligned">
|
<td class="right aligned">
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
<a class="ui" href="{{.RepoLink}}/branches">{{svg "octicon-git-branch"}} <b>{{.BranchesCount}}</b> {{.locale.TrN .BranchesCount "repo.branch" "repo.branches"}}</a>
|
<a class="ui" href="{{.RepoLink}}/branches">{{svg "octicon-git-branch"}} <b>{{.BranchesCount}}</b> {{.locale.TrN .BranchesCount "repo.branch" "repo.branches"}}</a>
|
||||||
</div>
|
</div>
|
||||||
{{if $.Permission.CanRead $.UnitTypeCode}}
|
{{if $.Permission.CanRead $.UnitTypeCode}}
|
||||||
<div class="item">
|
<div class="item{{if .PageIsTagList}} active{{end}}">
|
||||||
<a class="ui" href="{{.RepoLink}}/tags">{{svg "octicon-tag"}} <b>{{.NumTags}}</b> {{.locale.TrN .NumTags "repo.tag" "repo.tags"}}</a>
|
<a class="ui" href="{{.RepoLink}}/tags">{{svg "octicon-tag"}} <b>{{.NumTags}}</b> {{.locale.TrN .NumTags "repo.tag" "repo.tags"}}</a>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|||||||
17
templates/repo/sub_menu_release_tag.tmpl
Normal file
17
templates/repo/sub_menu_release_tag.tmpl
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
{{$canReadReleases := $.Permission.CanRead $.UnitTypeReleases}}
|
||||||
|
{{$canReadCode := $.Permission.CanRead $.UnitTypeCode}}
|
||||||
|
|
||||||
|
{{if $canReadReleases}}
|
||||||
|
<h2 class="ui compact small menu header">
|
||||||
|
<a class="{{if .PageIsReleaseList}}active {{end}}item" href="{{.RepoLink}}/releases">{{.locale.Tr "repo.release.releases"}}</a>
|
||||||
|
{{if $canReadCode}}
|
||||||
|
<a class="{{if .PageIsTagList}}active {{end}}item" href="{{.RepoLink}}/tags">{{.locale.Tr "repo.release.tags"}}</a>
|
||||||
|
{{end}}
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
{{if .EnableFeed}}
|
||||||
|
<a href="{{.RepoLink}}/{{if .PageIsTagList}}tags{{else}}releases{{end}}.rss"><i class="ui grey icon gt-ml-3" data-tooltip-content="{{.locale.Tr "rss_feed"}}">{{svg "octicon-rss" 18}}</i></a>
|
||||||
|
{{end}}
|
||||||
|
{{else if $canReadCode}}
|
||||||
|
{{template "repo/sub_menu" .}}
|
||||||
|
{{end}}
|
||||||
85
templates/repo/tag/list.tmpl
Normal file
85
templates/repo/tag/list.tmpl
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
{{template "base/head" .}}
|
||||||
|
|
||||||
|
<div role="main" aria-label="{{.Title}}" class="page-content repository tags">
|
||||||
|
{{template "repo/header" .}}
|
||||||
|
<div class="ui container">
|
||||||
|
{{template "base/alert" .}}
|
||||||
|
{{template "repo/sub_menu_release_tag" .}}
|
||||||
|
|
||||||
|
<div class="ui divider"></div>
|
||||||
|
|
||||||
|
<h4 class="ui top attached header">
|
||||||
|
<div class="five wide column gt-df gt-ac">
|
||||||
|
{{svg "octicon-tag" 16 "gt-mr-2"}}{{.locale.Tr "repo.release.tags"}}
|
||||||
|
</div>
|
||||||
|
</h4>
|
||||||
|
|
||||||
|
{{$canReadReleases := $.Permission.CanRead $.UnitTypeReleases}}
|
||||||
|
|
||||||
|
<div class="ui attached table segment">
|
||||||
|
<table class="ui very basic striped fixed table single line" id="tags-table">
|
||||||
|
<tbody class="tag-list">
|
||||||
|
{{range $idx, $release := .Releases}}
|
||||||
|
<tr>
|
||||||
|
<td class="tag">
|
||||||
|
<h3 class="release-tag-name gt-mb-3">
|
||||||
|
{{if $canReadReleases}}
|
||||||
|
<a class="gt-df gt-ac" href="{{$.RepoLink}}/releases/tag/{{.TagName | PathEscapeSegments}}" rel="nofollow">{{.TagName}}</a>
|
||||||
|
{{else}}
|
||||||
|
<a class="gt-df gt-ac" href="{{$.RepoLink}}/src/tag/{{.TagName | PathEscapeSegments}}" rel="nofollow">{{.TagName}}</a>
|
||||||
|
{{end}}
|
||||||
|
</h3>
|
||||||
|
<div class="download gt-df gt-ac">
|
||||||
|
{{if $.Permission.CanRead $.UnitTypeCode}}
|
||||||
|
{{if .CreatedUnix}}
|
||||||
|
<span class="gt-mr-3">{{svg "octicon-clock" 16 "gt-mr-2"}}{{TimeSinceUnix .CreatedUnix $.locale}}</span>
|
||||||
|
{{end}}
|
||||||
|
|
||||||
|
<a class="gt-mr-3 gt-mono muted" href="{{$.RepoLink}}/src/commit/{{.Sha1}}" rel="nofollow">{{svg "octicon-git-commit" 16 "gt-mr-2"}}{{ShortSha .Sha1}}</a>
|
||||||
|
|
||||||
|
{{if not $.DisableDownloadSourceArchives}}
|
||||||
|
<a class="archive-link gt-mr-3 muted" href="{{$.RepoLink}}/archive/{{.TagName | PathEscapeSegments}}.zip" rel="nofollow">{{svg "octicon-file-zip" 16 "gt-mr-2"}}ZIP</a>
|
||||||
|
<a class="archive-link gt-mr-3 muted" href="{{$.RepoLink}}/archive/{{.TagName | PathEscapeSegments}}.tar.gz" rel="nofollow">{{svg "octicon-file-zip" 16 "gt-mr-2"}}TAR.GZ</a>
|
||||||
|
{{end}}
|
||||||
|
|
||||||
|
{{if (and $canReadReleases $.CanCreateRelease $release.IsTag)}}
|
||||||
|
<a class="gt-mr-3 muted" href="{{$.RepoLink}}/releases/new?tag={{.TagName}}">{{svg "octicon-tag" 16 "gt-mr-2"}}{{$.locale.Tr "repo.release.new_release"}}</a>
|
||||||
|
{{end}}
|
||||||
|
|
||||||
|
{{if (and ($.Permission.CanWrite $.UnitTypeCode) $release.IsTag)}}
|
||||||
|
<a class="ui delete-button gt-mr-3 muted" data-url="{{$.RepoLink}}/tags/delete" data-id="{{.ID}}">
|
||||||
|
{{svg "octicon-trash" 16 "gt-mr-2"}}{{$.locale.Tr "repo.release.delete_tag"}}
|
||||||
|
</a>
|
||||||
|
{{end}}
|
||||||
|
|
||||||
|
{{if and $canReadReleases (not $release.IsTag)}}
|
||||||
|
<a class="gt-mr-3 muted" href="{{$.RepoLink}}/releases/tag/{{.TagName | PathEscapeSegments}}">{{svg "octicon-tag" 16 "gt-mr-2"}}{{$.locale.Tr "repo.release.detail"}}</a>
|
||||||
|
{{end}}
|
||||||
|
{{end}}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{{end}}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{template "base/paginate" .}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{if $.Permission.CanWrite $.UnitTypeCode}}
|
||||||
|
<div class="ui small basic delete modal">
|
||||||
|
<div class="ui header">
|
||||||
|
{{svg "octicon-trash" 16 "gt-mr-2"}}
|
||||||
|
{{.locale.Tr "repo.release.delete_tag"}}
|
||||||
|
</div>
|
||||||
|
<div class="content">
|
||||||
|
<p>{{.locale.Tr "repo.release.deletion_tag_desc"}}</p>
|
||||||
|
</div>
|
||||||
|
{{template "base/delete_modal_actions" .}}
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
|
|
||||||
|
|
||||||
|
{{template "base/footer" .}}
|
||||||
@@ -223,6 +223,31 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"delete": {
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"admin"
|
||||||
|
],
|
||||||
|
"summary": "Delete a hook",
|
||||||
|
"operationId": "adminDeleteHook",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int64",
|
||||||
|
"description": "id of the hook to delete",
|
||||||
|
"name": "id",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"204": {
|
||||||
|
"$ref": "#/responses/empty"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"patch": {
|
"patch": {
|
||||||
"consumes": [
|
"consumes": [
|
||||||
"application/json"
|
"application/json"
|
||||||
@@ -731,33 +756,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"/amdin/hooks/{id}": {
|
|
||||||
"delete": {
|
|
||||||
"produces": [
|
|
||||||
"application/json"
|
|
||||||
],
|
|
||||||
"tags": [
|
|
||||||
"admin"
|
|
||||||
],
|
|
||||||
"summary": "Delete a hook",
|
|
||||||
"operationId": "adminDeleteHook",
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"type": "integer",
|
|
||||||
"format": "int64",
|
|
||||||
"description": "id of the hook to delete",
|
|
||||||
"name": "id",
|
|
||||||
"in": "path",
|
|
||||||
"required": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"responses": {
|
|
||||||
"204": {
|
|
||||||
"$ref": "#/responses/empty"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"/markdown": {
|
"/markdown": {
|
||||||
"post": {
|
"post": {
|
||||||
"consumes": [
|
"consumes": [
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
ref: refs/heads/main
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
[core]
|
||||||
|
repositoryformatversion = 0
|
||||||
|
filemode = true
|
||||||
|
bare = true
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Unnamed repository; edit this file 'description' to name the repository.
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# An example hook script to check the commit log message taken by
|
||||||
|
# applypatch from an e-mail message.
|
||||||
|
#
|
||||||
|
# The hook should exit with non-zero status after issuing an
|
||||||
|
# appropriate message if it wants to stop the commit. The hook is
|
||||||
|
# allowed to edit the commit message file.
|
||||||
|
#
|
||||||
|
# To enable this hook, rename this file to "applypatch-msg".
|
||||||
|
|
||||||
|
. git-sh-setup
|
||||||
|
commitmsg="$(git rev-parse --git-path hooks/commit-msg)"
|
||||||
|
test -x "$commitmsg" && exec "$commitmsg" ${1+"$@"}
|
||||||
|
:
|
||||||
24
tests/gitea-repositories-meta/user2/repo-release.git/hooks/commit-msg.sample
Executable file
24
tests/gitea-repositories-meta/user2/repo-release.git/hooks/commit-msg.sample
Executable file
@@ -0,0 +1,24 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# An example hook script to check the commit log message.
|
||||||
|
# Called by "git commit" with one argument, the name of the file
|
||||||
|
# that has the commit message. The hook should exit with non-zero
|
||||||
|
# status after issuing an appropriate message if it wants to stop the
|
||||||
|
# commit. The hook is allowed to edit the commit message file.
|
||||||
|
#
|
||||||
|
# To enable this hook, rename this file to "commit-msg".
|
||||||
|
|
||||||
|
# Uncomment the below to add a Signed-off-by line to the message.
|
||||||
|
# Doing this in a hook is a bad idea in general, but the prepare-commit-msg
|
||||||
|
# hook is more suited to it.
|
||||||
|
#
|
||||||
|
# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
|
||||||
|
# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
|
||||||
|
|
||||||
|
# This example catches duplicate Signed-off-by lines.
|
||||||
|
|
||||||
|
test "" = "$(grep '^Signed-off-by: ' "$1" |
|
||||||
|
sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || {
|
||||||
|
echo >&2 Duplicate Signed-off-by lines.
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
@@ -0,0 +1,174 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use IPC::Open2;
|
||||||
|
|
||||||
|
# An example hook script to integrate Watchman
|
||||||
|
# (https://facebook.github.io/watchman/) with git to speed up detecting
|
||||||
|
# new and modified files.
|
||||||
|
#
|
||||||
|
# The hook is passed a version (currently 2) and last update token
|
||||||
|
# formatted as a string and outputs to stdout a new update token and
|
||||||
|
# all files that have been modified since the update token. Paths must
|
||||||
|
# be relative to the root of the working tree and separated by a single NUL.
|
||||||
|
#
|
||||||
|
# To enable this hook, rename this file to "query-watchman" and set
|
||||||
|
# 'git config core.fsmonitor .git/hooks/query-watchman'
|
||||||
|
#
|
||||||
|
my ($version, $last_update_token) = @ARGV;
|
||||||
|
|
||||||
|
# Uncomment for debugging
|
||||||
|
# print STDERR "$0 $version $last_update_token\n";
|
||||||
|
|
||||||
|
# Check the hook interface version
|
||||||
|
if ($version ne 2) {
|
||||||
|
die "Unsupported query-fsmonitor hook version '$version'.\n" .
|
||||||
|
"Falling back to scanning...\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
my $git_work_tree = get_working_dir();
|
||||||
|
|
||||||
|
my $retry = 1;
|
||||||
|
|
||||||
|
my $json_pkg;
|
||||||
|
eval {
|
||||||
|
require JSON::XS;
|
||||||
|
$json_pkg = "JSON::XS";
|
||||||
|
1;
|
||||||
|
} or do {
|
||||||
|
require JSON::PP;
|
||||||
|
$json_pkg = "JSON::PP";
|
||||||
|
};
|
||||||
|
|
||||||
|
launch_watchman();
|
||||||
|
|
||||||
|
sub launch_watchman {
|
||||||
|
my $o = watchman_query();
|
||||||
|
if (is_work_tree_watched($o)) {
|
||||||
|
output_result($o->{clock}, @{$o->{files}});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub output_result {
|
||||||
|
my ($clockid, @files) = @_;
|
||||||
|
|
||||||
|
# Uncomment for debugging watchman output
|
||||||
|
# open (my $fh, ">", ".git/watchman-output.out");
|
||||||
|
# binmode $fh, ":utf8";
|
||||||
|
# print $fh "$clockid\n@files\n";
|
||||||
|
# close $fh;
|
||||||
|
|
||||||
|
binmode STDOUT, ":utf8";
|
||||||
|
print $clockid;
|
||||||
|
print "\0";
|
||||||
|
local $, = "\0";
|
||||||
|
print @files;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub watchman_clock {
|
||||||
|
my $response = qx/watchman clock "$git_work_tree"/;
|
||||||
|
die "Failed to get clock id on '$git_work_tree'.\n" .
|
||||||
|
"Falling back to scanning...\n" if $? != 0;
|
||||||
|
|
||||||
|
return $json_pkg->new->utf8->decode($response);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub watchman_query {
|
||||||
|
my $pid = open2(\*CHLD_OUT, \*CHLD_IN, 'watchman -j --no-pretty')
|
||||||
|
or die "open2() failed: $!\n" .
|
||||||
|
"Falling back to scanning...\n";
|
||||||
|
|
||||||
|
# In the query expression below we're asking for names of files that
|
||||||
|
# changed since $last_update_token but not from the .git folder.
|
||||||
|
#
|
||||||
|
# To accomplish this, we're using the "since" generator to use the
|
||||||
|
# recency index to select candidate nodes and "fields" to limit the
|
||||||
|
# output to file names only. Then we're using the "expression" term to
|
||||||
|
# further constrain the results.
|
||||||
|
my $last_update_line = "";
|
||||||
|
if (substr($last_update_token, 0, 1) eq "c") {
|
||||||
|
$last_update_token = "\"$last_update_token\"";
|
||||||
|
$last_update_line = qq[\n"since": $last_update_token,];
|
||||||
|
}
|
||||||
|
my $query = <<" END";
|
||||||
|
["query", "$git_work_tree", {$last_update_line
|
||||||
|
"fields": ["name"],
|
||||||
|
"expression": ["not", ["dirname", ".git"]]
|
||||||
|
}]
|
||||||
|
END
|
||||||
|
|
||||||
|
# Uncomment for debugging the watchman query
|
||||||
|
# open (my $fh, ">", ".git/watchman-query.json");
|
||||||
|
# print $fh $query;
|
||||||
|
# close $fh;
|
||||||
|
|
||||||
|
print CHLD_IN $query;
|
||||||
|
close CHLD_IN;
|
||||||
|
my $response = do {local $/; <CHLD_OUT>};
|
||||||
|
|
||||||
|
# Uncomment for debugging the watch response
|
||||||
|
# open ($fh, ">", ".git/watchman-response.json");
|
||||||
|
# print $fh $response;
|
||||||
|
# close $fh;
|
||||||
|
|
||||||
|
die "Watchman: command returned no output.\n" .
|
||||||
|
"Falling back to scanning...\n" if $response eq "";
|
||||||
|
die "Watchman: command returned invalid output: $response\n" .
|
||||||
|
"Falling back to scanning...\n" unless $response =~ /^\{/;
|
||||||
|
|
||||||
|
return $json_pkg->new->utf8->decode($response);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub is_work_tree_watched {
|
||||||
|
my ($output) = @_;
|
||||||
|
my $error = $output->{error};
|
||||||
|
if ($retry > 0 and $error and $error =~ m/unable to resolve root .* directory (.*) is not watched/) {
|
||||||
|
$retry--;
|
||||||
|
my $response = qx/watchman watch "$git_work_tree"/;
|
||||||
|
die "Failed to make watchman watch '$git_work_tree'.\n" .
|
||||||
|
"Falling back to scanning...\n" if $? != 0;
|
||||||
|
$output = $json_pkg->new->utf8->decode($response);
|
||||||
|
$error = $output->{error};
|
||||||
|
die "Watchman: $error.\n" .
|
||||||
|
"Falling back to scanning...\n" if $error;
|
||||||
|
|
||||||
|
# Uncomment for debugging watchman output
|
||||||
|
# open (my $fh, ">", ".git/watchman-output.out");
|
||||||
|
# close $fh;
|
||||||
|
|
||||||
|
# Watchman will always return all files on the first query so
|
||||||
|
# return the fast "everything is dirty" flag to git and do the
|
||||||
|
# Watchman query just to get it over with now so we won't pay
|
||||||
|
# the cost in git to look up each individual file.
|
||||||
|
my $o = watchman_clock();
|
||||||
|
$error = $output->{error};
|
||||||
|
|
||||||
|
die "Watchman: $error.\n" .
|
||||||
|
"Falling back to scanning...\n" if $error;
|
||||||
|
|
||||||
|
output_result($o->{clock}, ("/"));
|
||||||
|
$last_update_token = $o->{clock};
|
||||||
|
|
||||||
|
eval { launch_watchman() };
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
die "Watchman: $error.\n" .
|
||||||
|
"Falling back to scanning...\n" if $error;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub get_working_dir {
|
||||||
|
my $working_dir;
|
||||||
|
if ($^O =~ 'msys' || $^O =~ 'cygwin') {
|
||||||
|
$working_dir = Win32::GetCwd();
|
||||||
|
$working_dir =~ tr/\\/\//;
|
||||||
|
} else {
|
||||||
|
require Cwd;
|
||||||
|
$working_dir = Cwd::cwd();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $working_dir;
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# An example hook script to prepare a packed repository for use over
|
||||||
|
# dumb transports.
|
||||||
|
#
|
||||||
|
# To enable this hook, rename this file to "post-update".
|
||||||
|
|
||||||
|
exec git update-server-info
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# An example hook script to verify what is about to be committed
|
||||||
|
# by applypatch from an e-mail message.
|
||||||
|
#
|
||||||
|
# The hook should exit with non-zero status after issuing an
|
||||||
|
# appropriate message if it wants to stop the commit.
|
||||||
|
#
|
||||||
|
# To enable this hook, rename this file to "pre-applypatch".
|
||||||
|
|
||||||
|
. git-sh-setup
|
||||||
|
precommit="$(git rev-parse --git-path hooks/pre-commit)"
|
||||||
|
test -x "$precommit" && exec "$precommit" ${1+"$@"}
|
||||||
|
:
|
||||||
49
tests/gitea-repositories-meta/user2/repo-release.git/hooks/pre-commit.sample
Executable file
49
tests/gitea-repositories-meta/user2/repo-release.git/hooks/pre-commit.sample
Executable file
@@ -0,0 +1,49 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# An example hook script to verify what is about to be committed.
|
||||||
|
# Called by "git commit" with no arguments. The hook should
|
||||||
|
# exit with non-zero status after issuing an appropriate message if
|
||||||
|
# it wants to stop the commit.
|
||||||
|
#
|
||||||
|
# To enable this hook, rename this file to "pre-commit".
|
||||||
|
|
||||||
|
if git rev-parse --verify HEAD >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
against=HEAD
|
||||||
|
else
|
||||||
|
# Initial commit: diff against an empty tree object
|
||||||
|
against=$(git hash-object -t tree /dev/null)
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If you want to allow non-ASCII filenames set this variable to true.
|
||||||
|
allownonascii=$(git config --type=bool hooks.allownonascii)
|
||||||
|
|
||||||
|
# Redirect output to stderr.
|
||||||
|
exec 1>&2
|
||||||
|
|
||||||
|
# Cross platform projects tend to avoid non-ASCII filenames; prevent
|
||||||
|
# them from being added to the repository. We exploit the fact that the
|
||||||
|
# printable range starts at the space character and ends with tilde.
|
||||||
|
if [ "$allownonascii" != "true" ] &&
|
||||||
|
# Note that the use of brackets around a tr range is ok here, (it's
|
||||||
|
# even required, for portability to Solaris 10's /usr/bin/tr), since
|
||||||
|
# the square bracket bytes happen to fall in the designated range.
|
||||||
|
test $(git diff --cached --name-only --diff-filter=A -z $against |
|
||||||
|
LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0
|
||||||
|
then
|
||||||
|
cat <<\EOF
|
||||||
|
Error: Attempt to add a non-ASCII file name.
|
||||||
|
|
||||||
|
This can cause problems if you want to work with people on other platforms.
|
||||||
|
|
||||||
|
To be portable it is advisable to rename the file.
|
||||||
|
|
||||||
|
If you know what you are doing you can disable this check using:
|
||||||
|
|
||||||
|
git config hooks.allownonascii true
|
||||||
|
EOF
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If there are whitespace errors, print the offending file names and fail.
|
||||||
|
exec git diff-index --check --cached $against --
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# An example hook script to verify what is about to be committed.
|
||||||
|
# Called by "git merge" with no arguments. The hook should
|
||||||
|
# exit with non-zero status after issuing an appropriate message to
|
||||||
|
# stderr if it wants to stop the merge commit.
|
||||||
|
#
|
||||||
|
# To enable this hook, rename this file to "pre-merge-commit".
|
||||||
|
|
||||||
|
. git-sh-setup
|
||||||
|
test -x "$GIT_DIR/hooks/pre-commit" &&
|
||||||
|
exec "$GIT_DIR/hooks/pre-commit"
|
||||||
|
:
|
||||||
53
tests/gitea-repositories-meta/user2/repo-release.git/hooks/pre-push.sample
Executable file
53
tests/gitea-repositories-meta/user2/repo-release.git/hooks/pre-push.sample
Executable file
@@ -0,0 +1,53 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# An example hook script to verify what is about to be pushed. Called by "git
|
||||||
|
# push" after it has checked the remote status, but before anything has been
|
||||||
|
# pushed. If this script exits with a non-zero status nothing will be pushed.
|
||||||
|
#
|
||||||
|
# This hook is called with the following parameters:
|
||||||
|
#
|
||||||
|
# $1 -- Name of the remote to which the push is being done
|
||||||
|
# $2 -- URL to which the push is being done
|
||||||
|
#
|
||||||
|
# If pushing without using a named remote those arguments will be equal.
|
||||||
|
#
|
||||||
|
# Information about the commits which are being pushed is supplied as lines to
|
||||||
|
# the standard input in the form:
|
||||||
|
#
|
||||||
|
# <local ref> <local oid> <remote ref> <remote oid>
|
||||||
|
#
|
||||||
|
# This sample shows how to prevent push of commits where the log message starts
|
||||||
|
# with "WIP" (work in progress).
|
||||||
|
|
||||||
|
remote="$1"
|
||||||
|
url="$2"
|
||||||
|
|
||||||
|
zero=$(git hash-object --stdin </dev/null | tr '[0-9a-f]' '0')
|
||||||
|
|
||||||
|
while read local_ref local_oid remote_ref remote_oid
|
||||||
|
do
|
||||||
|
if test "$local_oid" = "$zero"
|
||||||
|
then
|
||||||
|
# Handle delete
|
||||||
|
:
|
||||||
|
else
|
||||||
|
if test "$remote_oid" = "$zero"
|
||||||
|
then
|
||||||
|
# New branch, examine all commits
|
||||||
|
range="$local_oid"
|
||||||
|
else
|
||||||
|
# Update to existing branch, examine new commits
|
||||||
|
range="$remote_oid..$local_oid"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check for WIP commit
|
||||||
|
commit=$(git rev-list -n 1 --grep '^WIP' "$range")
|
||||||
|
if test -n "$commit"
|
||||||
|
then
|
||||||
|
echo >&2 "Found WIP commit in $local_ref, not pushing"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
exit 0
|
||||||
169
tests/gitea-repositories-meta/user2/repo-release.git/hooks/pre-rebase.sample
Executable file
169
tests/gitea-repositories-meta/user2/repo-release.git/hooks/pre-rebase.sample
Executable file
@@ -0,0 +1,169 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# Copyright (c) 2006, 2008 Junio C Hamano
|
||||||
|
#
|
||||||
|
# The "pre-rebase" hook is run just before "git rebase" starts doing
|
||||||
|
# its job, and can prevent the command from running by exiting with
|
||||||
|
# non-zero status.
|
||||||
|
#
|
||||||
|
# The hook is called with the following parameters:
|
||||||
|
#
|
||||||
|
# $1 -- the upstream the series was forked from.
|
||||||
|
# $2 -- the branch being rebased (or empty when rebasing the current branch).
|
||||||
|
#
|
||||||
|
# This sample shows how to prevent topic branches that are already
|
||||||
|
# merged to 'next' branch from getting rebased, because allowing it
|
||||||
|
# would result in rebasing already published history.
|
||||||
|
|
||||||
|
publish=next
|
||||||
|
basebranch="$1"
|
||||||
|
if test "$#" = 2
|
||||||
|
then
|
||||||
|
topic="refs/heads/$2"
|
||||||
|
else
|
||||||
|
topic=`git symbolic-ref HEAD` ||
|
||||||
|
exit 0 ;# we do not interrupt rebasing detached HEAD
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "$topic" in
|
||||||
|
refs/heads/??/*)
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
exit 0 ;# we do not interrupt others.
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Now we are dealing with a topic branch being rebased
|
||||||
|
# on top of master. Is it OK to rebase it?
|
||||||
|
|
||||||
|
# Does the topic really exist?
|
||||||
|
git show-ref -q "$topic" || {
|
||||||
|
echo >&2 "No such branch $topic"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Is topic fully merged to master?
|
||||||
|
not_in_master=`git rev-list --pretty=oneline ^master "$topic"`
|
||||||
|
if test -z "$not_in_master"
|
||||||
|
then
|
||||||
|
echo >&2 "$topic is fully merged to master; better remove it."
|
||||||
|
exit 1 ;# we could allow it, but there is no point.
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Is topic ever merged to next? If so you should not be rebasing it.
|
||||||
|
only_next_1=`git rev-list ^master "^$topic" ${publish} | sort`
|
||||||
|
only_next_2=`git rev-list ^master ${publish} | sort`
|
||||||
|
if test "$only_next_1" = "$only_next_2"
|
||||||
|
then
|
||||||
|
not_in_topic=`git rev-list "^$topic" master`
|
||||||
|
if test -z "$not_in_topic"
|
||||||
|
then
|
||||||
|
echo >&2 "$topic is already up to date with master"
|
||||||
|
exit 1 ;# we could allow it, but there is no point.
|
||||||
|
else
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"`
|
||||||
|
/usr/bin/perl -e '
|
||||||
|
my $topic = $ARGV[0];
|
||||||
|
my $msg = "* $topic has commits already merged to public branch:\n";
|
||||||
|
my (%not_in_next) = map {
|
||||||
|
/^([0-9a-f]+) /;
|
||||||
|
($1 => 1);
|
||||||
|
} split(/\n/, $ARGV[1]);
|
||||||
|
for my $elem (map {
|
||||||
|
/^([0-9a-f]+) (.*)$/;
|
||||||
|
[$1 => $2];
|
||||||
|
} split(/\n/, $ARGV[2])) {
|
||||||
|
if (!exists $not_in_next{$elem->[0]}) {
|
||||||
|
if ($msg) {
|
||||||
|
print STDERR $msg;
|
||||||
|
undef $msg;
|
||||||
|
}
|
||||||
|
print STDERR " $elem->[1]\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
' "$topic" "$not_in_next" "$not_in_master"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
<<\DOC_END
|
||||||
|
|
||||||
|
This sample hook safeguards topic branches that have been
|
||||||
|
published from being rewound.
|
||||||
|
|
||||||
|
The workflow assumed here is:
|
||||||
|
|
||||||
|
* Once a topic branch forks from "master", "master" is never
|
||||||
|
merged into it again (either directly or indirectly).
|
||||||
|
|
||||||
|
* Once a topic branch is fully cooked and merged into "master",
|
||||||
|
it is deleted. If you need to build on top of it to correct
|
||||||
|
earlier mistakes, a new topic branch is created by forking at
|
||||||
|
the tip of the "master". This is not strictly necessary, but
|
||||||
|
it makes it easier to keep your history simple.
|
||||||
|
|
||||||
|
* Whenever you need to test or publish your changes to topic
|
||||||
|
branches, merge them into "next" branch.
|
||||||
|
|
||||||
|
The script, being an example, hardcodes the publish branch name
|
||||||
|
to be "next", but it is trivial to make it configurable via
|
||||||
|
$GIT_DIR/config mechanism.
|
||||||
|
|
||||||
|
With this workflow, you would want to know:
|
||||||
|
|
||||||
|
(1) ... if a topic branch has ever been merged to "next". Young
|
||||||
|
topic branches can have stupid mistakes you would rather
|
||||||
|
clean up before publishing, and things that have not been
|
||||||
|
merged into other branches can be easily rebased without
|
||||||
|
affecting other people. But once it is published, you would
|
||||||
|
not want to rewind it.
|
||||||
|
|
||||||
|
(2) ... if a topic branch has been fully merged to "master".
|
||||||
|
Then you can delete it. More importantly, you should not
|
||||||
|
build on top of it -- other people may already want to
|
||||||
|
change things related to the topic as patches against your
|
||||||
|
"master", so if you need further changes, it is better to
|
||||||
|
fork the topic (perhaps with the same name) afresh from the
|
||||||
|
tip of "master".
|
||||||
|
|
||||||
|
Let's look at this example:
|
||||||
|
|
||||||
|
o---o---o---o---o---o---o---o---o---o "next"
|
||||||
|
/ / / /
|
||||||
|
/ a---a---b A / /
|
||||||
|
/ / / /
|
||||||
|
/ / c---c---c---c B /
|
||||||
|
/ / / \ /
|
||||||
|
/ / / b---b C \ /
|
||||||
|
/ / / / \ /
|
||||||
|
---o---o---o---o---o---o---o---o---o---o---o "master"
|
||||||
|
|
||||||
|
|
||||||
|
A, B and C are topic branches.
|
||||||
|
|
||||||
|
* A has one fix since it was merged up to "next".
|
||||||
|
|
||||||
|
* B has finished. It has been fully merged up to "master" and "next",
|
||||||
|
and is ready to be deleted.
|
||||||
|
|
||||||
|
* C has not merged to "next" at all.
|
||||||
|
|
||||||
|
We would want to allow C to be rebased, refuse A, and encourage
|
||||||
|
B to be deleted.
|
||||||
|
|
||||||
|
To compute (1):
|
||||||
|
|
||||||
|
git rev-list ^master ^topic next
|
||||||
|
git rev-list ^master next
|
||||||
|
|
||||||
|
if these match, topic has not merged in next at all.
|
||||||
|
|
||||||
|
To compute (2):
|
||||||
|
|
||||||
|
git rev-list master..topic
|
||||||
|
|
||||||
|
if this is empty, it is fully merged to "master".
|
||||||
|
|
||||||
|
DOC_END
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# An example hook script to make use of push options.
|
||||||
|
# The example simply echoes all push options that start with 'echoback='
|
||||||
|
# and rejects all pushes when the "reject" push option is used.
|
||||||
|
#
|
||||||
|
# To enable this hook, rename this file to "pre-receive".
|
||||||
|
|
||||||
|
if test -n "$GIT_PUSH_OPTION_COUNT"
|
||||||
|
then
|
||||||
|
i=0
|
||||||
|
while test "$i" -lt "$GIT_PUSH_OPTION_COUNT"
|
||||||
|
do
|
||||||
|
eval "value=\$GIT_PUSH_OPTION_$i"
|
||||||
|
case "$value" in
|
||||||
|
echoback=*)
|
||||||
|
echo "echo from the pre-receive-hook: ${value#*=}" >&2
|
||||||
|
;;
|
||||||
|
reject)
|
||||||
|
exit 1
|
||||||
|
esac
|
||||||
|
i=$((i + 1))
|
||||||
|
done
|
||||||
|
fi
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# An example hook script to prepare the commit log message.
|
||||||
|
# Called by "git commit" with the name of the file that has the
|
||||||
|
# commit message, followed by the description of the commit
|
||||||
|
# message's source. The hook's purpose is to edit the commit
|
||||||
|
# message file. If the hook fails with a non-zero status,
|
||||||
|
# the commit is aborted.
|
||||||
|
#
|
||||||
|
# To enable this hook, rename this file to "prepare-commit-msg".
|
||||||
|
|
||||||
|
# This hook includes three examples. The first one removes the
|
||||||
|
# "# Please enter the commit message..." help message.
|
||||||
|
#
|
||||||
|
# The second includes the output of "git diff --name-status -r"
|
||||||
|
# into the message, just before the "git status" output. It is
|
||||||
|
# commented because it doesn't cope with --amend or with squashed
|
||||||
|
# commits.
|
||||||
|
#
|
||||||
|
# The third example adds a Signed-off-by line to the message, that can
|
||||||
|
# still be edited. This is rarely a good idea.
|
||||||
|
|
||||||
|
COMMIT_MSG_FILE=$1
|
||||||
|
COMMIT_SOURCE=$2
|
||||||
|
SHA1=$3
|
||||||
|
|
||||||
|
/usr/bin/perl -i.bak -ne 'print unless(m/^. Please enter the commit message/..m/^#$/)' "$COMMIT_MSG_FILE"
|
||||||
|
|
||||||
|
# case "$COMMIT_SOURCE,$SHA1" in
|
||||||
|
# ,|template,)
|
||||||
|
# /usr/bin/perl -i.bak -pe '
|
||||||
|
# print "\n" . `git diff --cached --name-status -r`
|
||||||
|
# if /^#/ && $first++ == 0' "$COMMIT_MSG_FILE" ;;
|
||||||
|
# *) ;;
|
||||||
|
# esac
|
||||||
|
|
||||||
|
# SOB=$(git var GIT_COMMITTER_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
|
||||||
|
# git interpret-trailers --in-place --trailer "$SOB" "$COMMIT_MSG_FILE"
|
||||||
|
# if test -z "$COMMIT_SOURCE"
|
||||||
|
# then
|
||||||
|
# /usr/bin/perl -i.bak -pe 'print "\n" if !$first_line++' "$COMMIT_MSG_FILE"
|
||||||
|
# fi
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# An example hook script to update a checked-out tree on a git push.
|
||||||
|
#
|
||||||
|
# This hook is invoked by git-receive-pack(1) when it reacts to git
|
||||||
|
# push and updates reference(s) in its repository, and when the push
|
||||||
|
# tries to update the branch that is currently checked out and the
|
||||||
|
# receive.denyCurrentBranch configuration variable is set to
|
||||||
|
# updateInstead.
|
||||||
|
#
|
||||||
|
# By default, such a push is refused if the working tree and the index
|
||||||
|
# of the remote repository has any difference from the currently
|
||||||
|
# checked out commit; when both the working tree and the index match
|
||||||
|
# the current commit, they are updated to match the newly pushed tip
|
||||||
|
# of the branch. This hook is to be used to override the default
|
||||||
|
# behaviour; however the code below reimplements the default behaviour
|
||||||
|
# as a starting point for convenient modification.
|
||||||
|
#
|
||||||
|
# The hook receives the commit with which the tip of the current
|
||||||
|
# branch is going to be updated:
|
||||||
|
commit=$1
|
||||||
|
|
||||||
|
# It can exit with a non-zero status to refuse the push (when it does
|
||||||
|
# so, it must not modify the index or the working tree).
|
||||||
|
die () {
|
||||||
|
echo >&2 "$*"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Or it can make any necessary changes to the working tree and to the
|
||||||
|
# index to bring them to the desired state when the tip of the current
|
||||||
|
# branch is updated to the new commit, and exit with a zero status.
|
||||||
|
#
|
||||||
|
# For example, the hook can simply run git read-tree -u -m HEAD "$1"
|
||||||
|
# in order to emulate git fetch that is run in the reverse direction
|
||||||
|
# with git push, as the two-tree form of git read-tree -u -m is
|
||||||
|
# essentially the same as git switch or git checkout that switches
|
||||||
|
# branches while keeping the local changes in the working tree that do
|
||||||
|
# not interfere with the difference between the branches.
|
||||||
|
|
||||||
|
# The below is a more-or-less exact translation to shell of the C code
|
||||||
|
# for the default behaviour for git's push-to-checkout hook defined in
|
||||||
|
# the push_to_deploy() function in builtin/receive-pack.c.
|
||||||
|
#
|
||||||
|
# Note that the hook will be executed from the repository directory,
|
||||||
|
# not from the working tree, so if you want to perform operations on
|
||||||
|
# the working tree, you will have to adapt your code accordingly, e.g.
|
||||||
|
# by adding "cd .." or using relative paths.
|
||||||
|
|
||||||
|
if ! git update-index -q --ignore-submodules --refresh
|
||||||
|
then
|
||||||
|
die "Up-to-date check failed"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! git diff-files --quiet --ignore-submodules --
|
||||||
|
then
|
||||||
|
die "Working directory has unstaged changes"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# This is a rough translation of:
|
||||||
|
#
|
||||||
|
# head_has_history() ? "HEAD" : EMPTY_TREE_SHA1_HEX
|
||||||
|
if git cat-file -e HEAD 2>/dev/null
|
||||||
|
then
|
||||||
|
head=HEAD
|
||||||
|
else
|
||||||
|
head=$(git hash-object -t tree --stdin </dev/null)
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! git diff-index --quiet --cached --ignore-submodules $head --
|
||||||
|
then
|
||||||
|
die "Working directory has staged changes"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! git read-tree -u -m "$commit"
|
||||||
|
then
|
||||||
|
die "Could not update working tree to new HEAD"
|
||||||
|
fi
|
||||||
128
tests/gitea-repositories-meta/user2/repo-release.git/hooks/update.sample
Executable file
128
tests/gitea-repositories-meta/user2/repo-release.git/hooks/update.sample
Executable file
@@ -0,0 +1,128 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# An example hook script to block unannotated tags from entering.
|
||||||
|
# Called by "git receive-pack" with arguments: refname sha1-old sha1-new
|
||||||
|
#
|
||||||
|
# To enable this hook, rename this file to "update".
|
||||||
|
#
|
||||||
|
# Config
|
||||||
|
# ------
|
||||||
|
# hooks.allowunannotated
|
||||||
|
# This boolean sets whether unannotated tags will be allowed into the
|
||||||
|
# repository. By default they won't be.
|
||||||
|
# hooks.allowdeletetag
|
||||||
|
# This boolean sets whether deleting tags will be allowed in the
|
||||||
|
# repository. By default they won't be.
|
||||||
|
# hooks.allowmodifytag
|
||||||
|
# This boolean sets whether a tag may be modified after creation. By default
|
||||||
|
# it won't be.
|
||||||
|
# hooks.allowdeletebranch
|
||||||
|
# This boolean sets whether deleting branches will be allowed in the
|
||||||
|
# repository. By default they won't be.
|
||||||
|
# hooks.denycreatebranch
|
||||||
|
# This boolean sets whether remotely creating branches will be denied
|
||||||
|
# in the repository. By default this is allowed.
|
||||||
|
#
|
||||||
|
|
||||||
|
# --- Command line
|
||||||
|
refname="$1"
|
||||||
|
oldrev="$2"
|
||||||
|
newrev="$3"
|
||||||
|
|
||||||
|
# --- Safety check
|
||||||
|
if [ -z "$GIT_DIR" ]; then
|
||||||
|
echo "Don't run this script from the command line." >&2
|
||||||
|
echo " (if you want, you could supply GIT_DIR then run" >&2
|
||||||
|
echo " $0 <ref> <oldrev> <newrev>)" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then
|
||||||
|
echo "usage: $0 <ref> <oldrev> <newrev>" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# --- Config
|
||||||
|
allowunannotated=$(git config --type=bool hooks.allowunannotated)
|
||||||
|
allowdeletebranch=$(git config --type=bool hooks.allowdeletebranch)
|
||||||
|
denycreatebranch=$(git config --type=bool hooks.denycreatebranch)
|
||||||
|
allowdeletetag=$(git config --type=bool hooks.allowdeletetag)
|
||||||
|
allowmodifytag=$(git config --type=bool hooks.allowmodifytag)
|
||||||
|
|
||||||
|
# check for no description
|
||||||
|
projectdesc=$(sed -e '1q' "$GIT_DIR/description")
|
||||||
|
case "$projectdesc" in
|
||||||
|
"Unnamed repository"* | "")
|
||||||
|
echo "*** Project description file hasn't been set" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# --- Check types
|
||||||
|
# if $newrev is 0000...0000, it's a commit to delete a ref.
|
||||||
|
zero=$(git hash-object --stdin </dev/null | tr '[0-9a-f]' '0')
|
||||||
|
if [ "$newrev" = "$zero" ]; then
|
||||||
|
newrev_type=delete
|
||||||
|
else
|
||||||
|
newrev_type=$(git cat-file -t $newrev)
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "$refname","$newrev_type" in
|
||||||
|
refs/tags/*,commit)
|
||||||
|
# un-annotated tag
|
||||||
|
short_refname=${refname##refs/tags/}
|
||||||
|
if [ "$allowunannotated" != "true" ]; then
|
||||||
|
echo "*** The un-annotated tag, $short_refname, is not allowed in this repository" >&2
|
||||||
|
echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
refs/tags/*,delete)
|
||||||
|
# delete tag
|
||||||
|
if [ "$allowdeletetag" != "true" ]; then
|
||||||
|
echo "*** Deleting a tag is not allowed in this repository" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
refs/tags/*,tag)
|
||||||
|
# annotated tag
|
||||||
|
if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1
|
||||||
|
then
|
||||||
|
echo "*** Tag '$refname' already exists." >&2
|
||||||
|
echo "*** Modifying a tag is not allowed in this repository." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
refs/heads/*,commit)
|
||||||
|
# branch
|
||||||
|
if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then
|
||||||
|
echo "*** Creating a branch is not allowed in this repository" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
refs/heads/*,delete)
|
||||||
|
# delete branch
|
||||||
|
if [ "$allowdeletebranch" != "true" ]; then
|
||||||
|
echo "*** Deleting a branch is not allowed in this repository" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
refs/remotes/*,commit)
|
||||||
|
# tracking branch
|
||||||
|
;;
|
||||||
|
refs/remotes/*,delete)
|
||||||
|
# delete tracking branch
|
||||||
|
if [ "$allowdeletebranch" != "true" ]; then
|
||||||
|
echo "*** Deleting a tracking branch is not allowed in this repository" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
# Anything else (is there anything else?)
|
||||||
|
echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# --- Finished
|
||||||
|
exit 0
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
# git ls-files --others --exclude-from=.git/info/exclude
|
||||||
|
# Lines that start with '#' are comments.
|
||||||
|
# For a project mostly in C, the following would be a good set of
|
||||||
|
# exclude patterns (uncomment them if you want to use them):
|
||||||
|
# *.[oa]
|
||||||
|
# *~
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user