mirror of
https://github.com/go-gitea/gitea
synced 2026-02-09 23:28:09 +00:00
Compare commits
104 Commits
v1.21.8
...
release/v1.21
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ec4fa231c7 | ||
|
|
33d4d32096 | ||
|
|
17c6a3862d | ||
|
|
30a593dfbb | ||
|
|
6c235f4959 | ||
|
|
1389fa8a99 | ||
|
|
87bd47cff3 | ||
|
|
0f2035d52f | ||
|
|
954962ca61 | ||
|
|
aa3c76159a | ||
|
|
224c48e16b | ||
|
|
7aba99af5e | ||
|
|
c5f37af8cd | ||
|
|
7aa8b8e2d2 | ||
|
|
ddf64b84e4 | ||
|
|
03518d3e18 | ||
|
|
fcdc57d811 | ||
|
|
f394cd70ac | ||
|
|
32f895f2d7 | ||
|
|
d95408bd5d | ||
|
|
1c1c94b061 | ||
|
|
0e20ccfe32 | ||
|
|
08822651a6 | ||
|
|
79484e1cb7 | ||
|
|
667427b4b9 | ||
|
|
2566f6ce8a | ||
|
|
944f1ec54c | ||
|
|
a05d098a37 | ||
|
|
332ee359ce | ||
|
|
a82bf022bf | ||
|
|
acdcfcc6eb | ||
|
|
727b1914b4 | ||
|
|
60181eb599 | ||
|
|
a0ca311165 | ||
|
|
430fe6c0c1 | ||
|
|
b6379d2f16 | ||
|
|
928c0d4f46 | ||
|
|
222d16e6ea | ||
|
|
09df5c9c7d | ||
|
|
fc4e08f804 | ||
|
|
68bd1dd89d | ||
|
|
55990ebf92 | ||
|
|
245e8d10c2 | ||
|
|
529604a044 | ||
|
|
6cfe67cfc3 | ||
|
|
9149221845 | ||
|
|
6e3aaa9975 | ||
|
|
3f6ddd9bee | ||
|
|
65d96725bb | ||
|
|
4588c7b705 | ||
|
|
47de6e3b54 | ||
|
|
5123ed3191 | ||
|
|
9f2a1a55e6 | ||
|
|
935bfe6445 | ||
|
|
2ac78c75d0 | ||
|
|
b1dae9f2c8 | ||
|
|
7bffb923ce | ||
|
|
0c10c3a282 | ||
|
|
09a5067c0c | ||
|
|
a0f89ba8c7 | ||
|
|
6d47b63be2 | ||
|
|
8dccea02f2 | ||
|
|
03f29db46d | ||
|
|
d6b0d0e9c0 | ||
|
|
087aed7096 | ||
|
|
78795dd566 | ||
|
|
e321b8a849 | ||
|
|
2172b38d50 | ||
|
|
01f736f68c | ||
|
|
688107651c | ||
|
|
24c66c5096 | ||
|
|
e1e88f9ad1 | ||
|
|
f91b4dd959 | ||
|
|
6ef986d474 | ||
|
|
c03b1e2854 | ||
|
|
3ff3c5ba78 | ||
|
|
58a0ba711d | ||
|
|
b4a6c6fd7a | ||
|
|
3fd15aeff2 | ||
|
|
0873088223 | ||
|
|
ff27ca32ca | ||
|
|
eb302deb18 | ||
|
|
aae96cc62b | ||
|
|
5f7b6b55a5 | ||
|
|
408c92938b | ||
|
|
b9dd5dd471 | ||
|
|
440be51a45 | ||
|
|
00ea9af8e1 | ||
|
|
c044510ca8 | ||
|
|
85f31eb643 | ||
|
|
8242c3c88c | ||
|
|
0cbbcf20e3 | ||
|
|
47dc4598a3 | ||
|
|
817d5e4d30 | ||
|
|
31ab839a65 | ||
|
|
df23ec0f8b | ||
|
|
e0a9a921af | ||
|
|
e03cf66e8b | ||
|
|
61db562a5f | ||
|
|
538efb9df7 | ||
|
|
5e3581f073 | ||
|
|
bb9860307f | ||
|
|
bb2640c485 | ||
|
|
462ae88fc2 |
+69
-21
@@ -1,36 +1,84 @@
|
||||
modifies/docs:
|
||||
- "**/*.md"
|
||||
- "docs/**"
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "**/*.md"
|
||||
- "docs/**"
|
||||
|
||||
modifies/frontend:
|
||||
- "web_src/**/*"
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "web_src/**"
|
||||
- "tailwind.config.js"
|
||||
- "webpack.config.js"
|
||||
|
||||
modifies/templates:
|
||||
- all: ["templates/**", "!templates/swagger/v1_json.tmpl"]
|
||||
- changed-files:
|
||||
- all-globs-to-any-file:
|
||||
- "templates/**"
|
||||
- "!templates/swagger/v1_json.tmpl"
|
||||
|
||||
modifies/api:
|
||||
- "routers/api/**"
|
||||
- "templates/swagger/v1_json.tmpl"
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "routers/api/**"
|
||||
- "templates/swagger/v1_json.tmpl"
|
||||
|
||||
modifies/cli:
|
||||
- "cmd/**"
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "cmd/**"
|
||||
|
||||
modifies/translation:
|
||||
- "options/locale/*.ini"
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "options/locale/*.ini"
|
||||
|
||||
modifies/migrations:
|
||||
- "models/migrations/**/*"
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "models/migrations/**"
|
||||
|
||||
modifies/internal:
|
||||
- "Makefile"
|
||||
- "Dockerfile"
|
||||
- "Dockerfile.rootless"
|
||||
- "docker/**"
|
||||
- "webpack.config.js"
|
||||
- ".eslintrc.yaml"
|
||||
- ".golangci.yml"
|
||||
- ".markdownlint.yaml"
|
||||
- ".spectral.yaml"
|
||||
- ".stylelintrc.yaml"
|
||||
- ".yamllint.yaml"
|
||||
- ".github/**"
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- ".air.toml"
|
||||
- "Makefile"
|
||||
- "Dockerfile"
|
||||
- "Dockerfile.rootless"
|
||||
- ".dockerignore"
|
||||
- "docker/**"
|
||||
- ".editorconfig"
|
||||
- ".eslintrc.yaml"
|
||||
- ".golangci.yml"
|
||||
- ".gitpod.yml"
|
||||
- ".markdownlint.yaml"
|
||||
- ".spectral.yaml"
|
||||
- ".stylelintrc.yaml"
|
||||
- ".yamllint.yaml"
|
||||
- ".github/**"
|
||||
- ".gitea/"
|
||||
- ".devcontainer/**"
|
||||
- "build.go"
|
||||
- "build/**"
|
||||
- "contrib/**"
|
||||
|
||||
modifies/dependencies:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "package.json"
|
||||
- "package-lock.json"
|
||||
- "poetry.toml"
|
||||
- "poetry.lock"
|
||||
- "go.mod"
|
||||
- "go.sum"
|
||||
- "pyproject.toml"
|
||||
|
||||
modifies/go:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "**/*.go"
|
||||
|
||||
modifies/js:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "**/*.js"
|
||||
|
||||
@@ -58,9 +58,11 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
cache: npm
|
||||
cache-dependency-path: package-lock.json
|
||||
- run: make deps-frontend
|
||||
- run: make lint-swagger
|
||||
|
||||
@@ -127,9 +129,11 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
cache: npm
|
||||
cache-dependency-path: package-lock.json
|
||||
- run: make deps-frontend
|
||||
- run: make lint-frontend
|
||||
- run: make checks-frontend
|
||||
@@ -174,9 +178,11 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
cache: npm
|
||||
cache-dependency-path: package-lock.json
|
||||
- run: make deps-frontend
|
||||
- run: make lint-md
|
||||
- run: make docs
|
||||
|
||||
@@ -21,9 +21,11 @@ jobs:
|
||||
with:
|
||||
go-version: "~1.21"
|
||||
check-latest: true
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
cache: npm
|
||||
cache-dependency-path: package-lock.json
|
||||
- run: make deps-frontend frontend deps-backend
|
||||
- run: npx playwright install --with-deps
|
||||
- run: make test-e2e-sqlite
|
||||
|
||||
@@ -9,13 +9,12 @@ concurrency:
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
label:
|
||||
labeler:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
steps:
|
||||
- uses: actions/labeler@v4
|
||||
- uses: actions/labeler@v5
|
||||
with:
|
||||
dot: true
|
||||
sync-labels: true
|
||||
|
||||
@@ -20,9 +20,11 @@ jobs:
|
||||
with:
|
||||
go-version: "~1.21"
|
||||
check-latest: true
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
cache: npm
|
||||
cache-dependency-path: package-lock.json
|
||||
- run: make deps-frontend deps-backend
|
||||
# xgo build
|
||||
- run: make release
|
||||
|
||||
@@ -21,9 +21,11 @@ jobs:
|
||||
with:
|
||||
go-version: "~1.21"
|
||||
check-latest: true
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
cache: npm
|
||||
cache-dependency-path: package-lock.json
|
||||
- run: make deps-frontend deps-backend
|
||||
# xgo build
|
||||
- run: make release
|
||||
|
||||
@@ -23,9 +23,11 @@ jobs:
|
||||
with:
|
||||
go-version: "~1.21"
|
||||
check-latest: true
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
cache: npm
|
||||
cache-dependency-path: package-lock.json
|
||||
- run: make deps-frontend deps-backend
|
||||
# xgo build
|
||||
- run: make release
|
||||
|
||||
+81
-2
@@ -4,7 +4,86 @@ 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
|
||||
been added to each release, please refer to the [blog](https://blog.gitea.com).
|
||||
|
||||
## [1.21.8](https://github.com/go-gitea/gitea/releases/tag/1.21.8) - 2024-03-12
|
||||
## [1.21.11](https://github.com/go-gitea/gitea/releases/tag/v1.21.11) - 2024-04-07
|
||||
|
||||
* SECURITY
|
||||
* Use go1.21.9 to include Golang security fix
|
||||
* Fix possible renderer security problem (#30136) (#30315)
|
||||
* Performance optimization for git push and check permissions for push options (#30104) (#30354)
|
||||
* BUGFIXES
|
||||
* Fix close file in the Upload func (#30262) (#30269)
|
||||
* Fix inline math blocks can't be preceeded/followed by alphanumerical characters (#30175) (#30250)
|
||||
* Fix missing 0 prefix of GPG key id (#30245) (#30247)
|
||||
* Include encoding in signature payload (#30174) (#30181)
|
||||
* Move from `max( id )` to `max( index )` for latest commit statuses (#30076) (#30155)
|
||||
* Load attachments for code comments (#30124) (#30126)
|
||||
* Fix gitea doctor will remove repo-avatar files when executing command storage-archives (#30094) (#30120)
|
||||
* Fix possible data race on tests (#30093) (#30108)
|
||||
* Fix duplicate migrated milestones (#30102) (#30105)
|
||||
* Fix panic for fixBrokenRepoUnits16961 (#30068) (#30100)
|
||||
* Fix incorrect SVGs (#30086) (#30087)
|
||||
* Fix create commit status (#30225) (#30340)
|
||||
* Fix misuse of unsupported global variables (#30402)
|
||||
* Fix to delete the cookie when AppSubURL is non-empty (#30375) (#30468)
|
||||
* Avoid user does not exist error when detecting schedule actions when the commit author is an external user (#30357) (#30408)
|
||||
* Change the default maxPerPage for gitbucket (#30392) (#30471)
|
||||
* Check the token's owner and repository when registering a runner (#30406) (#30412)
|
||||
* Avoid losing token when updating mirror settings (#30429) (#30466)
|
||||
* Fix commit status cache which missed target_url (#30426) (#30445)
|
||||
* Fix rename branch 500 when the target branch is deleted but exist in database (#30430) (#30437)
|
||||
* Fix mirror error when mirror repo is empty (#30432) (#30467)
|
||||
* Use db.ListOptions directly instead of Paginator interface to make it easier to use and fix performance of /pulls and /issues (#29990) (#30447)
|
||||
* Fix code owners will not be mentioned when a pull request comes from a forked repository (#30476) (#30497)
|
||||
* DOCS
|
||||
* Update actions variables documents (#30394) (#30405)
|
||||
* MISC
|
||||
* Update katex to 0.16.10 (#30089)
|
||||
* Upgrade go-sqlite to v1.14.22 (#30462)
|
||||
|
||||
## [1.21.10](https://github.com/go-gitea/gitea/releases/tag/v1.21.10) - 2024-03-25
|
||||
|
||||
* BUGFIXES
|
||||
* Fix Add/Remove WIP on pull request title failure (#29999) (#30066)
|
||||
* Fix misuse of `TxContext` (#30061) (#30062)
|
||||
* Respect DEFAULT_ORG_MEMBER_VISIBLE setting when adding creator to org (#30013) (#30035)
|
||||
* Escape paths for find file correctly (#30026) (#30031)
|
||||
* Remove duplicate option in admin screen and now-unused translation keys (#28492) (#30024)
|
||||
* Fix manual merge form and 404 page templates (#30000)
|
||||
|
||||
## [1.21.9](https://github.com/go-gitea/gitea/releases/tag/v1.21.9) - 2024-03-21
|
||||
|
||||
* PERFORMANCE
|
||||
* Only do counting when count_only=true for repo dashboard (#29884) (#29905)
|
||||
* Add cache for dashboard commit status (#29932)
|
||||
* ENHANCEMENT
|
||||
* Make runs-on support variable expression (#29468) (#29782)
|
||||
* Show Actions post step when it's running (#29926) (#29928)
|
||||
* BUGFIXES
|
||||
* Fix PR creation via API between branches of the same repo with head field namespaced (#26986) (#29857)
|
||||
* Fix and rewrite markup anchor processing (#29931) (#29946)
|
||||
* Notify reviewers added via CODEOWNERS (#29842) (#29902)
|
||||
* Fix template error when comment review doesn't exist (#29888) (#29889)
|
||||
* Fix user id column case (#29863) (#29867)
|
||||
* Make meilisearch do exact search for issues (#29740 & #29671) (#29846)
|
||||
* Fix the `for` attribute not pointing to the ID of the color picker (#29813) (#29815)
|
||||
* Fix codeowner detected diff base branch to mergebase (#29783) (#29807)
|
||||
* Fix Safari spinner rendering (#29801) (#29802)
|
||||
* Fix missing translation on milestones (#29785) (#29789)
|
||||
* Fix user router possible panic (#29751) (#29786)
|
||||
* Fix possible NPE in ToPullReviewList (#29759) (#29775)
|
||||
* Fix the wrong default value of ENABLE_OPENID_SIGNIN on docs (#29925) (#29927)
|
||||
* Solving the issue of UI disruption when the review is deleted without refreshing (#29951) (#29968)
|
||||
* Fix loadOneBranch panic (#29938) (#29939)
|
||||
* Fix invalid link of the commit status when ref is tagged (#29752) (#29908)
|
||||
* Editor error message misleading due to re-used key. (#29859) (#29876)
|
||||
* Fix double border and border-radius on empty action steps (#29845) (#29850)
|
||||
* Use `Temporal.PlainDate` for absolute dates (#29804) (#29808)
|
||||
* Fix incorrect package link method calls in templates (#29580) (#29764)
|
||||
* Fix the bug that the user may log out if GetUserByID returns unknown error (#29962) (#29964)
|
||||
* Performance improvements for pull request list page (#29900) (#29972)
|
||||
* Fix bugs in rerunning jobs (#29983) (#29955)
|
||||
|
||||
## [1.21.8](https://github.com/go-gitea/gitea/releases/tag/v1.21.8) - 2024-03-12
|
||||
|
||||
* SECURITY
|
||||
* Only use supported sort orders for "/explore/users" page (#29430) (#29443)
|
||||
@@ -49,7 +128,7 @@ been added to each release, please refer to the [blog](https://blog.gitea.com).
|
||||
* Fixing the issue when status checks per rule matches multiple actions (#29631) (#29655)
|
||||
* Improve contrast on blame timestamp, fix double border (#29482) (#29485)
|
||||
|
||||
## [1.21.7](https://github.com/go-gitea/gitea/releases/tag/1.21.7) - 2024-02-26
|
||||
## [1.21.7](https://github.com/go-gitea/gitea/releases/tag/v1.21.7) - 2024-02-26
|
||||
|
||||
* ENHANCEMENTS
|
||||
* Users with `read` permission of pull requests can be assigned too (#27263) (#29372)
|
||||
|
||||
@@ -959,8 +959,9 @@ webpack: $(WEBPACK_DEST)
|
||||
|
||||
$(WEBPACK_DEST): $(WEBPACK_SOURCES) $(WEBPACK_CONFIGS) package-lock.json
|
||||
@$(MAKE) -s node-check node_modules
|
||||
rm -rf $(WEBPACK_DEST_ENTRIES)
|
||||
npx webpack
|
||||
@rm -rf $(WEBPACK_DEST_ENTRIES)
|
||||
@echo "Running webpack..."
|
||||
@BROWSERSLIST_IGNORE_OLD_DATA=true npx webpack
|
||||
@touch $(WEBPACK_DEST)
|
||||
|
||||
.PHONY: svg
|
||||
@@ -1009,7 +1010,7 @@ generate-gitignore:
|
||||
|
||||
.PHONY: generate-images
|
||||
generate-images: | node_modules
|
||||
npm install --no-save --no-package-lock fabric@5 imagemin-zopfli@7
|
||||
npm install --no-save fabric@6.0.0-rc1 imagemin-zopfli@7
|
||||
node build/generate-images.js $(TAGS)
|
||||
|
||||
.PHONY: generate-manpage
|
||||
|
||||
Generated
+5
-5
File diff suppressed because one or more lines are too long
+15
-18
@@ -1,20 +1,13 @@
|
||||
#!/usr/bin/env node
|
||||
import imageminZopfli from 'imagemin-zopfli';
|
||||
import {loadSVGFromString, Canvas, Rect, util} from 'fabric/node';
|
||||
import {optimize} from 'svgo';
|
||||
import {fabric} from 'fabric';
|
||||
import {readFile, writeFile} from 'node:fs/promises';
|
||||
import {argv, exit} from 'node:process';
|
||||
|
||||
function exit(err) {
|
||||
function doExit(err) {
|
||||
if (err) console.error(err);
|
||||
process.exit(err ? 1 : 0);
|
||||
}
|
||||
|
||||
function loadSvg(svg) {
|
||||
return new Promise((resolve) => {
|
||||
fabric.loadSVGFromString(svg, (objects, options) => {
|
||||
resolve({objects, options});
|
||||
});
|
||||
});
|
||||
exit(err ? 1 : 0);
|
||||
}
|
||||
|
||||
async function generate(svg, path, {size, bg}) {
|
||||
@@ -27,7 +20,7 @@ async function generate(svg, path, {size, bg}) {
|
||||
'removeDimensions',
|
||||
{
|
||||
name: 'addAttributesToSVGElement',
|
||||
params: {attributes: [{width: size}, {height: size}]}
|
||||
params: {attributes: [{width: size}, {height: size}]},
|
||||
},
|
||||
],
|
||||
});
|
||||
@@ -35,14 +28,14 @@ async function generate(svg, path, {size, bg}) {
|
||||
return;
|
||||
}
|
||||
|
||||
const {objects, options} = await loadSvg(svg);
|
||||
const canvas = new fabric.Canvas();
|
||||
const {objects, options} = await loadSVGFromString(svg);
|
||||
const canvas = new Canvas();
|
||||
canvas.setDimensions({width: size, height: size});
|
||||
const ctx = canvas.getContext('2d');
|
||||
ctx.scale(options.width ? (size / options.width) : 1, options.height ? (size / options.height) : 1);
|
||||
|
||||
if (bg) {
|
||||
canvas.add(new fabric.Rect({
|
||||
canvas.add(new Rect({
|
||||
left: 0,
|
||||
top: 0,
|
||||
height: size * (1 / (size / options.height)),
|
||||
@@ -51,7 +44,7 @@ async function generate(svg, path, {size, bg}) {
|
||||
}));
|
||||
}
|
||||
|
||||
canvas.add(fabric.util.groupSVGElements(objects, options));
|
||||
canvas.add(util.groupSVGElements(objects, options));
|
||||
canvas.renderAll();
|
||||
|
||||
let png = Buffer.from([]);
|
||||
@@ -64,7 +57,7 @@ async function generate(svg, path, {size, bg}) {
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const gitea = process.argv.slice(2).includes('gitea');
|
||||
const gitea = argv.slice(2).includes('gitea');
|
||||
const logoSvg = await readFile(new URL('../assets/logo.svg', import.meta.url), 'utf8');
|
||||
const faviconSvg = await readFile(new URL('../assets/favicon.svg', import.meta.url), 'utf8');
|
||||
|
||||
@@ -79,4 +72,8 @@ async function main() {
|
||||
]);
|
||||
}
|
||||
|
||||
main().then(exit).catch(exit);
|
||||
try {
|
||||
doExit(await main());
|
||||
} catch (err) {
|
||||
doExit(err);
|
||||
}
|
||||
|
||||
+23
-14
@@ -446,23 +446,26 @@ Gitea or set your environment appropriately.`, "")
|
||||
|
||||
func hookPrintResults(results []private.HookPostReceiveBranchResult) {
|
||||
for _, res := range results {
|
||||
if !res.Message {
|
||||
continue
|
||||
}
|
||||
|
||||
fmt.Fprintln(os.Stderr, "")
|
||||
if res.Create {
|
||||
fmt.Fprintf(os.Stderr, "Create a new pull request for '%s':\n", res.Branch)
|
||||
fmt.Fprintf(os.Stderr, " %s\n", res.URL)
|
||||
} else {
|
||||
fmt.Fprint(os.Stderr, "Visit the existing pull request:\n")
|
||||
fmt.Fprintf(os.Stderr, " %s\n", res.URL)
|
||||
}
|
||||
fmt.Fprintln(os.Stderr, "")
|
||||
os.Stderr.Sync()
|
||||
hookPrintResult(res.Message, res.Create, res.Branch, res.URL)
|
||||
}
|
||||
}
|
||||
|
||||
func hookPrintResult(output, isCreate bool, branch, url string) {
|
||||
if !output {
|
||||
return
|
||||
}
|
||||
fmt.Fprintln(os.Stderr, "")
|
||||
if isCreate {
|
||||
fmt.Fprintf(os.Stderr, "Create a new pull request for '%s':\n", branch)
|
||||
fmt.Fprintf(os.Stderr, " %s\n", url)
|
||||
} else {
|
||||
fmt.Fprint(os.Stderr, "Visit the existing pull request:\n")
|
||||
fmt.Fprintf(os.Stderr, " %s\n", url)
|
||||
}
|
||||
fmt.Fprintln(os.Stderr, "")
|
||||
os.Stderr.Sync()
|
||||
}
|
||||
|
||||
func pushOptions() map[string]string {
|
||||
opts := make(map[string]string)
|
||||
if pushCount, err := strconv.Atoi(os.Getenv(private.GitPushOptionCount)); err == nil {
|
||||
@@ -688,6 +691,12 @@ Gitea or set your environment appropriately.`, "")
|
||||
}
|
||||
err = writeFlushPktLine(ctx, os.Stdout)
|
||||
|
||||
if err == nil {
|
||||
for _, res := range resp.Results {
|
||||
hookPrintResult(res.ShouldShowMessage, res.IsCreatePR, res.HeadBranch, res.URL)
|
||||
}
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -1430,7 +1430,7 @@ LEVEL = Info
|
||||
;; Batch size to send for batched queues
|
||||
;BATCH_LENGTH = 20
|
||||
;;
|
||||
;; Connection string for redis queues this will store the redis or redis-cluster connection string.
|
||||
;; Connection string for redis queues this will store the redis (or Redis cluster) connection string.
|
||||
;; When `TYPE` is `persistable-channel`, this provides a directory for the underlying leveldb
|
||||
;; or additional options of the form `leveldb://path/to/db?option=value&....`, and will override `DATADIR`.
|
||||
;CONN_STR = "redis://127.0.0.1:6379/0"
|
||||
@@ -1702,9 +1702,8 @@ LEVEL = Info
|
||||
;; For "memory" only, GC interval in seconds, default is 60
|
||||
;INTERVAL = 60
|
||||
;;
|
||||
;; For "redis", "redis-cluster" and "memcache", connection host address
|
||||
;; redis: `redis://127.0.0.1:6379/0?pool_size=100&idle_timeout=180s`
|
||||
;; redis-cluster: `redis+cluster://127.0.0.1:6379/0?pool_size=100&idle_timeout=180s`
|
||||
;; For "redis" and "memcache", connection host address
|
||||
;; redis: `redis://127.0.0.1:6379/0?pool_size=100&idle_timeout=180s` (or `redis+cluster://127.0.0.1:6379/0?pool_size=100&idle_timeout=180s` for a Redis cluster)
|
||||
;; memcache: `127.0.0.1:11211`
|
||||
;; twoqueue: `{"size":50000,"recent_ratio":0.25,"ghost_ratio":0.5}` or `50000`
|
||||
;HOST =
|
||||
@@ -1736,15 +1735,14 @@ LEVEL = Info
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;
|
||||
;; Either "memory", "file", "redis", "redis-cluster", "db", "mysql", "couchbase", "memcache" or "postgres"
|
||||
;; Either "memory", "file", "redis", "db", "mysql", "couchbase", "memcache" or "postgres"
|
||||
;; Default is "memory". "db" will reuse the configuration in [database]
|
||||
;PROVIDER = memory
|
||||
;;
|
||||
;; Provider config options
|
||||
;; memory: doesn't have any config yet
|
||||
;; file: session file path, e.g. `data/sessions`
|
||||
;; redis: `redis://127.0.0.1:6379/0?pool_size=100&idle_timeout=180s`
|
||||
;; redis-cluster: `redis+cluster://127.0.0.1:6379/0?pool_size=100&idle_timeout=180s`
|
||||
;; redis: `redis://127.0.0.1:6379/0?pool_size=100&idle_timeout=180s` (or `redis+cluster://127.0.0.1:6379/0?pool_size=100&idle_timeout=180s` for a Redis cluster)
|
||||
;; mysql: go-sql-driver/mysql dsn config string, e.g. `root:password@/session_table`
|
||||
;PROVIDER_CONFIG = data/sessions ; Relative paths will be made absolute against _`AppWorkPath`_.
|
||||
;;
|
||||
@@ -2340,22 +2338,6 @@ LEVEL = Info
|
||||
;; Enable issue by repository metrics; default is false
|
||||
;ENABLED_ISSUE_BY_REPOSITORY = false
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;[task]
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;
|
||||
;; Task queue type, could be `channel` or `redis`.
|
||||
;QUEUE_TYPE = channel
|
||||
;;
|
||||
;; Task queue length, available only when `QUEUE_TYPE` is `channel`.
|
||||
;QUEUE_LENGTH = 1000
|
||||
;;
|
||||
;; Task queue connection string, available only when `QUEUE_TYPE` is `redis`.
|
||||
;; If there is a password of redis, use `redis://127.0.0.1:6379/0?pool_size=100&idle_timeout=180s` or `redis+cluster://127.0.0.1:6379/0?pool_size=100&idle_timeout=180s` for `redis-clsuter`.
|
||||
;QUEUE_CONN_STR = "redis://127.0.0.1:6379/0?pool_size=100&idle_timeout=180s"
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;[migrations]
|
||||
|
||||
@@ -487,7 +487,7 @@ Configuration at `[queue]` will set defaults for queues with overrides for indiv
|
||||
- `DATADIR`: **queues/common**: Base DataDir for storing level queues. `DATADIR` for individual queues can be set in `queue.name` sections. Relative paths will be made absolute against `%(APP_DATA_PATH)s`.
|
||||
- `LENGTH`: **100000**: Maximal queue size before channel queues block
|
||||
- `BATCH_LENGTH`: **20**: Batch data before passing to the handler
|
||||
- `CONN_STR`: **redis://127.0.0.1:6379/0**: Connection string for the redis queue type. For `redis-cluster` use `redis+cluster://127.0.0.1:6379/0`. Options can be set using query params. Similarly, LevelDB options can also be set using: **leveldb://relative/path?option=value** or **leveldb:///absolute/path?option=value**, and will override `DATADIR`
|
||||
- `CONN_STR`: **redis://127.0.0.1:6379/0**: Connection string for the redis queue type. If you're running a Redis cluster, use `redis+cluster://127.0.0.1:6379/0`. Options can be set using query params. Similarly, LevelDB options can also be set using: **leveldb://relative/path?option=value** or **leveldb:///absolute/path?option=value**, and will override `DATADIR`
|
||||
- `QUEUE_NAME`: **_queue**: The suffix for default redis and disk queue name. Individual queues will default to **`name`**`QUEUE_NAME` but can be overridden in the specific `queue.name` section.
|
||||
- `SET_NAME`: **_unique**: The suffix that will be added to the default redis and disk queue `set` name for unique queues. Individual queues will default to **`name`**`QUEUE_NAME`_`SET_NAME`_ but can be overridden in the specific `queue.name` section.
|
||||
- `MAX_WORKERS`: **(dynamic)**: Maximum number of worker go-routines for the queue. Default value is "CpuNum/2" clipped to between 1 and 10.
|
||||
@@ -581,7 +581,7 @@ And the following unique queues:
|
||||
|
||||
## OpenID (`openid`)
|
||||
|
||||
- `ENABLE_OPENID_SIGNIN`: **false**: Allow authentication in via OpenID.
|
||||
- `ENABLE_OPENID_SIGNIN`: **true**: Allow authentication in via OpenID.
|
||||
- `ENABLE_OPENID_SIGNUP`: **! DISABLE\_REGISTRATION**: Allow registering via OpenID.
|
||||
- `WHITELISTED_URIS`: **_empty_**: If non-empty, list of POSIX regex patterns matching
|
||||
OpenID URI's to permit.
|
||||
@@ -760,12 +760,11 @@ and
|
||||
|
||||
## Cache (`cache`)
|
||||
|
||||
- `ENABLED`: **true**: Enable the cache.
|
||||
- `ADAPTER`: **memory**: Cache engine adapter, either `memory`, `redis`, `redis-cluster`, `twoqueue` or `memcache`. (`twoqueue` represents a size limited LRU cache.)
|
||||
- `ADAPTER`: **memory**: Cache engine adapter, either `memory`, `redis`, `twoqueue` or `memcache`. (`twoqueue` represents a size limited LRU cache.)
|
||||
- `INTERVAL`: **60**: Garbage Collection interval (sec), for memory and twoqueue cache only.
|
||||
- `HOST`: **_empty_**: Connection string for `redis`, `redis-cluster` and `memcache`. For `twoqueue` sets configuration for the queue.
|
||||
- `HOST`: **_empty_**: Connection string for `redis` and `memcache`. For `twoqueue` sets configuration for the queue.
|
||||
- Redis: `redis://:macaron@127.0.0.1:6379/0?pool_size=100&idle_timeout=180s`
|
||||
- Redis-cluster `redis+cluster://:macaron@127.0.0.1:6379/0?pool_size=100&idle_timeout=180s`
|
||||
- For a Redis cluster: `redis+cluster://:macaron@127.0.0.1:6379/0?pool_size=100&idle_timeout=180s`
|
||||
- Memcache: `127.0.0.1:9090;127.0.0.1:9091`
|
||||
- TwoQueue LRU cache: `{"size":50000,"recent_ratio":0.25,"ghost_ratio":0.5}` or `50000` representing the maximum number of objects stored in the cache.
|
||||
- `ITEM_TTL`: **16h**: Time to keep items in cache if not used, Setting it to -1 disables caching.
|
||||
@@ -778,7 +777,7 @@ and
|
||||
|
||||
## Session (`session`)
|
||||
|
||||
- `PROVIDER`: **memory**: Session engine provider \[memory, file, redis, redis-cluster, db, mysql, couchbase, memcache, postgres\]. Setting `db` will reuse the configuration in `[database]`
|
||||
- `PROVIDER`: **memory**: Session engine provider \[memory, file, redis, db, mysql, couchbase, memcache, postgres\]. Setting `db` will reuse the configuration in `[database]`
|
||||
- `PROVIDER_CONFIG`: **data/sessions**: For file, the root path; for db, empty (database config will be used); for others, the connection string. Relative paths will be made absolute against _`AppWorkPath`_.
|
||||
- `COOKIE_SECURE`:**_empty_**: `true` or `false`. Enable this to force using HTTPS for all session access. If not set, it defaults to `true` if the ROOT_URL is an HTTPS URL.
|
||||
- `COOKIE_NAME`: **i\_like\_gitea**: The name of the cookie used for the session ID.
|
||||
@@ -1182,14 +1181,6 @@ in this mapping or the filetype using heuristics.
|
||||
|
||||
- `DEFAULT_UI_LOCATION`: Default location of time on the UI, so that we can display correct user's time on UI. i.e. Asia/Shanghai
|
||||
|
||||
## Task (`task`)
|
||||
|
||||
Task queue configuration has been moved to `queue.task`. However, the below configuration values are kept for backwards compatibility:
|
||||
|
||||
- `QUEUE_TYPE`: **channel**: Task queue type, could be `channel` or `redis`.
|
||||
- `QUEUE_LENGTH`: **1000**: Task queue length, available only when `QUEUE_TYPE` is `channel`.
|
||||
- `QUEUE_CONN_STR`: **redis://127.0.0.1:6379/0**: Task queue connection string, available only when `QUEUE_TYPE` is `redis`. If redis needs a password, use `redis://123@127.0.0.1:6379/0` or `redis+cluster://123@127.0.0.1:6379/0`.
|
||||
|
||||
## Migrations (`migrations`)
|
||||
|
||||
- `MAX_ATTEMPTS`: **3**: Max attempts per http/https request on migrations.
|
||||
|
||||
@@ -559,7 +559,7 @@ Gitea 创建以下非唯一队列:
|
||||
|
||||
## OpenID (`openid`)
|
||||
|
||||
- `ENABLE_OPENID_SIGNIN`: **false**:允许通过OpenID进行身份验证。
|
||||
- `ENABLE_OPENID_SIGNIN`: **true**:允许通过OpenID进行身份验证。
|
||||
- `ENABLE_OPENID_SIGNUP`: **! DISABLE\_REGISTRATION**:允许通过OpenID进行注册。
|
||||
- `WHITELISTED_URIS`: **_empty_**:如果非空,是一组匹配OpenID URI的POSIX正则表达式模式,用于允许访问。
|
||||
- `BLACKLISTED_URIS`: **_empty_**:如果非空,是一组匹配OpenID URI的POSIX正则表达式模式,用于阻止访问。
|
||||
@@ -1127,15 +1127,6 @@ ALLOW_DATA_URI_IMAGES = true
|
||||
|
||||
- `DEFAULT_UI_LOCATION`:在 UI 上的默认时间位置,以便我们可以在 UI 上显示正确的用户时间。例如:Asia/Shanghai
|
||||
|
||||
## 任务 (`task`)
|
||||
|
||||
任务队列配置已移动到 `queue.task`。然而,以下配置值仍保留以确保向后兼容:
|
||||
|
||||
- `QUEUE_TYPE`:**channel**:任务队列类型,可以是 `channel` 或 `redis`。
|
||||
- `QUEUE_LENGTH`:**1000**:任务队列长度,仅在 `QUEUE_TYPE` 为 `channel` 时可用。
|
||||
- `QUEUE_CONN_STR`:**redis://127.0.0.1:6379/0**:任务队列连接字符串,仅在 `QUEUE_TYPE` 为 `redis` 时可用。
|
||||
如果 redis 需要密码,使用 `redis://123@127.0.0.1:6379/0` 或 `redis+cluster://123@127.0.0.1:6379/0`。
|
||||
|
||||
## 迁移 (`migrations`)
|
||||
|
||||
- `MAX_ATTEMPTS`:**3**:每次 http/https 请求的最大尝试次数(用于迁移)。
|
||||
|
||||
@@ -350,6 +350,8 @@ Match User git
|
||||
AuthorizedKeysCommand /usr/bin/docker exec -i gitea /usr/local/bin/gitea keys -c /etc/gitea/app.ini -e git -u %u -t %t -k %k
|
||||
```
|
||||
|
||||
For this to work, the user `git` has to be allowed to run the `docker` cli command. Please read through the [security considerations](https://docs.docker.com/engine/security/#docker-daemon-attack-surface) of providing non-root linux users access to the docker daemon.
|
||||
|
||||
(From 1.16.0 you will not need to set the `-c /etc/gitea/app.ini` option.)
|
||||
|
||||
All that is left to do is restart the SSH server:
|
||||
|
||||
@@ -545,7 +545,7 @@ In this option, the idea is that the host SSH uses an `AuthorizedKeysCommand` in
|
||||
```bash
|
||||
cat <<"EOF" | sudo tee /home/git/docker-shell
|
||||
#!/bin/sh
|
||||
/usr/bin/docker exec -i --env SSH_ORIGINAL_COMMAND="$SSH_ORIGINAL_COMMAND" gitea sh "$@"
|
||||
/usr/bin/docker exec -i -u git --env SSH_ORIGINAL_COMMAND="$SSH_ORIGINAL_COMMAND" gitea sh "$@"
|
||||
EOF
|
||||
sudo chmod +x /home/git/docker-shell
|
||||
sudo usermod -s /home/git/docker-shell git
|
||||
@@ -560,7 +560,7 @@ Add the following block to `/etc/ssh/sshd_config`, on the host:
|
||||
```bash
|
||||
Match User git
|
||||
AuthorizedKeysCommandUser git
|
||||
AuthorizedKeysCommand /usr/bin/docker exec -i gitea /usr/local/bin/gitea keys -c /data/gitea/conf/app.ini -e git -u %u -t %t -k %k
|
||||
AuthorizedKeysCommand /usr/bin/docker exec -i -u git gitea /usr/local/bin/gitea keys -c /data/gitea/conf/app.ini -e git -u %u -t %t -k %k
|
||||
```
|
||||
|
||||
(From 1.16.0 you will not need to set the `-c /data/gitea/conf/app.ini` option.)
|
||||
|
||||
@@ -301,34 +301,3 @@ sudo systemctl enable act_runner --now
|
||||
```
|
||||
|
||||
If using Docker, the `act_runner` user should also be added to the `docker` group before starting the service. Keep in mind that this effectively gives `act_runner` root access to the system [[1]](https://docs.docker.com/engine/security/#docker-daemon-attack-surface).
|
||||
|
||||
## Configuration variable
|
||||
|
||||
You can create configuration variables on the user, organization and repository level.
|
||||
The level of the variable depends on where you created it.
|
||||
|
||||
### Naming conventions
|
||||
|
||||
The following rules apply to variable names:
|
||||
|
||||
- Variable names can only contain alphanumeric characters (`[a-z]`, `[A-Z]`, `[0-9]`) or underscores (`_`). Spaces are not allowed.
|
||||
|
||||
- Variable names must not start with the `GITHUB_` and `GITEA_` prefix.
|
||||
|
||||
- Variable names must not start with a number.
|
||||
|
||||
- Variable names are case-insensitive.
|
||||
|
||||
- Variable names must be unique at the level they are created at.
|
||||
|
||||
- Variable names must not be `CI`.
|
||||
|
||||
### Using variable
|
||||
|
||||
After creating configuration variables, they will be automatically filled in the `vars` context.
|
||||
They can be accessed through expressions like `{{ vars.VARIABLE_NAME }}` in the workflow.
|
||||
|
||||
### Precedence
|
||||
|
||||
If a variable with the same name exists at multiple levels, the variable at the lowest level takes precedence:
|
||||
A repository variable will always be chosen over an organization/user variable.
|
||||
|
||||
@@ -258,32 +258,3 @@ Runner的标签用于确定Runner可以运行哪些Job以及如何运行它们
|
||||
Runner将从Gitea实例获取Job并自动运行它们。
|
||||
|
||||
由于Act Runner仍处于开发中,建议定期检查最新版本并进行升级。
|
||||
|
||||
## 变量
|
||||
|
||||
您可以创建用户、组织和仓库级别的变量。变量的级别取决于创建它的位置。
|
||||
|
||||
### 命名规则
|
||||
|
||||
以下规则适用于变量名:
|
||||
|
||||
- 变量名称只能包含字母数字字符 (`[a-z]`, `[A-Z]`, `[0-9]`) 或下划线 (`_`)。不允许使用空格。
|
||||
|
||||
- 变量名称不能以 `GITHUB_` 和 `GITEA_` 前缀开头。
|
||||
|
||||
- 变量名称不能以数字开头。
|
||||
|
||||
- 变量名称不区分大小写。
|
||||
|
||||
- 变量名称在创建它们的级别上必须是唯一的。
|
||||
|
||||
- 变量名称不能为 “CI”。
|
||||
|
||||
### 使用
|
||||
|
||||
创建配置变量后,它们将自动填充到 `vars` 上下文中。您可以在工作流中使用类似 `{{ vars.VARIABLE_NAME }}` 这样的表达式来使用它们。
|
||||
|
||||
### 优先级
|
||||
|
||||
如果同名变量存在于多个级别,则级别最低的变量优先。
|
||||
仓库级别的变量总是比组织或者用户级别的变量优先被选中。
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
---
|
||||
date: "2024-04-10T22:21:00+08:00"
|
||||
title: "Variables"
|
||||
slug: "actions-variables"
|
||||
sidebar_position: 25
|
||||
draft: false
|
||||
toc: false
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "actions"
|
||||
name: "Variables"
|
||||
sidebar_position: 25
|
||||
identifier: "actions-variables"
|
||||
---
|
||||
|
||||
## Variables
|
||||
|
||||
You can create configuration variables on the user, organization and repository level.
|
||||
The level of the variable depends on where you created it. When creating a variable, the
|
||||
key will be converted to uppercase. You need use uppercase on the yaml file.
|
||||
|
||||
### Naming conventions
|
||||
|
||||
The following rules apply to variable names:
|
||||
|
||||
- Variable names can only contain alphanumeric characters (`[a-z]`, `[A-Z]`, `[0-9]`) or underscores (`_`). Spaces are not allowed.
|
||||
- Variable names must not start with the `GITHUB_` and `GITEA_` prefix.
|
||||
- Variable names must not start with a number.
|
||||
- Variable names are case-insensitive.
|
||||
- Variable names must be unique at the level they are created at.
|
||||
- Variable names must not be `CI`.
|
||||
|
||||
### Using variable
|
||||
|
||||
After creating configuration variables, they will be automatically filled in the `vars` context.
|
||||
They can be accessed through expressions like `${{ vars.VARIABLE_NAME }}` in the workflow.
|
||||
|
||||
### Precedence
|
||||
|
||||
If a variable with the same name exists at multiple levels, the variable at the lowest level takes precedence:
|
||||
A repository variable will always be chosen over an organization/user variable.
|
||||
@@ -0,0 +1,39 @@
|
||||
---
|
||||
date: "2024-04-10T22:21:00+08:00"
|
||||
title: "变量"
|
||||
slug: "actions-variables"
|
||||
sidebar_position: 25
|
||||
draft: false
|
||||
toc: false
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "actions"
|
||||
name: "变量"
|
||||
sidebar_position: 25
|
||||
identifier: "actions-variables"
|
||||
---
|
||||
|
||||
## 变量
|
||||
|
||||
您可以创建用户、组织和仓库级别的变量。变量的级别取决于创建它的位置。当创建变量时,变量的名称会被
|
||||
转换为大写,在yaml文件中引用时需要使用大写。
|
||||
|
||||
### 命名规则
|
||||
|
||||
以下规则适用于变量名:
|
||||
|
||||
- 变量名称只能包含字母数字字符 (`[a-z]`, `[A-Z]`, `[0-9]`) 或下划线 (`_`)。不允许使用空格。
|
||||
- 变量名称不能以 `GITHUB_` 和 `GITEA_` 前缀开头。
|
||||
- 变量名称不能以数字开头。
|
||||
- 变量名称不区分大小写。
|
||||
- 变量名称在创建它们的级别上必须是唯一的。
|
||||
- 变量名称不能为 `CI`。
|
||||
|
||||
### 使用
|
||||
|
||||
创建配置变量后,它们将自动填充到 `vars` 上下文中。您可以在工作流中使用类似 `${{ vars.VARIABLE_NAME }}` 这样的表达式来使用它们。
|
||||
|
||||
### 优先级
|
||||
|
||||
如果同名变量存在于多个级别,则级别最低的变量优先。
|
||||
仓库级别的变量总是比组织或者用户级别的变量优先被选中。
|
||||
@@ -7,7 +7,7 @@ require (
|
||||
code.gitea.io/gitea-vet v0.2.3
|
||||
code.gitea.io/sdk/gitea v0.16.0
|
||||
codeberg.org/gusted/mcaptcha v0.0.0-20220723083913-4f3072e1d570
|
||||
gitea.com/go-chi/binding v0.0.0-20230415142243-04b515c6d669
|
||||
gitea.com/go-chi/binding v0.0.0-20240430071103-39a851e106ed
|
||||
gitea.com/go-chi/cache v0.2.0
|
||||
gitea.com/go-chi/captcha v0.0.0-20230415143339-2c0754df4384
|
||||
gitea.com/go-chi/session v0.0.0-20230613035928-39541325faa3
|
||||
@@ -15,9 +15,8 @@ require (
|
||||
gitea.com/lunny/levelqueue v0.4.2-0.20230414023320-3c0159fe0fe4
|
||||
github.com/42wim/sshsig v0.0.0-20211121163825-841cf5bbc121
|
||||
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358
|
||||
github.com/NYTimes/gziphandler v1.1.1
|
||||
github.com/PuerkitoBio/goquery v1.8.1
|
||||
github.com/alecthomas/chroma/v2 v2.10.0
|
||||
github.com/alecthomas/chroma/v2 v2.13.0
|
||||
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb
|
||||
github.com/blevesearch/bleve/v2 v2.3.10
|
||||
github.com/bufbuild/connect-go v1.10.0
|
||||
@@ -68,12 +67,12 @@ require (
|
||||
github.com/json-iterator/go v1.1.12
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
|
||||
github.com/keybase/go-crypto v0.0.0-20200123153347-de78d2cb44f4
|
||||
github.com/klauspost/compress v1.17.0
|
||||
github.com/klauspost/compress v1.17.2
|
||||
github.com/klauspost/cpuid/v2 v2.2.5
|
||||
github.com/lib/pq v1.10.9
|
||||
github.com/markbates/goth v1.78.0
|
||||
github.com/mattn/go-isatty v0.0.19
|
||||
github.com/mattn/go-sqlite3 v1.14.17
|
||||
github.com/mattn/go-isatty v0.0.20
|
||||
github.com/mattn/go-sqlite3 v1.14.22
|
||||
github.com/meilisearch/meilisearch-go v0.25.1
|
||||
github.com/mholt/archiver/v3 v3.5.1
|
||||
github.com/microcosm-cc/bluemonday v1.0.26
|
||||
@@ -173,10 +172,10 @@ require (
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/davidmz/go-pageant v1.0.2 // indirect
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||
github.com/dlclark/regexp2 v1.10.0 // indirect
|
||||
github.com/emersion/go-sasl v0.0.0-20220912192320-0145f2c60ead // indirect
|
||||
github.com/fatih/color v1.15.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.3 // indirect
|
||||
github.com/dlclark/regexp2 v1.11.0 // indirect
|
||||
github.com/emersion/go-sasl v0.0.0-20231106173351-e73c9f7bad43 // indirect
|
||||
github.com/fatih/color v1.16.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/fxamacker/cbor/v2 v2.5.0 // indirect
|
||||
github.com/go-ap/errors v0.0.0-20231003111023-183eef4b31b7 // indirect
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.5 // indirect
|
||||
@@ -281,7 +280,7 @@ require (
|
||||
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
|
||||
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
|
||||
github.com/zeebo/blake3 v0.2.3 // indirect
|
||||
go.etcd.io/bbolt v1.3.7 // indirect
|
||||
go.etcd.io/bbolt v1.3.8 // indirect
|
||||
go.mongodb.org/mongo-driver v1.12.1 // indirect
|
||||
go.opentelemetry.io/otel v1.19.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.19.0 // indirect
|
||||
@@ -303,7 +302,7 @@ replace github.com/hashicorp/go-version => github.com/6543/go-version v1.3.1
|
||||
|
||||
replace github.com/shurcooL/vfsgen => github.com/lunny/vfsgen v0.0.0-20220105142115-2c99e1ffdfa0
|
||||
|
||||
replace github.com/nektos/act => gitea.com/gitea/act v0.2.51
|
||||
replace github.com/nektos/act => gitea.com/gitea/act v0.259.1
|
||||
|
||||
exclude github.com/gofrs/uuid v3.2.0+incompatible
|
||||
|
||||
|
||||
@@ -53,10 +53,10 @@ dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
|
||||
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/go.mod h1:g/V2Hjas6Z1UHUp4yIx6bATpNzJ7DYtD0FG3+xARWxs=
|
||||
gitea.com/gitea/act v0.2.51 h1:gXc/B4OlTciTTzAx9cmNyw04n2SDO7exPjAsR5Idu+c=
|
||||
gitea.com/gitea/act v0.2.51/go.mod h1:CoaX2053jqBlD6JMgu4d4UgFL/rp2I14Kt5mMqcs0Z0=
|
||||
gitea.com/go-chi/binding v0.0.0-20230415142243-04b515c6d669 h1:RUBX+MK/TsDxpHmymaOaydfigEbbzqUnG1OTZU/HAeo=
|
||||
gitea.com/go-chi/binding v0.0.0-20230415142243-04b515c6d669/go.mod h1:77TZu701zMXWJFvB8gvTbQ92zQ3DQq/H7l5wAEjQRKc=
|
||||
gitea.com/gitea/act v0.259.1 h1:8GG1o/xtUHl3qjn5f0h/2FXrT5ubBn05TJOM5ry+FBw=
|
||||
gitea.com/gitea/act v0.259.1/go.mod h1:UxZWRYqQG2Yj4+4OqfGWW5a3HELwejyWFQyU7F1jUD8=
|
||||
gitea.com/go-chi/binding v0.0.0-20240430071103-39a851e106ed h1:EZZBtilMLSZNWtHHcgq2mt6NSGhJSZBuduAlinMEmso=
|
||||
gitea.com/go-chi/binding v0.0.0-20240430071103-39a851e106ed/go.mod h1:E3i3cgB04dDx0v3CytCgRTTn9Z/9x891aet3r456RVw=
|
||||
gitea.com/go-chi/cache v0.0.0-20210110083709-82c4c9ce2d5e/go.mod h1:k2V/gPDEtXGjjMGuBJiapffAXTv76H4snSmlJRLUhH0=
|
||||
gitea.com/go-chi/cache v0.2.0 h1:E0npuTfDW6CT1yD8NMDVc1SK6IeRjfmRL2zlEsCEd7w=
|
||||
gitea.com/go-chi/cache v0.2.0/go.mod h1:iQlVK2aKTZ/rE9UcHyz9pQWGvdP9i1eI2spOpzgCrtE=
|
||||
@@ -99,8 +99,6 @@ github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBa
|
||||
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
|
||||
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
|
||||
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
|
||||
github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I=
|
||||
github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c=
|
||||
github.com/ProtonMail/go-crypto v1.0.0 h1:LRuvITjQWX+WIfr930YHG2HNfjR1uOfyf5vE0kC2U78=
|
||||
github.com/ProtonMail/go-crypto v1.0.0/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
|
||||
github.com/PuerkitoBio/goquery v1.8.1 h1:uQxhNlArOIdbrH1tr0UXwdVFgDcZDrZVdcpygAcwmWM=
|
||||
@@ -111,14 +109,14 @@ github.com/RoaringBitmap/roaring v0.4.23/go.mod h1:D0gp8kJQgE1A4LQ5wFLggQEyvDi06
|
||||
github.com/RoaringBitmap/roaring v0.7.1/go.mod h1:jdT9ykXwHFNdJbEtxePexlFYH9LXucApeS0/+/g+p1I=
|
||||
github.com/RoaringBitmap/roaring v1.6.0 h1:dc7kRiroETgJcHhWX6BerXkZz2b3JgLGg9nTURJL/og=
|
||||
github.com/RoaringBitmap/roaring v1.6.0/go.mod h1:plvDsJQpxOC5bw8LRteu/MLWHsHez/3y6cubLI4/1yE=
|
||||
github.com/alecthomas/assert/v2 v2.2.1 h1:XivOgYcduV98QCahG8T5XTezV5bylXe+lBxLG2K2ink=
|
||||
github.com/alecthomas/assert/v2 v2.2.1/go.mod h1:pXcQ2Asjp247dahGEmsZ6ru0UVwnkhktn7S0bBDLxvQ=
|
||||
github.com/alecthomas/assert/v2 v2.6.0 h1:o3WJwILtexrEUk3cUVal3oiQY2tfgr/FHWiz/v2n4FU=
|
||||
github.com/alecthomas/assert/v2 v2.6.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
|
||||
github.com/alecthomas/chroma/v2 v2.2.0/go.mod h1:vf4zrexSH54oEjJ7EdB65tGNHmH3pGZmVkgTP5RHvAs=
|
||||
github.com/alecthomas/chroma/v2 v2.10.0 h1:T2iQOCCt4pRmRMfL55gTodMtc7cU0y7lc1Jb8/mK/64=
|
||||
github.com/alecthomas/chroma/v2 v2.10.0/go.mod h1:4TQu7gdfuPjSh76j78ietmqh9LiurGF0EpseFXdKMBw=
|
||||
github.com/alecthomas/chroma/v2 v2.13.0 h1:VP72+99Fb2zEcYM0MeaWJmV+xQvz5v5cxRHd+ooU1lI=
|
||||
github.com/alecthomas/chroma/v2 v2.13.0/go.mod h1:BUGjjsD+ndS6eX37YgTchSEG+Jg9Jv1GiZs9sqPqztk=
|
||||
github.com/alecthomas/repr v0.0.0-20220113201626-b1b626ac65ae/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8=
|
||||
github.com/alecthomas/repr v0.2.0 h1:HAzS41CIzNW5syS8Mf9UwXhNH1J9aix/BvDRf1Ml2Yk=
|
||||
github.com/alecthomas/repr v0.2.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
|
||||
github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc=
|
||||
github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
|
||||
github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74 h1:Kk6a4nehpJ3UuJRqlA3JxYxBZEqCeOmATOvrbT4p9RA=
|
||||
github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4=
|
||||
github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
|
||||
@@ -269,8 +267,8 @@ github.com/djherbis/nio/v3 v3.0.1/go.mod h1:Ng4h80pbZFMla1yKzm61cF0tqqilXZYrogmW
|
||||
github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
|
||||
github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
|
||||
github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
||||
github.com/dlclark/regexp2 v1.10.0 h1:+/GIL799phkJqYW+3YbOd8LCcbHzT0Pbo8zl70MHsq0=
|
||||
github.com/dlclark/regexp2 v1.10.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
||||
github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI=
|
||||
github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
||||
github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ=
|
||||
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 h1:iFaUwBSo5Svw6L7HYpRu/0lE3e0BaElwnNO1qkNQxBY=
|
||||
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5/go.mod h1:qssHWj60/X5sZFNxpG4HBPDHVqxNm4DfnCKgrbZOT+s=
|
||||
@@ -288,8 +286,8 @@ github.com/emersion/go-imap v1.2.1 h1:+s9ZjMEjOB8NzZMVTM3cCenz2JrQIGGo5j1df19WjT
|
||||
github.com/emersion/go-imap v1.2.1/go.mod h1:Qlx1FSx2FTxjnjWpIlVNEuX+ylerZQNFE5NsmKFSejY=
|
||||
github.com/emersion/go-message v0.15.0/go.mod h1:wQUEfE+38+7EW8p8aZ96ptg6bAb1iwdgej19uXASlE4=
|
||||
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ=
|
||||
github.com/emersion/go-sasl v0.0.0-20220912192320-0145f2c60ead h1:fI1Jck0vUrXT8bnphprS1EoVRe2Q5CKCX8iDlpqjQ/Y=
|
||||
github.com/emersion/go-sasl v0.0.0-20220912192320-0145f2c60ead/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ=
|
||||
github.com/emersion/go-sasl v0.0.0-20231106173351-e73c9f7bad43 h1:hH4PQfOndHDlpzYfLAAfl63E8Le6F2+EL/cdhlkyRJY=
|
||||
github.com/emersion/go-sasl v0.0.0-20231106173351-e73c9f7bad43/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ=
|
||||
github.com/emersion/go-textwrapper v0.0.0-20200911093747-65d896831594/go.mod h1:aqO8z8wPrjkscevZJFVE1wXJrLpC5LtJG7fqLOsPb2U=
|
||||
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
|
||||
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
|
||||
@@ -301,13 +299,13 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.m
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/ethantkoenig/rupture v1.0.1 h1:6aAXghmvtnngMgQzy7SMGdicMvkV86V4n9fT0meE5E4=
|
||||
github.com/ethantkoenig/rupture v1.0.1/go.mod h1:Sjqo/nbffZp1pVVXNGhpugIjsWmuS9KiIB4GtpEBur4=
|
||||
github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
|
||||
github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
|
||||
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
|
||||
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
|
||||
github.com/felixge/fgprof v0.9.3 h1:VvyZxILNuCiUCSXtPtYmmtGvb65nqXh2QFWc0Wpf2/g=
|
||||
github.com/felixge/fgprof v0.9.3/go.mod h1:RdbpDgzqYVh/T9fPELJyV7EYJuHB55UTEULNun8eiPw=
|
||||
github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk=
|
||||
github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=
|
||||
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
|
||||
github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY=
|
||||
@@ -448,7 +446,6 @@ github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/V
|
||||
github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw=
|
||||
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
|
||||
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
|
||||
github.com/goccy/go-json v0.9.5/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/goccy/go-json v0.9.6/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
||||
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
@@ -654,8 +651,8 @@ github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYs
|
||||
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||
github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||
github.com/klauspost/compress v1.15.6/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
|
||||
github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM=
|
||||
github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
||||
github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4=
|
||||
github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
||||
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||
github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c=
|
||||
@@ -710,14 +707,14 @@ github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kN
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
|
||||
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
|
||||
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||
github.com/mattn/go-sqlite3 v1.14.17 h1:mCRHCLDUBXgpKAqIKsaAaAsrAlbkeomtRFKXh2L6YIM=
|
||||
github.com/mattn/go-sqlite3 v1.14.17/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
||||
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
|
||||
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
|
||||
github.com/meilisearch/meilisearch-go v0.25.1 h1:D5wY22sn5kkpRH3uYMGlwltdUEq5regIFmO7awHz3Vo=
|
||||
@@ -1010,8 +1007,8 @@ github.com/zeebo/blake3 v0.2.3/go.mod h1:mjJjZpnsyIVtVgTOSpJ9vmRE4wgDeyt2HU3qXvv
|
||||
github.com/zeebo/pcg v1.0.1 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo=
|
||||
github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4=
|
||||
go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
|
||||
go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ=
|
||||
go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw=
|
||||
go.etcd.io/bbolt v1.3.8 h1:xs88BrvEv273UsB79e0hcVrlUWmS0a8upikMFhSyAtA=
|
||||
go.etcd.io/bbolt v1.3.8/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw=
|
||||
go.mongodb.org/mongo-driver v1.7.3/go.mod h1:NqaYOwnXWr5Pm7AOpO5QFxKJ503nbMse/R79oO62zWg=
|
||||
go.mongodb.org/mongo-driver v1.7.5/go.mod h1:VXEWRZ6URJIkUq2SCAyapmhH0ZLRBP+FT4xhp5Zvxng=
|
||||
go.mongodb.org/mongo-driver v1.10.0/go.mod h1:wsihk0Kdgv8Kqu1Anit4sfK+22vSFbUrAVEYRhCXrA8=
|
||||
|
||||
+16
-6
@@ -95,13 +95,10 @@ func (run *ActionRun) LoadAttributes(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
if run.Repo == nil {
|
||||
repo, err := repo_model.GetRepositoryByID(ctx, run.RepoID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
run.Repo = repo
|
||||
if err := run.LoadRepo(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := run.Repo.LoadAttributes(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -117,6 +114,19 @@ func (run *ActionRun) LoadAttributes(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (run *ActionRun) LoadRepo(ctx context.Context) error {
|
||||
if run == nil || run.Repo != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
repo, err := repo_model.GetRepositoryByID(ctx, run.RepoID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
run.Repo = repo
|
||||
return nil
|
||||
}
|
||||
|
||||
func (run *ActionRun) Duration() time.Duration {
|
||||
return calculateDuration(run.Started, run.Stopped, run.Status)
|
||||
}
|
||||
|
||||
@@ -284,7 +284,7 @@ func CountRunnersWithoutBelongingOwner(ctx context.Context) (int64, error) {
|
||||
// Only affect action runners were a owner ID is set, as actions runners
|
||||
// could also be created on a repository.
|
||||
return db.GetEngine(ctx).Table("action_runner").
|
||||
Join("LEFT", "user", "`action_runner`.owner_id = `user`.id").
|
||||
Join("LEFT", "`user`", "`action_runner`.owner_id = `user`.id").
|
||||
Where("`action_runner`.owner_id != ?", 0).
|
||||
And(builder.IsNull{"`user`.id"}).
|
||||
Count(new(ActionRunner))
|
||||
@@ -293,7 +293,7 @@ func CountRunnersWithoutBelongingOwner(ctx context.Context) (int64, error) {
|
||||
func FixRunnersWithoutBelongingOwner(ctx context.Context) (int64, error) {
|
||||
subQuery := builder.Select("`action_runner`.id").
|
||||
From("`action_runner`").
|
||||
Join("LEFT", "user", "`action_runner`.owner_id = `user`.id").
|
||||
Join("LEFT", "`user`", "`action_runner`.owner_id = `user`.id").
|
||||
Where(builder.Neq{"`action_runner`.owner_id": 0}).
|
||||
And(builder.IsNull{"`user`.id"})
|
||||
b := builder.Delete(builder.In("id", subQuery)).From("`action_runner`")
|
||||
@@ -303,3 +303,25 @@ func FixRunnersWithoutBelongingOwner(ctx context.Context) (int64, error) {
|
||||
}
|
||||
return res.RowsAffected()
|
||||
}
|
||||
|
||||
func CountRunnersWithoutBelongingRepo(ctx context.Context) (int64, error) {
|
||||
return db.GetEngine(ctx).Table("action_runner").
|
||||
Join("LEFT", "`repository`", "`action_runner`.repo_id = `repository`.id").
|
||||
Where("`action_runner`.repo_id != ?", 0).
|
||||
And(builder.IsNull{"`repository`.id"}).
|
||||
Count(new(ActionRunner))
|
||||
}
|
||||
|
||||
func FixRunnersWithoutBelongingRepo(ctx context.Context) (int64, error) {
|
||||
subQuery := builder.Select("`action_runner`.id").
|
||||
From("`action_runner`").
|
||||
Join("LEFT", "`repository`", "`action_runner`.repo_id = `repository`.id").
|
||||
Where(builder.Neq{"`action_runner`.repo_id": 0}).
|
||||
And(builder.IsNull{"`repository`.id"})
|
||||
b := builder.Delete(builder.In("id", subQuery)).From("`action_runner`")
|
||||
res, err := db.GetEngine(ctx).Exec(b)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return res.RowsAffected()
|
||||
}
|
||||
|
||||
@@ -44,6 +44,9 @@ func (schedules ScheduleList) LoadTriggerUser(ctx context.Context) error {
|
||||
schedule.TriggerUser = user_model.NewActionsUser()
|
||||
} else {
|
||||
schedule.TriggerUser = users[schedule.TriggerUserID]
|
||||
if schedule.TriggerUser == nil {
|
||||
schedule.TriggerUser = user_model.NewGhostUser()
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/timeutil"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
|
||||
@@ -95,3 +96,33 @@ func UpdateVariable(ctx context.Context, variable *ActionVariable) (bool, error)
|
||||
})
|
||||
return count != 0, err
|
||||
}
|
||||
|
||||
func GetVariablesOfRun(ctx context.Context, run *ActionRun) (map[string]string, error) {
|
||||
variables := map[string]string{}
|
||||
|
||||
if err := run.LoadRepo(ctx); err != nil {
|
||||
log.Error("LoadRepo: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Org / User level
|
||||
ownerVariables, err := FindVariables(ctx, FindVariablesOpts{OwnerID: run.Repo.OwnerID})
|
||||
if err != nil {
|
||||
log.Error("find variables of org: %d, error: %v", run.Repo.OwnerID, err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Repo level
|
||||
repoVariables, err := FindVariables(ctx, FindVariablesOpts{RepoID: run.RepoID})
|
||||
if err != nil {
|
||||
log.Error("find variables of repo: %d, error: %v", run.RepoID, err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Level precedence: Repo > Org / User
|
||||
for _, v := range append(ownerVariables, repoVariables...) {
|
||||
variables[v.Name] = v.Data
|
||||
}
|
||||
|
||||
return variables, nil
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import (
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/timeutil"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
|
||||
"xorm.io/builder"
|
||||
"xorm.io/xorm"
|
||||
@@ -821,3 +822,31 @@ func UpdateNotificationStatuses(ctx context.Context, user *user_model.User, curr
|
||||
Update(n)
|
||||
return err
|
||||
}
|
||||
|
||||
// LoadIssuePullRequests loads all issues' pull requests if possible
|
||||
func (nl NotificationList) LoadIssuePullRequests(ctx context.Context) error {
|
||||
issues := make(map[int64]*issues_model.Issue, len(nl))
|
||||
for _, notification := range nl {
|
||||
if notification.Issue != nil && notification.Issue.IsPull && notification.Issue.PullRequest == nil {
|
||||
issues[notification.Issue.ID] = notification.Issue
|
||||
}
|
||||
}
|
||||
|
||||
if len(issues) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
pulls, err := issues_model.GetPullRequestByIssueIDs(ctx, util.KeysOfMap(issues))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, pull := range pulls {
|
||||
if issue := issues[pull.IssueID]; issue != nil {
|
||||
issue.PullRequest = pull
|
||||
issue.PullRequest.Issue = issue
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -139,13 +139,7 @@ func ParseCommitWithSignature(ctx context.Context, c *git.Commit) *CommitVerific
|
||||
}
|
||||
}
|
||||
|
||||
keyID := ""
|
||||
if sig.IssuerKeyId != nil && (*sig.IssuerKeyId) != 0 {
|
||||
keyID = fmt.Sprintf("%X", *sig.IssuerKeyId)
|
||||
}
|
||||
if keyID == "" && sig.IssuerFingerprint != nil && len(sig.IssuerFingerprint) > 0 {
|
||||
keyID = fmt.Sprintf("%X", sig.IssuerFingerprint[12:20])
|
||||
}
|
||||
keyID := tryGetKeyIDFromSignature(sig)
|
||||
defaultReason := NoKeyFound
|
||||
|
||||
// First check if the sig has a keyID and if so just look at that
|
||||
|
||||
@@ -134,3 +134,13 @@ func extractSignature(s string) (*packet.Signature, error) {
|
||||
}
|
||||
return sig, nil
|
||||
}
|
||||
|
||||
func tryGetKeyIDFromSignature(sig *packet.Signature) string {
|
||||
if sig.IssuerKeyId != nil && (*sig.IssuerKeyId) != 0 {
|
||||
return fmt.Sprintf("%016X", *sig.IssuerKeyId)
|
||||
}
|
||||
if sig.IssuerFingerprint != nil && len(sig.IssuerFingerprint) > 0 {
|
||||
return fmt.Sprintf("%016X", sig.IssuerFingerprint[12:20])
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
@@ -11,7 +11,9 @@ import (
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/timeutil"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
|
||||
"github.com/keybase/go-crypto/openpgp/packet"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
@@ -391,3 +393,13 @@ epiDVQ==
|
||||
assert.Equal(t, time.Unix(1586105389, 0), expire)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTryGetKeyIDFromSignature(t *testing.T) {
|
||||
assert.Empty(t, tryGetKeyIDFromSignature(&packet.Signature{}))
|
||||
assert.Equal(t, "038D1A3EADDBEA9C", tryGetKeyIDFromSignature(&packet.Signature{
|
||||
IssuerKeyId: util.ToPointer(uint64(0x38D1A3EADDBEA9C)),
|
||||
}))
|
||||
assert.Equal(t, "038D1A3EADDBEA9C", tryGetKeyIDFromSignature(&packet.Signature{
|
||||
IssuerFingerprint: []uint8{0xb, 0x23, 0x24, 0xc7, 0xe6, 0xfe, 0x4f, 0x3a, 0x6, 0x26, 0xc1, 0x21, 0x3, 0x8d, 0x1a, 0x3e, 0xad, 0xdb, 0xea, 0x9c},
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -13,8 +13,6 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
//////////////////// Application
|
||||
|
||||
func TestOAuth2Application_GenerateClientSecret(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
app := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{ID: 1})
|
||||
|
||||
@@ -120,6 +120,16 @@ func (c *halfCommitter) Close() error {
|
||||
|
||||
// TxContext represents a transaction Context,
|
||||
// it will reuse the existing transaction in the parent context or create a new one.
|
||||
// Some tips to use:
|
||||
//
|
||||
// 1 It's always recommended to use `WithTx` in new code instead of `TxContext`, since `WithTx` will handle the transaction automatically.
|
||||
// 2. To maintain the old code which uses `TxContext`:
|
||||
// a. Always call `Close()` before returning regardless of whether `Commit()` has been called.
|
||||
// b. Always call `Commit()` before returning if there are no errors, even if the code did not change any data.
|
||||
// c. Remember the `Committer` will be a halfCommitter when a transaction is being reused.
|
||||
// So calling `Commit()` will do nothing, but calling `Close()` without calling `Commit()` will rollback the transaction.
|
||||
// And all operations submitted by the caller stack will be rollbacked as well, not only the operations in the current function.
|
||||
// d. It doesn't mean rollback is forbidden, but always do it only when there is an error, and you do want to rollback.
|
||||
func TxContext(parentCtx context.Context) (*Context, Committer, error) {
|
||||
if sess, ok := inTransaction(parentCtx); ok {
|
||||
return newContext(parentCtx, sess, true), &halfCommitter{committer: sess}, nil
|
||||
|
||||
@@ -75,3 +75,11 @@
|
||||
content: "comment in private pository"
|
||||
created_unix: 946684811
|
||||
updated_unix: 946684811
|
||||
|
||||
-
|
||||
id: 9
|
||||
type: 22 # review
|
||||
poster_id: 2
|
||||
issue_id: 2 # in repo_id 1
|
||||
review_id: 20
|
||||
created_unix: 946684810
|
||||
|
||||
@@ -170,3 +170,12 @@
|
||||
content: "review request for user15"
|
||||
updated_unix: 946684835
|
||||
created_unix: 946684835
|
||||
|
||||
-
|
||||
id: 20
|
||||
type: 22
|
||||
reviewer_id: 1
|
||||
issue_id: 2
|
||||
content: "Review Comment"
|
||||
updated_unix: 946684810
|
||||
created_unix: 946684810
|
||||
|
||||
+25
-6
@@ -292,6 +292,7 @@ func RenameBranch(ctx context.Context, repo *repo_model.Repository, from, to str
|
||||
|
||||
sess := db.GetEngine(ctx)
|
||||
|
||||
// check whether from branch exist
|
||||
var branch Branch
|
||||
exist, err := db.GetEngine(ctx).Where("repo_id=? AND name=?", repo.ID, from).Get(&branch)
|
||||
if err != nil {
|
||||
@@ -303,6 +304,24 @@ func RenameBranch(ctx context.Context, repo *repo_model.Repository, from, to str
|
||||
}
|
||||
}
|
||||
|
||||
// check whether to branch exist or is_deleted
|
||||
var dstBranch Branch
|
||||
exist, err = db.GetEngine(ctx).Where("repo_id=? AND name=?", repo.ID, to).Get(&dstBranch)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if exist {
|
||||
if !dstBranch.IsDeleted {
|
||||
return ErrBranchAlreadyExists{
|
||||
BranchName: to,
|
||||
}
|
||||
}
|
||||
|
||||
if _, err := db.GetEngine(ctx).ID(dstBranch.ID).NoAutoCondition().Delete(&dstBranch); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// 1. update branch in database
|
||||
if n, err := sess.Where("repo_id=? AND name=?", repo.ID, from).Update(&Branch{
|
||||
Name: to,
|
||||
@@ -357,12 +376,7 @@ func RenameBranch(ctx context.Context, repo *repo_model.Repository, from, to str
|
||||
return err
|
||||
}
|
||||
|
||||
// 5. do git action
|
||||
if err = gitAction(ctx, isDefault); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 6. insert renamed branch record
|
||||
// 5. insert renamed branch record
|
||||
renamedBranch := &RenamedBranch{
|
||||
RepoID: repo.ID,
|
||||
From: from,
|
||||
@@ -373,6 +387,11 @@ func RenameBranch(ctx context.Context, repo *repo_model.Repository, from, to str
|
||||
return err
|
||||
}
|
||||
|
||||
// 6. do git action
|
||||
if err = gitAction(ctx, isDefault); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return committer.Commit()
|
||||
}
|
||||
|
||||
|
||||
+54
-48
@@ -25,6 +25,7 @@ import (
|
||||
"code.gitea.io/gitea/modules/translation"
|
||||
|
||||
"xorm.io/builder"
|
||||
"xorm.io/xorm"
|
||||
)
|
||||
|
||||
// CommitStatus holds a single Status of a single Commit
|
||||
@@ -281,44 +282,48 @@ type CommitStatusIndex struct {
|
||||
|
||||
// GetLatestCommitStatus returns all statuses with a unique context for a given commit.
|
||||
func GetLatestCommitStatus(ctx context.Context, repoID int64, sha string, listOptions db.ListOptions) ([]*CommitStatus, int64, error) {
|
||||
ids := make([]int64, 0, 10)
|
||||
sess := db.GetEngine(ctx).Table(&CommitStatus{}).
|
||||
Where("repo_id = ?", repoID).And("sha = ?", sha).
|
||||
Select("max( id ) as id").
|
||||
GroupBy("context_hash").OrderBy("max( id ) desc")
|
||||
getBase := func() *xorm.Session {
|
||||
return db.GetEngine(ctx).Table(&CommitStatus{}).
|
||||
Where("repo_id = ?", repoID).And("sha = ?", sha)
|
||||
}
|
||||
indices := make([]int64, 0, 10)
|
||||
sess := getBase().Select("max( `index` ) as `index`").
|
||||
GroupBy("context_hash").OrderBy("max( `index` ) desc")
|
||||
if !listOptions.IsListAll() {
|
||||
sess = db.SetSessionPagination(sess, &listOptions)
|
||||
}
|
||||
count, err := sess.FindAndCount(&ids)
|
||||
count, err := sess.FindAndCount(&indices)
|
||||
if err != nil {
|
||||
return nil, count, err
|
||||
}
|
||||
statuses := make([]*CommitStatus, 0, len(ids))
|
||||
if len(ids) == 0 {
|
||||
statuses := make([]*CommitStatus, 0, len(indices))
|
||||
if len(indices) == 0 {
|
||||
return statuses, count, nil
|
||||
}
|
||||
return statuses, count, db.GetEngine(ctx).In("id", ids).Find(&statuses)
|
||||
return statuses, count, getBase().And(builder.In("`index`", indices)).Find(&statuses)
|
||||
}
|
||||
|
||||
// GetLatestCommitStatusForPairs returns all statuses with a unique context for a given list of repo-sha pairs
|
||||
func GetLatestCommitStatusForPairs(ctx context.Context, repoIDsToLatestCommitSHAs map[int64]string, listOptions db.ListOptions) (map[int64][]*CommitStatus, error) {
|
||||
type result struct {
|
||||
ID int64
|
||||
Index int64
|
||||
RepoID int64
|
||||
}
|
||||
|
||||
results := make([]result, 0, len(repoIDsToLatestCommitSHAs))
|
||||
|
||||
sess := db.GetEngine(ctx).Table(&CommitStatus{})
|
||||
getBase := func() *xorm.Session {
|
||||
return db.GetEngine(ctx).Table(&CommitStatus{})
|
||||
}
|
||||
|
||||
// Create a disjunction of conditions for each repoID and SHA pair
|
||||
conds := make([]builder.Cond, 0, len(repoIDsToLatestCommitSHAs))
|
||||
for repoID, sha := range repoIDsToLatestCommitSHAs {
|
||||
conds = append(conds, builder.Eq{"repo_id": repoID, "sha": sha})
|
||||
}
|
||||
sess = sess.Where(builder.Or(conds...)).
|
||||
Select("max( id ) as id, repo_id").
|
||||
GroupBy("context_hash, repo_id").OrderBy("max( id ) desc")
|
||||
sess := getBase().Where(builder.Or(conds...)).
|
||||
Select("max( `index` ) as `index`, repo_id").
|
||||
GroupBy("context_hash, repo_id").OrderBy("max( `index` ) desc")
|
||||
|
||||
sess = db.SetSessionPagination(sess, &listOptions)
|
||||
|
||||
@@ -327,15 +332,21 @@ func GetLatestCommitStatusForPairs(ctx context.Context, repoIDsToLatestCommitSHA
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ids := make([]int64, 0, len(results))
|
||||
repoStatuses := make(map[int64][]*CommitStatus)
|
||||
for _, result := range results {
|
||||
ids = append(ids, result.ID)
|
||||
}
|
||||
|
||||
statuses := make([]*CommitStatus, 0, len(ids))
|
||||
if len(ids) > 0 {
|
||||
err = db.GetEngine(ctx).In("id", ids).Find(&statuses)
|
||||
if len(results) > 0 {
|
||||
statuses := make([]*CommitStatus, 0, len(results))
|
||||
|
||||
conds = make([]builder.Cond, 0, len(results))
|
||||
for _, result := range results {
|
||||
cond := builder.Eq{
|
||||
"`index`": result.Index,
|
||||
"repo_id": result.RepoID,
|
||||
"sha": repoIDsToLatestCommitSHAs[result.RepoID],
|
||||
}
|
||||
conds = append(conds, cond)
|
||||
}
|
||||
err = getBase().Where(builder.Or(conds...)).Find(&statuses)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -352,42 +363,43 @@ func GetLatestCommitStatusForPairs(ctx context.Context, repoIDsToLatestCommitSHA
|
||||
// GetLatestCommitStatusForRepoCommitIDs returns all statuses with a unique context for a given list of repo-sha pairs
|
||||
func GetLatestCommitStatusForRepoCommitIDs(ctx context.Context, repoID int64, commitIDs []string) (map[string][]*CommitStatus, error) {
|
||||
type result struct {
|
||||
ID int64
|
||||
Sha string
|
||||
Index int64
|
||||
SHA string
|
||||
}
|
||||
|
||||
getBase := func() *xorm.Session {
|
||||
return db.GetEngine(ctx).Table(&CommitStatus{}).Where("repo_id = ?", repoID)
|
||||
}
|
||||
results := make([]result, 0, len(commitIDs))
|
||||
|
||||
sess := db.GetEngine(ctx).Table(&CommitStatus{})
|
||||
|
||||
// Create a disjunction of conditions for each repoID and SHA pair
|
||||
conds := make([]builder.Cond, 0, len(commitIDs))
|
||||
for _, sha := range commitIDs {
|
||||
conds = append(conds, builder.Eq{"sha": sha})
|
||||
}
|
||||
sess = sess.Where(builder.Eq{"repo_id": repoID}.And(builder.Or(conds...))).
|
||||
Select("max( id ) as id, sha").
|
||||
GroupBy("context_hash, sha").OrderBy("max( id ) desc")
|
||||
sess := getBase().And(builder.Or(conds...)).
|
||||
Select("max( `index` ) as `index`, sha").
|
||||
GroupBy("context_hash, sha").OrderBy("max( `index` ) desc")
|
||||
|
||||
err := sess.Find(&results)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ids := make([]int64, 0, len(results))
|
||||
repoStatuses := make(map[string][]*CommitStatus)
|
||||
for _, result := range results {
|
||||
ids = append(ids, result.ID)
|
||||
}
|
||||
|
||||
statuses := make([]*CommitStatus, 0, len(ids))
|
||||
if len(ids) > 0 {
|
||||
err = db.GetEngine(ctx).In("id", ids).Find(&statuses)
|
||||
if len(results) > 0 {
|
||||
statuses := make([]*CommitStatus, 0, len(results))
|
||||
|
||||
conds = make([]builder.Cond, 0, len(results))
|
||||
for _, result := range results {
|
||||
conds = append(conds, builder.Eq{"`index`": result.Index, "sha": result.SHA})
|
||||
}
|
||||
err = getBase().And(builder.Or(conds...)).Find(&statuses)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Group the statuses by repo ID
|
||||
// Group the statuses by commit
|
||||
for _, status := range statuses {
|
||||
repoStatuses[status.SHA] = append(repoStatuses[status.SHA], status)
|
||||
}
|
||||
@@ -399,21 +411,15 @@ func GetLatestCommitStatusForRepoCommitIDs(ctx context.Context, repoID int64, co
|
||||
// FindRepoRecentCommitStatusContexts returns repository's recent commit status contexts
|
||||
func FindRepoRecentCommitStatusContexts(ctx context.Context, repoID int64, before time.Duration) ([]string, error) {
|
||||
start := timeutil.TimeStampNow().AddDuration(-before)
|
||||
ids := make([]int64, 0, 10)
|
||||
|
||||
var contexts []string
|
||||
if err := db.GetEngine(ctx).Table("commit_status").
|
||||
Where("repo_id = ?", repoID).
|
||||
And("updated_unix >= ?", start).
|
||||
Select("max( id ) as id").
|
||||
GroupBy("context_hash").OrderBy("max( id ) desc").
|
||||
Find(&ids); err != nil {
|
||||
Where("repo_id = ?", repoID).And("updated_unix >= ?", start).
|
||||
Cols("context").Distinct().Find(&contexts); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
contexts := make([]string, 0, len(ids))
|
||||
if len(ids) == 0 {
|
||||
return contexts, nil
|
||||
}
|
||||
return contexts, db.GetEngine(ctx).Select("context").Table("commit_status").In("id", ids).Find(&contexts)
|
||||
return contexts, nil
|
||||
}
|
||||
|
||||
// NewCommitStatusOptions holds options for creating a CommitStatus
|
||||
|
||||
@@ -5,11 +5,14 @@ package git_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
git_model "code.gitea.io/gitea/models/git"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/structs"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
@@ -60,3 +63,55 @@ func TestGetCommitStatuses(t *testing.T) {
|
||||
assert.Equal(t, int(maxResults), 5)
|
||||
assert.Empty(t, statuses)
|
||||
}
|
||||
|
||||
func TestFindRepoRecentCommitStatusContexts(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
|
||||
repo2 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2})
|
||||
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||
gitRepo, err := git.OpenRepository(git.DefaultContext, repo2.RepoPath())
|
||||
assert.NoError(t, err)
|
||||
defer gitRepo.Close()
|
||||
|
||||
commit, err := gitRepo.GetBranchCommit(repo2.DefaultBranch)
|
||||
assert.NoError(t, err)
|
||||
|
||||
defer func() {
|
||||
_, err := db.DeleteByBean(db.DefaultContext, &git_model.CommitStatus{
|
||||
RepoID: repo2.ID,
|
||||
CreatorID: user2.ID,
|
||||
SHA: commit.ID.String(),
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
}()
|
||||
|
||||
err = git_model.NewCommitStatus(db.DefaultContext, git_model.NewCommitStatusOptions{
|
||||
Repo: repo2,
|
||||
Creator: user2,
|
||||
SHA: commit.ID.String(),
|
||||
CommitStatus: &git_model.CommitStatus{
|
||||
State: structs.CommitStatusFailure,
|
||||
TargetURL: "https://example.com/tests/",
|
||||
Context: "compliance/lint-backend",
|
||||
},
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = git_model.NewCommitStatus(db.DefaultContext, git_model.NewCommitStatusOptions{
|
||||
Repo: repo2,
|
||||
Creator: user2,
|
||||
SHA: commit.ID.String(),
|
||||
CommitStatus: &git_model.CommitStatus{
|
||||
State: structs.CommitStatusSuccess,
|
||||
TargetURL: "https://example.com/tests/",
|
||||
Context: "compliance/lint-backend",
|
||||
},
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
|
||||
contexts, err := git_model.FindRepoRecentCommitStatusContexts(db.DefaultContext, repo2.ID, time.Hour)
|
||||
assert.NoError(t, err)
|
||||
if assert.Len(t, contexts, 1) {
|
||||
assert.Equal(t, "compliance/lint-backend", contexts[0])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,6 +74,10 @@ func findCodeComments(ctx context.Context, opts FindCommentsOptions, issue *Issu
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := comments.LoadAttachments(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Find all reviews by ReviewID
|
||||
reviews := make(map[int64]*Review)
|
||||
ids := make([]int64, 0, len(comments))
|
||||
|
||||
@@ -200,20 +200,6 @@ func (issue *Issue) IsTimetrackerEnabled(ctx context.Context) bool {
|
||||
return issue.Repo.IsTimetrackerEnabled(ctx)
|
||||
}
|
||||
|
||||
// GetPullRequest returns the issue pull request
|
||||
func (issue *Issue) GetPullRequest() (pr *PullRequest, err error) {
|
||||
if !issue.IsPull {
|
||||
return nil, fmt.Errorf("Issue is not a pull request")
|
||||
}
|
||||
|
||||
pr, err = GetPullRequestByIssueID(db.DefaultContext, issue.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pr.Issue = issue
|
||||
return pr, err
|
||||
}
|
||||
|
||||
// LoadPoster loads poster
|
||||
func (issue *Issue) LoadPoster(ctx context.Context) (err error) {
|
||||
if issue.Poster == nil && issue.PosterID != 0 {
|
||||
|
||||
@@ -370,6 +370,9 @@ func (issues IssueList) LoadPullRequests(ctx context.Context) error {
|
||||
|
||||
for _, issue := range issues {
|
||||
issue.PullRequest = pullRequestMaps[issue.ID]
|
||||
if issue.PullRequest != nil {
|
||||
issue.PullRequest.Issue = issue
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ import (
|
||||
|
||||
// IssuesOptions represents options of an issue.
|
||||
type IssuesOptions struct { //nolint
|
||||
db.Paginator
|
||||
Paginator *db.ListOptions
|
||||
RepoIDs []int64 // overwrites RepoCond if the length is not 0
|
||||
RepoCond builder.Cond
|
||||
AssigneeID int64
|
||||
@@ -103,23 +103,11 @@ func applyLimit(sess *xorm.Session, opts *IssuesOptions) *xorm.Session {
|
||||
return sess
|
||||
}
|
||||
|
||||
// Warning: Do not use GetSkipTake() for *db.ListOptions
|
||||
// Its implementation could reset the page size with setting.API.MaxResponseItems
|
||||
if listOptions, ok := opts.Paginator.(*db.ListOptions); ok {
|
||||
if listOptions.Page >= 0 && listOptions.PageSize > 0 {
|
||||
var start int
|
||||
if listOptions.Page == 0 {
|
||||
start = 0
|
||||
} else {
|
||||
start = (listOptions.Page - 1) * listOptions.PageSize
|
||||
}
|
||||
sess.Limit(listOptions.PageSize, start)
|
||||
}
|
||||
return sess
|
||||
start := 0
|
||||
if opts.Paginator.Page > 1 {
|
||||
start = (opts.Paginator.Page - 1) * opts.Paginator.PageSize
|
||||
}
|
||||
|
||||
start, limit := opts.Paginator.GetSkipTake()
|
||||
sess.Limit(limit, start)
|
||||
sess.Limit(opts.Paginator.PageSize, start)
|
||||
|
||||
return sess
|
||||
}
|
||||
|
||||
@@ -69,13 +69,17 @@ func CountIssuesByRepo(ctx context.Context, opts *IssuesOptions) (map[int64]int6
|
||||
}
|
||||
|
||||
// CountIssues number return of issues by given conditions.
|
||||
func CountIssues(ctx context.Context, opts *IssuesOptions) (int64, error) {
|
||||
func CountIssues(ctx context.Context, opts *IssuesOptions, otherConds ...builder.Cond) (int64, error) {
|
||||
sess := db.GetEngine(ctx).
|
||||
Select("COUNT(issue.id) AS count").
|
||||
Table("issue").
|
||||
Join("INNER", "repository", "`issue`.repo_id = `repository`.id")
|
||||
applyConditions(sess, opts)
|
||||
|
||||
for _, cond := range otherConds {
|
||||
sess.And(cond)
|
||||
}
|
||||
|
||||
return sess.Count()
|
||||
}
|
||||
|
||||
|
||||
+4
-80
@@ -706,8 +706,8 @@ func (pr *PullRequest) UpdateColsIfNotMerged(ctx context.Context, cols ...string
|
||||
|
||||
// IsWorkInProgress determine if the Pull Request is a Work In Progress by its title
|
||||
// Issue must be set before this method can be called.
|
||||
func (pr *PullRequest) IsWorkInProgress() bool {
|
||||
if err := pr.LoadIssue(db.DefaultContext); err != nil {
|
||||
func (pr *PullRequest) IsWorkInProgress(ctx context.Context) bool {
|
||||
if err := pr.LoadIssue(ctx); err != nil {
|
||||
log.Error("LoadIssue: %v", err)
|
||||
return false
|
||||
}
|
||||
@@ -810,14 +810,14 @@ func UpdateAllowEdits(ctx context.Context, pr *PullRequest) error {
|
||||
}
|
||||
|
||||
// Mergeable returns if the pullrequest is mergeable.
|
||||
func (pr *PullRequest) Mergeable() bool {
|
||||
func (pr *PullRequest) Mergeable(ctx context.Context) bool {
|
||||
// If a pull request isn't mergable if it's:
|
||||
// - Being conflict checked.
|
||||
// - Has a conflict.
|
||||
// - Received a error while being conflict checked.
|
||||
// - Is a work-in-progress pull request.
|
||||
return pr.Status != PullRequestStatusChecking && pr.Status != PullRequestStatusConflict &&
|
||||
pr.Status != PullRequestStatusError && !pr.IsWorkInProgress()
|
||||
pr.Status != PullRequestStatusError && !pr.IsWorkInProgress(ctx)
|
||||
}
|
||||
|
||||
// HasEnoughApprovals returns true if pr has enough granted approvals.
|
||||
@@ -887,82 +887,6 @@ func MergeBlockedByOutdatedBranch(protectBranch *git_model.ProtectedBranch, pr *
|
||||
return protectBranch.BlockOnOutdatedBranch && pr.CommitsBehind > 0
|
||||
}
|
||||
|
||||
func PullRequestCodeOwnersReview(ctx context.Context, pull *Issue, pr *PullRequest) error {
|
||||
files := []string{"CODEOWNERS", "docs/CODEOWNERS", ".gitea/CODEOWNERS"}
|
||||
|
||||
if pr.IsWorkInProgress() {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := pr.LoadBaseRepo(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
repo, err := git.OpenRepository(ctx, pr.BaseRepo.RepoPath())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer repo.Close()
|
||||
|
||||
branch, err := repo.GetDefaultBranch()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
commit, err := repo.GetBranchCommit(branch)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var data string
|
||||
for _, file := range files {
|
||||
if blob, err := commit.GetBlobByPath(file); err == nil {
|
||||
data, err = blob.GetBlobContent(setting.UI.MaxDisplayFileSize)
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rules, _ := GetCodeOwnersFromContent(ctx, data)
|
||||
changedFiles, err := repo.GetFilesChangedBetween(git.BranchPrefix+pr.BaseBranch, pr.GetGitRefName())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
uniqUsers := make(map[int64]*user_model.User)
|
||||
uniqTeams := make(map[string]*org_model.Team)
|
||||
for _, rule := range rules {
|
||||
for _, f := range changedFiles {
|
||||
if (rule.Rule.MatchString(f) && !rule.Negative) || (!rule.Rule.MatchString(f) && rule.Negative) {
|
||||
for _, u := range rule.Users {
|
||||
uniqUsers[u.ID] = u
|
||||
}
|
||||
for _, t := range rule.Teams {
|
||||
uniqTeams[fmt.Sprintf("%d/%d", t.OrgID, t.ID)] = t
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, u := range uniqUsers {
|
||||
if u.ID != pull.Poster.ID {
|
||||
if _, err := AddReviewRequest(ctx, pull, u, pull.Poster); err != nil {
|
||||
log.Warn("Failed add assignee user: %s to PR review: %s#%d, error: %s", u.Name, pr.BaseRepo.Name, pr.ID, err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, t := range uniqTeams {
|
||||
if _, err := AddTeamReviewRequest(ctx, pull, t, pull.Poster); err != nil {
|
||||
log.Warn("Failed add assignee team: %s to PR review: %s#%d, error: %s", t.Name, pr.BaseRepo.Name, pr.ID, err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetCodeOwnersFromContent returns the code owners configuration
|
||||
// Return empty slice if files missing
|
||||
// Return warning messages on parsing errors
|
||||
|
||||
@@ -212,3 +212,12 @@ func HasMergedPullRequestInRepo(ctx context.Context, repoID, posterID int64) (bo
|
||||
Limit(1).
|
||||
Get(new(Issue))
|
||||
}
|
||||
|
||||
// GetPullRequestByIssueIDs returns all pull requests by issue ids
|
||||
func GetPullRequestByIssueIDs(ctx context.Context, issueIDs []int64) (PullRequestList, error) {
|
||||
prs := make([]*PullRequest, 0, len(issueIDs))
|
||||
return prs, db.GetEngine(ctx).
|
||||
Where("issue_id > 0").
|
||||
In("issue_id", issueIDs).
|
||||
Find(&prs)
|
||||
}
|
||||
|
||||
@@ -260,13 +260,13 @@ func TestPullRequest_IsWorkInProgress(t *testing.T) {
|
||||
pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 2})
|
||||
pr.LoadIssue(db.DefaultContext)
|
||||
|
||||
assert.False(t, pr.IsWorkInProgress())
|
||||
assert.False(t, pr.IsWorkInProgress(db.DefaultContext))
|
||||
|
||||
pr.Issue.Title = "WIP: " + pr.Issue.Title
|
||||
assert.True(t, pr.IsWorkInProgress())
|
||||
assert.True(t, pr.IsWorkInProgress(db.DefaultContext))
|
||||
|
||||
pr.Issue.Title = "[wip]: " + pr.Issue.Title
|
||||
assert.True(t, pr.IsWorkInProgress())
|
||||
assert.True(t, pr.IsWorkInProgress(db.DefaultContext))
|
||||
}
|
||||
|
||||
func TestPullRequest_GetWorkInProgressPrefixWorkInProgress(t *testing.T) {
|
||||
|
||||
@@ -240,11 +240,11 @@ type CreateReviewOptions struct {
|
||||
|
||||
// IsOfficialReviewer check if at least one of the provided reviewers can make official reviews in issue (counts towards required approvals)
|
||||
func IsOfficialReviewer(ctx context.Context, issue *Issue, reviewer *user_model.User) (bool, error) {
|
||||
pr, err := GetPullRequestByIssueID(ctx, issue.ID)
|
||||
if err != nil {
|
||||
if err := issue.LoadPullRequest(ctx); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
pr := issue.PullRequest
|
||||
rule, err := git_model.GetFirstMatchProtectedBranchRule(ctx, pr.BaseRepoID, pr.BaseBranch)
|
||||
if err != nil {
|
||||
return false, err
|
||||
@@ -272,11 +272,10 @@ func IsOfficialReviewer(ctx context.Context, issue *Issue, reviewer *user_model.
|
||||
|
||||
// IsOfficialReviewerTeam check if reviewer in this team can make official reviews in issue (counts towards required approvals)
|
||||
func IsOfficialReviewerTeam(ctx context.Context, issue *Issue, team *organization.Team) (bool, error) {
|
||||
pr, err := GetPullRequestByIssueID(ctx, issue.ID)
|
||||
if err != nil {
|
||||
if err := issue.LoadPullRequest(ctx); err != nil {
|
||||
return false, err
|
||||
}
|
||||
pb, err := git_model.GetFirstMatchProtectedBranchRule(ctx, pr.BaseRepoID, pr.BaseBranch)
|
||||
pb, err := git_model.GetFirstMatchProtectedBranchRule(ctx, issue.PullRequest.BaseRepoID, issue.PullRequest.BaseBranch)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -622,7 +621,7 @@ func AddReviewRequest(ctx context.Context, issue *Issue, reviewer, doer *user_mo
|
||||
|
||||
// skip it when reviewer hase been request to review
|
||||
if review != nil && review.Type == ReviewTypeRequest {
|
||||
return nil, nil
|
||||
return nil, committer.Commit() // still commit the transaction, or committer.Close() will rollback it, even if it's a reused transaction.
|
||||
}
|
||||
|
||||
// if the reviewer is an official reviewer,
|
||||
|
||||
@@ -9,9 +9,9 @@ import (
|
||||
|
||||
// AddConfidentialColumnToOAuth2ApplicationTable: add ConfidentialClient column, setting existing rows to true
|
||||
func AddConfidentialClientColumnToOAuth2ApplicationTable(x *xorm.Engine) error {
|
||||
type OAuth2Application struct {
|
||||
type oauth2Application struct {
|
||||
ID int64
|
||||
ConfidentialClient bool `xorm:"NOT NULL DEFAULT TRUE"`
|
||||
}
|
||||
|
||||
return x.Sync(new(OAuth2Application))
|
||||
return x.Sync(new(oauth2Application))
|
||||
}
|
||||
|
||||
@@ -13,12 +13,12 @@ import (
|
||||
|
||||
func Test_AddConfidentialClientColumnToOAuth2ApplicationTable(t *testing.T) {
|
||||
// premigration
|
||||
type OAuth2Application struct {
|
||||
type oauth2Application struct {
|
||||
ID int64
|
||||
}
|
||||
|
||||
// Prepare and load the testing database
|
||||
x, deferable := base.PrepareTestEnv(t, 0, new(OAuth2Application))
|
||||
x, deferable := base.PrepareTestEnv(t, 0, new(oauth2Application))
|
||||
defer deferable()
|
||||
if x == nil || t.Failed() {
|
||||
return
|
||||
@@ -36,7 +36,7 @@ func Test_AddConfidentialClientColumnToOAuth2ApplicationTable(t *testing.T) {
|
||||
}
|
||||
|
||||
got := []ExpectedOAuth2Application{}
|
||||
if err := x.Table("o_auth2_application").Select("id, confidential_client").Find(&got); !assert.NoError(t, err) {
|
||||
if err := x.Table("oauth2_application").Select("id, confidential_client").Find(&got); !assert.NoError(t, err) {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
actions_model "code.gitea.io/gitea/models/actions"
|
||||
"code.gitea.io/gitea/models/db"
|
||||
"code.gitea.io/gitea/models/perm"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
@@ -319,8 +320,9 @@ func CreateOrganization(org *Organization, owner *user_model.User) (err error) {
|
||||
|
||||
// Add initial creator to organization and owner team.
|
||||
if err = db.Insert(ctx, &OrgUser{
|
||||
UID: owner.ID,
|
||||
OrgID: org.ID,
|
||||
UID: owner.ID,
|
||||
OrgID: org.ID,
|
||||
IsPublic: setting.Service.DefaultOrgMemberVisible,
|
||||
}); err != nil {
|
||||
return fmt.Errorf("insert org-user relation: %w", err)
|
||||
}
|
||||
@@ -400,6 +402,8 @@ func DeleteOrganization(ctx context.Context, org *Organization) error {
|
||||
&TeamUnit{OrgID: org.ID},
|
||||
&TeamInvite{OrgID: org.ID},
|
||||
&secret_model.Secret{OwnerID: org.ID},
|
||||
&actions_model.ActionRunner{OwnerID: org.ID},
|
||||
&actions_model.ActionRunnerToken{OwnerID: org.ID},
|
||||
); err != nil {
|
||||
return fmt.Errorf("DeleteBeans: %w", err)
|
||||
}
|
||||
|
||||
@@ -95,7 +95,10 @@ func GetRepoAssignees(ctx context.Context, repo *Repository) (_ []*user_model.Us
|
||||
// and just waste 1 unit is cheaper than re-allocate memory once.
|
||||
users := make([]*user_model.User, 0, len(uniqueUserIDs)+1)
|
||||
if len(userIDs) > 0 {
|
||||
if err = e.In("id", uniqueUserIDs.Values()).OrderBy(user_model.GetOrderByName()).Find(&users); err != nil {
|
||||
if err = e.In("id", uniqueUserIDs.Values()).
|
||||
Where(builder.Eq{"`user`.is_active": true}).
|
||||
OrderBy(user_model.GetOrderByName()).
|
||||
Find(&users); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
@@ -117,7 +120,8 @@ func GetReviewers(ctx context.Context, repo *Repository, doerID, posterID int64)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cond := builder.And(builder.Neq{"`user`.id": posterID})
|
||||
cond := builder.And(builder.Neq{"`user`.id": posterID}).
|
||||
And(builder.Eq{"`user`.is_active": true})
|
||||
|
||||
if repo.IsPrivate || repo.Owner.Visibility == api.VisibleTypePrivate {
|
||||
// This a private repository:
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"code.gitea.io/gitea/models/db"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
@@ -25,10 +26,17 @@ func TestRepoAssignees(t *testing.T) {
|
||||
repo21 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 21})
|
||||
users, err = repo_model.GetRepoAssignees(db.DefaultContext, repo21)
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, users, 3)
|
||||
assert.Equal(t, users[0].ID, int64(15))
|
||||
assert.Equal(t, users[1].ID, int64(18))
|
||||
assert.Equal(t, users[2].ID, int64(16))
|
||||
if assert.Len(t, users, 3) {
|
||||
assert.ElementsMatch(t, []int64{15, 16, 18}, []int64{users[0].ID, users[1].ID, users[2].ID})
|
||||
}
|
||||
|
||||
// do not return deactivated users
|
||||
assert.NoError(t, user_model.UpdateUserCols(db.DefaultContext, &user_model.User{ID: 15, IsActive: false}, "is_active"))
|
||||
users, err = repo_model.GetRepoAssignees(db.DefaultContext, repo21)
|
||||
assert.NoError(t, err)
|
||||
if assert.Len(t, users, 2) {
|
||||
assert.NotContains(t, []int64{users[0].ID, users[1].ID}, 15)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRepoGetReviewers(t *testing.T) {
|
||||
@@ -40,17 +48,19 @@ func TestRepoGetReviewers(t *testing.T) {
|
||||
ctx := db.DefaultContext
|
||||
reviewers, err := repo_model.GetReviewers(ctx, repo1, 2, 2)
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, reviewers, 4)
|
||||
if assert.Len(t, reviewers, 3) {
|
||||
assert.ElementsMatch(t, []int64{1, 4, 11}, []int64{reviewers[0].ID, reviewers[1].ID, reviewers[2].ID})
|
||||
}
|
||||
|
||||
// should include doer if doer is not PR poster.
|
||||
reviewers, err = repo_model.GetReviewers(ctx, repo1, 11, 2)
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, reviewers, 4)
|
||||
assert.Len(t, reviewers, 3)
|
||||
|
||||
// should not include PR poster, if PR poster would be otherwise eligible
|
||||
reviewers, err = repo_model.GetReviewers(ctx, repo1, 11, 4)
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, reviewers, 3)
|
||||
assert.Len(t, reviewers, 2)
|
||||
|
||||
// test private user repo
|
||||
repo2 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2})
|
||||
|
||||
@@ -9,7 +9,10 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
actions_model "code.gitea.io/gitea/models/actions"
|
||||
"code.gitea.io/gitea/models/db"
|
||||
actions_module "code.gitea.io/gitea/modules/actions"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
secret_module "code.gitea.io/gitea/modules/secret"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/timeutil"
|
||||
@@ -128,3 +131,39 @@ func UpdateSecret(ctx context.Context, secretID int64, data string) error {
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func GetSecretsOfTask(ctx context.Context, task *actions_model.ActionTask) (map[string]string, error) {
|
||||
secrets := map[string]string{}
|
||||
|
||||
secrets["GITHUB_TOKEN"] = task.Token
|
||||
secrets["GITEA_TOKEN"] = task.Token
|
||||
|
||||
if task.Job.Run.IsForkPullRequest && task.Job.Run.TriggerEvent != actions_module.GithubEventPullRequestTarget {
|
||||
// ignore secrets for fork pull request, except GITHUB_TOKEN and GITEA_TOKEN which are automatically generated.
|
||||
// for the tasks triggered by pull_request_target event, they could access the secrets because they will run in the context of the base branch
|
||||
// see the documentation: https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_target
|
||||
return secrets, nil
|
||||
}
|
||||
|
||||
ownerSecrets, err := FindSecrets(ctx, FindSecretsOptions{OwnerID: task.Job.Run.Repo.OwnerID})
|
||||
if err != nil {
|
||||
log.Error("find secrets of owner %v: %v", task.Job.Run.Repo.OwnerID, err)
|
||||
return nil, err
|
||||
}
|
||||
repoSecrets, err := FindSecrets(ctx, FindSecretsOptions{RepoID: task.Job.Run.RepoID})
|
||||
if err != nil {
|
||||
log.Error("find secrets of repo %v: %v", task.Job.Run.RepoID, err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, secret := range append(ownerSecrets, repoSecrets...) {
|
||||
v, err := secret_module.DecryptSecret(setting.SecretKey, secret.Data)
|
||||
if err != nil {
|
||||
log.Error("decrypt secret %v %q: %v", secret.ID, secret.Name, err)
|
||||
return nil, err
|
||||
}
|
||||
secrets[secret.Name] = v
|
||||
}
|
||||
|
||||
return secrets, nil
|
||||
}
|
||||
|
||||
@@ -491,7 +491,7 @@ func SearchEmails(ctx context.Context, opts *SearchEmailOptions) ([]*SearchEmail
|
||||
cond = cond.And(builder.Eq{"email_address.is_activated": false})
|
||||
}
|
||||
|
||||
count, err := db.GetEngine(ctx).Join("INNER", "`user`", "`user`.ID = email_address.uid").
|
||||
count, err := db.GetEngine(ctx).Join("INNER", "`user`", "`user`.id = email_address.uid").
|
||||
Where(cond).Count(new(EmailAddress))
|
||||
if err != nil {
|
||||
return nil, 0, fmt.Errorf("Count: %w", err)
|
||||
@@ -507,7 +507,7 @@ func SearchEmails(ctx context.Context, opts *SearchEmailOptions) ([]*SearchEmail
|
||||
emails := make([]*SearchEmailResult, 0, opts.PageSize)
|
||||
err = db.GetEngine(ctx).Table("email_address").
|
||||
Select("email_address.*, `user`.name, `user`.full_name").
|
||||
Join("INNER", "`user`", "`user`.ID = email_address.uid").
|
||||
Join("INNER", "`user`", "`user`.id = email_address.uid").
|
||||
Where(cond).
|
||||
OrderBy(orderby).
|
||||
Limit(opts.PageSize, (opts.Page-1)*opts.PageSize).
|
||||
|
||||
@@ -41,6 +41,12 @@ func FullSteps(task *actions_model.ActionTask) []*actions_model.ActionTaskStep {
|
||||
}
|
||||
logIndex += preStep.LogLength
|
||||
|
||||
// lastHasRunStep is the last step that has run.
|
||||
// For example,
|
||||
// 1. preStep(Success) -> step1(Success) -> step2(Running) -> step3(Waiting) -> postStep(Waiting): lastHasRunStep is step1.
|
||||
// 2. preStep(Success) -> step1(Success) -> step2(Success) -> step3(Success) -> postStep(Success): lastHasRunStep is step3.
|
||||
// 3. preStep(Success) -> step1(Success) -> step2(Failure) -> step3 -> postStep(Waiting): lastHasRunStep is step2.
|
||||
// So its Stopped is the Started of postStep when there are no more steps to run.
|
||||
var lastHasRunStep *actions_model.ActionTaskStep
|
||||
for _, step := range task.Steps {
|
||||
if step.Status.HasRun() {
|
||||
@@ -56,11 +62,15 @@ func FullSteps(task *actions_model.ActionTask) []*actions_model.ActionTaskStep {
|
||||
Name: postStepName,
|
||||
Status: actions_model.StatusWaiting,
|
||||
}
|
||||
if task.Status.IsDone() {
|
||||
// If the lastHasRunStep is the last step, or it has failed, postStep has started.
|
||||
if lastHasRunStep.Status.IsFailure() || lastHasRunStep == task.Steps[len(task.Steps)-1] {
|
||||
postStep.LogIndex = logIndex
|
||||
postStep.LogLength = task.LogLength - postStep.LogIndex
|
||||
postStep.Status = task.Status
|
||||
postStep.Started = lastHasRunStep.Stopped
|
||||
postStep.Status = actions_model.StatusRunning
|
||||
}
|
||||
if task.Status.IsDone() {
|
||||
postStep.Status = task.Status
|
||||
postStep.Stopped = task.Stopped
|
||||
}
|
||||
ret := make([]*actions_model.ActionTaskStep, 0, len(task.Steps)+2)
|
||||
|
||||
@@ -103,6 +103,40 @@ func TestFullSteps(t *testing.T) {
|
||||
{Name: postStepName, Status: actions_model.StatusSuccess, LogIndex: 100, LogLength: 0, Started: 10100, Stopped: 10100},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "all steps finished but task is running",
|
||||
task: &actions_model.ActionTask{
|
||||
Steps: []*actions_model.ActionTaskStep{
|
||||
{Status: actions_model.StatusSuccess, LogIndex: 10, LogLength: 80, Started: 10010, Stopped: 10090},
|
||||
},
|
||||
Status: actions_model.StatusRunning,
|
||||
Started: 10000,
|
||||
Stopped: 0,
|
||||
LogLength: 100,
|
||||
},
|
||||
want: []*actions_model.ActionTaskStep{
|
||||
{Name: preStepName, Status: actions_model.StatusSuccess, LogIndex: 0, LogLength: 10, Started: 10000, Stopped: 10010},
|
||||
{Status: actions_model.StatusSuccess, LogIndex: 10, LogLength: 80, Started: 10010, Stopped: 10090},
|
||||
{Name: postStepName, Status: actions_model.StatusRunning, LogIndex: 90, LogLength: 10, Started: 10090, Stopped: 0},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "skipped task",
|
||||
task: &actions_model.ActionTask{
|
||||
Steps: []*actions_model.ActionTaskStep{
|
||||
{Status: actions_model.StatusSkipped, LogIndex: 0, LogLength: 0, Started: 0, Stopped: 0},
|
||||
},
|
||||
Status: actions_model.StatusSkipped,
|
||||
Started: 0,
|
||||
Stopped: 0,
|
||||
LogLength: 0,
|
||||
},
|
||||
want: []*actions_model.ActionTaskStep{
|
||||
{Name: preStepName, Status: actions_model.StatusSkipped, LogIndex: 0, LogLength: 0, Started: 0, Stopped: 0},
|
||||
{Status: actions_model.StatusSkipped, LogIndex: 0, LogLength: 0, Started: 0, Stopped: 0},
|
||||
{Name: postStepName, Status: actions_model.StatusSkipped, LogIndex: 0, LogLength: 0, Started: 0, Stopped: 0},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
|
||||
@@ -158,6 +158,12 @@ func checkDBConsistency(ctx context.Context, logger log.Logger, autofix bool) er
|
||||
Fixer: actions_model.FixRunnersWithoutBelongingOwner,
|
||||
FixedMessage: "Removed",
|
||||
},
|
||||
{
|
||||
Name: "Action Runners without existing repository",
|
||||
Counter: actions_model.CountRunnersWithoutBelongingRepo,
|
||||
Fixer: actions_model.FixRunnersWithoutBelongingRepo,
|
||||
FixedMessage: "Removed",
|
||||
},
|
||||
}
|
||||
|
||||
// TODO: function to recalc all counters
|
||||
|
||||
@@ -216,6 +216,12 @@ func fixBrokenRepoUnit16961(repoUnit *repo_model.RepoUnit, bs []byte) (fixed boo
|
||||
return false, nil
|
||||
}
|
||||
|
||||
var cfg any
|
||||
err = json.UnmarshalHandleDoubleEncode(bs, &cfg)
|
||||
if err == nil {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
switch repoUnit.Type {
|
||||
case unit.TypeCode, unit.TypeReleases, unit.TypeWiki, unit.TypeProjects:
|
||||
cfg := &repo_model.UnitConfig{}
|
||||
|
||||
@@ -162,7 +162,7 @@ func checkStorage(opts *checkStorageOptions) func(ctx context.Context, logger lo
|
||||
if opts.RepoArchives || opts.All {
|
||||
if err := commonCheckStorage(ctx, logger, autofix,
|
||||
&commonStorageCheckOptions{
|
||||
storer: storage.RepoAvatars,
|
||||
storer: storage.RepoArchives,
|
||||
isOrphaned: func(path string, obj storage.Object, stat fs.FileInfo) (bool, error) {
|
||||
exists, err := repo.ExistsRepoArchiverWithStoragePath(ctx, path)
|
||||
if err == nil || errors.Is(err, util.ErrInvalidArgument) {
|
||||
|
||||
@@ -459,7 +459,7 @@ func parseCommitFileStatus(fileStatus *CommitFileStatus, stdout io.Reader) {
|
||||
_, _ = rd.Discard(1)
|
||||
}
|
||||
for {
|
||||
modifier, err := rd.ReadSlice('\x00')
|
||||
modifier, err := rd.ReadString('\x00')
|
||||
if err != nil {
|
||||
if err != io.EOF {
|
||||
log.Error("Unexpected error whilst reading from git log --name-status. Error: %v", err)
|
||||
|
||||
@@ -47,6 +47,12 @@ func convertPGPSignature(c *object.Commit) *CommitGPGSignature {
|
||||
return nil
|
||||
}
|
||||
|
||||
if c.Encoding != "" && c.Encoding != "UTF-8" {
|
||||
if _, err = fmt.Fprintf(&w, "\nencoding %s\n", c.Encoding); err != nil {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
if _, err = fmt.Fprintf(&w, "\n\n%s", c.Message); err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -84,6 +84,8 @@ readLoop:
|
||||
commit.Committer = &Signature{}
|
||||
commit.Committer.Decode(data)
|
||||
_, _ = payloadSB.Write(line)
|
||||
case "encoding":
|
||||
_, _ = payloadSB.Write(line)
|
||||
case "gpgsig":
|
||||
_, _ = signatureSB.Write(data)
|
||||
_ = signatureSB.WriteByte('\n')
|
||||
|
||||
@@ -125,6 +125,73 @@ empty commit`, commitFromReader.Signature.Payload)
|
||||
assert.EqualValues(t, commitFromReader, commitFromReader2)
|
||||
}
|
||||
|
||||
func TestCommitWithEncodingFromReader(t *testing.T) {
|
||||
commitString := `feaf4ba6bc635fec442f46ddd4512416ec43c2c2 commit 1074
|
||||
tree ca3fad42080dd1a6d291b75acdfc46e5b9b307e5
|
||||
parent 47b24e7ab977ed31c5a39989d570847d6d0052af
|
||||
author KN4CK3R <admin@oldschoolhack.me> 1711702962 +0100
|
||||
committer KN4CK3R <admin@oldschoolhack.me> 1711702962 +0100
|
||||
encoding ISO-8859-1
|
||||
gpgsig -----BEGIN PGP SIGNATURE-----
|
||||
|
||||
iQGzBAABCgAdFiEE9HRrbqvYxPT8PXbefPSEkrowAa8FAmYGg7IACgkQfPSEkrow
|
||||
Aa9olwv+P0HhtCM6CRvlUmPaqswRsDPNR4i66xyXGiSxdI9V5oJL7HLiQIM7KrFR
|
||||
gizKa2COiGtugv8fE+TKqXKaJx6uJUJEjaBd8E9Af9PrAzjWj+A84lU6/PgPS8hq
|
||||
zOfZraLOEWRH4tZcS+u2yFLu3ez2Wqh1xW5LNy7xqEedMXEFD1HwSJ0+pjacNkzr
|
||||
frp6Asyt7xRI6YmgFJZJoRsS3Ktr6rtKeRL2IErSQQyorOqj6gKrglhrhfG/114j
|
||||
FKB1v4or0WZ1DE8iP2SJZ3n+/K1IuWAINh7MVdb7PndfBPEa+IL+ucNk5uzEE8Jd
|
||||
G8smGxXUeFEt2cP1dj2W8EgAxuA9sTnH9dqI5aRqy5ifDjuya7Emm8sdOUvtGdmn
|
||||
SONRzusmu5n3DgV956REL7x62h7JuqmBz/12HZkr0z0zgXkcZ04q08pSJATX5N1F
|
||||
yN+tWxTsWg+zhDk96d5Esdo9JMjcFvPv0eioo30GAERaz1hoD7zCMT4jgUFTQwgz
|
||||
jw4YcO5u
|
||||
=r3UU
|
||||
-----END PGP SIGNATURE-----
|
||||
|
||||
ISO-8859-1`
|
||||
|
||||
sha := SHA1{0xfe, 0xaf, 0x4b, 0xa6, 0xbc, 0x63, 0x5f, 0xec, 0x44, 0x2f, 0x46, 0xdd, 0xd4, 0x51, 0x24, 0x16, 0xec, 0x43, 0xc2, 0xc2}
|
||||
gitRepo, err := openRepositoryWithDefaultContext(filepath.Join(testReposDir, "repo1_bare"))
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, gitRepo)
|
||||
defer gitRepo.Close()
|
||||
|
||||
commitFromReader, err := CommitFromReader(gitRepo, sha, strings.NewReader(commitString))
|
||||
assert.NoError(t, err)
|
||||
if !assert.NotNil(t, commitFromReader) {
|
||||
return
|
||||
}
|
||||
assert.EqualValues(t, sha, commitFromReader.ID)
|
||||
assert.EqualValues(t, `-----BEGIN PGP SIGNATURE-----
|
||||
|
||||
iQGzBAABCgAdFiEE9HRrbqvYxPT8PXbefPSEkrowAa8FAmYGg7IACgkQfPSEkrow
|
||||
Aa9olwv+P0HhtCM6CRvlUmPaqswRsDPNR4i66xyXGiSxdI9V5oJL7HLiQIM7KrFR
|
||||
gizKa2COiGtugv8fE+TKqXKaJx6uJUJEjaBd8E9Af9PrAzjWj+A84lU6/PgPS8hq
|
||||
zOfZraLOEWRH4tZcS+u2yFLu3ez2Wqh1xW5LNy7xqEedMXEFD1HwSJ0+pjacNkzr
|
||||
frp6Asyt7xRI6YmgFJZJoRsS3Ktr6rtKeRL2IErSQQyorOqj6gKrglhrhfG/114j
|
||||
FKB1v4or0WZ1DE8iP2SJZ3n+/K1IuWAINh7MVdb7PndfBPEa+IL+ucNk5uzEE8Jd
|
||||
G8smGxXUeFEt2cP1dj2W8EgAxuA9sTnH9dqI5aRqy5ifDjuya7Emm8sdOUvtGdmn
|
||||
SONRzusmu5n3DgV956REL7x62h7JuqmBz/12HZkr0z0zgXkcZ04q08pSJATX5N1F
|
||||
yN+tWxTsWg+zhDk96d5Esdo9JMjcFvPv0eioo30GAERaz1hoD7zCMT4jgUFTQwgz
|
||||
jw4YcO5u
|
||||
=r3UU
|
||||
-----END PGP SIGNATURE-----
|
||||
`, commitFromReader.Signature.Signature)
|
||||
assert.EqualValues(t, `tree ca3fad42080dd1a6d291b75acdfc46e5b9b307e5
|
||||
parent 47b24e7ab977ed31c5a39989d570847d6d0052af
|
||||
author KN4CK3R <admin@oldschoolhack.me> 1711702962 +0100
|
||||
committer KN4CK3R <admin@oldschoolhack.me> 1711702962 +0100
|
||||
encoding ISO-8859-1
|
||||
|
||||
ISO-8859-1`, commitFromReader.Signature.Payload)
|
||||
assert.EqualValues(t, "KN4CK3R <admin@oldschoolhack.me>", commitFromReader.Author.String())
|
||||
|
||||
commitFromReader2, err := CommitFromReader(gitRepo, sha, strings.NewReader(commitString+"\n\n"))
|
||||
assert.NoError(t, err)
|
||||
commitFromReader.CommitMessage += "\n\n"
|
||||
commitFromReader.Signature.Payload += "\n\n"
|
||||
assert.EqualValues(t, commitFromReader, commitFromReader2)
|
||||
}
|
||||
|
||||
func TestHasPreviousCommit(t *testing.T) {
|
||||
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
|
||||
|
||||
|
||||
+1
-1
@@ -248,7 +248,7 @@ type DivergeObject struct {
|
||||
// GetDivergingCommits returns the number of commits a targetBranch is ahead or behind a baseBranch
|
||||
func GetDivergingCommits(ctx context.Context, repoPath, baseBranch, targetBranch string) (do DivergeObject, err error) {
|
||||
cmd := NewCommand(ctx, "rev-list", "--count", "--left-right").
|
||||
AddDynamicArguments(baseBranch + "..." + targetBranch)
|
||||
AddDynamicArguments(baseBranch + "..." + targetBranch).AddArguments("--")
|
||||
stdout, _, err := cmd.RunStdString(&RunOpts{Dir: repoPath})
|
||||
if err != nil {
|
||||
return do, err
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
)
|
||||
|
||||
// ParsePaginator parses a db.Paginator into a skip and limit
|
||||
func ParsePaginator(paginator db.Paginator, max ...int) (int, int) {
|
||||
func ParsePaginator(paginator *db.ListOptions, max ...int) (int, int) {
|
||||
// Use a very large number to indicate no limit
|
||||
unlimited := math.MaxInt32
|
||||
if len(max) > 0 {
|
||||
@@ -19,22 +19,15 @@ func ParsePaginator(paginator db.Paginator, max ...int) (int, int) {
|
||||
}
|
||||
|
||||
if paginator == nil || paginator.IsListAll() {
|
||||
// It shouldn't happen. In actual usage scenarios, there should not be requests to search all.
|
||||
// But if it does happen, respect it and return "unlimited".
|
||||
// And it's also useful for testing.
|
||||
return 0, unlimited
|
||||
}
|
||||
|
||||
// Warning: Do not use GetSkipTake() for *db.ListOptions
|
||||
// Its implementation could reset the page size with setting.API.MaxResponseItems
|
||||
if listOptions, ok := paginator.(*db.ListOptions); ok {
|
||||
if listOptions.Page >= 0 && listOptions.PageSize > 0 {
|
||||
var start int
|
||||
if listOptions.Page == 0 {
|
||||
start = 0
|
||||
} else {
|
||||
start = (listOptions.Page - 1) * listOptions.PageSize
|
||||
}
|
||||
return start, listOptions.PageSize
|
||||
}
|
||||
return 0, unlimited
|
||||
if paginator.PageSize == 0 {
|
||||
// Do not return any results when searching, it's used to get the total count only.
|
||||
return 0, 0
|
||||
}
|
||||
|
||||
return paginator.GetSkipTake()
|
||||
|
||||
@@ -78,6 +78,17 @@ func (i *Indexer) Search(ctx context.Context, options *internal.SearchOptions) (
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// If pagesize == 0, return total count only. It's a special case for search count.
|
||||
if options.Paginator != nil && options.Paginator.PageSize == 0 {
|
||||
total, err := issue_model.CountIssues(ctx, opt, cond)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &internal.SearchResult{
|
||||
Total: total,
|
||||
}, nil
|
||||
}
|
||||
|
||||
ids, total, err := issue_model.IssueIDs(ctx, opt, cond)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -68,7 +68,7 @@ func ToSearchOptions(keyword string, opts *issues_model.IssuesOptions) *SearchOp
|
||||
searchOpt.Paginator = opts.Paginator
|
||||
|
||||
switch opts.SortType {
|
||||
case "":
|
||||
case "", "latest":
|
||||
searchOpt.SortBy = SortByCreatedDesc
|
||||
case "oldest":
|
||||
searchOpt.SortBy = SortByCreatedAsc
|
||||
@@ -86,7 +86,7 @@ func ToSearchOptions(keyword string, opts *issues_model.IssuesOptions) *SearchOp
|
||||
searchOpt.SortBy = SortByDeadlineDesc
|
||||
case "priority", "priorityrepo", "project-column-sorting":
|
||||
// Unsupported sort type for search
|
||||
searchOpt.SortBy = SortByUpdatedDesc
|
||||
fallthrough
|
||||
default:
|
||||
searchOpt.SortBy = SortByUpdatedDesc
|
||||
}
|
||||
|
||||
@@ -309,7 +309,7 @@ func SearchIssues(ctx context.Context, opts *SearchOptions) ([]int64, int64, err
|
||||
|
||||
// CountIssues counts issues by options. It is a shortcut of SearchIssues(ctx, opts) but only returns the total count.
|
||||
func CountIssues(ctx context.Context, opts *SearchOptions) (int64, error) {
|
||||
opts = opts.Copy(func(options *SearchOptions) { opts.Paginator = &db_model.ListOptions{PageSize: 0} })
|
||||
opts = opts.Copy(func(options *SearchOptions) { options.Paginator = &db_model.ListOptions{PageSize: 0} })
|
||||
|
||||
_, total, err := SearchIssues(ctx, opts)
|
||||
return total, err
|
||||
|
||||
@@ -104,7 +104,7 @@ type SearchOptions struct {
|
||||
UpdatedAfterUnix *int64
|
||||
UpdatedBeforeUnix *int64
|
||||
|
||||
db.Paginator
|
||||
Paginator *db.ListOptions
|
||||
|
||||
SortBy SortBy // sort by field
|
||||
}
|
||||
|
||||
@@ -77,6 +77,13 @@ func TestIndexer(t *testing.T, indexer internal.Indexer) {
|
||||
assert.Equal(t, c.ExpectedIDs, ids)
|
||||
assert.Equal(t, c.ExpectedTotal, result.Total)
|
||||
}
|
||||
|
||||
// test counting
|
||||
c.SearchOptions.Paginator = &db.ListOptions{PageSize: 0}
|
||||
countResult, err := indexer.Search(context.Background(), c.SearchOptions)
|
||||
require.NoError(t, err)
|
||||
assert.Empty(t, countResult.Hits)
|
||||
assert.Equal(t, result.Total, countResult.Total)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ package meilisearch
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
@@ -210,7 +211,19 @@ func (b *Indexer) Search(ctx context.Context, options *internal.SearchOptions) (
|
||||
|
||||
skip, limit := indexer_internal.ParsePaginator(options.Paginator, maxTotalHits)
|
||||
|
||||
searchRes, err := b.inner.Client.Index(b.inner.VersionedIndexName()).Search(options.Keyword, &meilisearch.SearchRequest{
|
||||
counting := limit == 0
|
||||
if counting {
|
||||
// If set limit to 0, it will be 20 by default, and -1 is not allowed.
|
||||
// See https://www.meilisearch.com/docs/reference/api/search#limit
|
||||
// So set limit to 1 to make the cost as low as possible, then clear the result before returning.
|
||||
limit = 1
|
||||
}
|
||||
|
||||
// to make it non fuzzy ("typo tolerance" in meilisearch terms), we have to quote the keyword(s)
|
||||
// https://www.meilisearch.com/docs/reference/api/search#phrase-search
|
||||
keyword := doubleQuoteKeyword(options.Keyword)
|
||||
|
||||
searchRes, err := b.inner.Client.Index(b.inner.VersionedIndexName()).Search(keyword, &meilisearch.SearchRequest{
|
||||
Filter: query.Statement(),
|
||||
Limit: int64(limit),
|
||||
Offset: int64(skip),
|
||||
@@ -221,6 +234,10 @@ func (b *Indexer) Search(ctx context.Context, options *internal.SearchOptions) (
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if counting {
|
||||
searchRes.Hits = nil
|
||||
}
|
||||
|
||||
hits := make([]internal.Match, 0, len(searchRes.Hits))
|
||||
for _, hit := range searchRes.Hits {
|
||||
hits = append(hits, internal.Match{
|
||||
@@ -241,3 +258,16 @@ func parseSortBy(sortBy internal.SortBy) string {
|
||||
}
|
||||
return field + ":asc"
|
||||
}
|
||||
|
||||
func doubleQuoteKeyword(k string) string {
|
||||
kp := strings.Split(k, " ")
|
||||
parts := 0
|
||||
for i := range kp {
|
||||
part := strings.Trim(kp[i], "\"")
|
||||
if part != "" {
|
||||
kp[parts] = fmt.Sprintf(`"%s"`, part)
|
||||
parts++
|
||||
}
|
||||
}
|
||||
return strings.Join(kp[:parts], " ")
|
||||
}
|
||||
|
||||
@@ -11,6 +11,8 @@ import (
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/modules/indexer/issues/internal/tests"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestMeilisearchIndexer(t *testing.T) {
|
||||
@@ -48,3 +50,11 @@ func TestMeilisearchIndexer(t *testing.T) {
|
||||
|
||||
tests.TestIndexer(t, indexer)
|
||||
}
|
||||
|
||||
func TestDoubleQuoteKeyword(t *testing.T) {
|
||||
assert.EqualValues(t, "", doubleQuoteKeyword(""))
|
||||
assert.EqualValues(t, `"a" "b" "c"`, doubleQuoteKeyword("a b c"))
|
||||
assert.EqualValues(t, `"a" "d" "g"`, doubleQuoteKeyword("a d g"))
|
||||
assert.EqualValues(t, `"a" "d" "g"`, doubleQuoteKeyword("a d g"))
|
||||
assert.EqualValues(t, `"a" "d" "g"`, doubleQuoteKeyword(`a "" "d" """g`))
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ func (c *FilesystemClient) Download(ctx context.Context, objects []Pointer, call
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer f.Close()
|
||||
if err := callback(p, f, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -75,7 +75,7 @@ func (c *FilesystemClient) Upload(ctx context.Context, objects []Pointer, callba
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer f.Close()
|
||||
_, err = io.Copy(f, content)
|
||||
|
||||
return err
|
||||
|
||||
@@ -503,9 +503,17 @@ func TestMathBlock(t *testing.T) {
|
||||
`\(a\) \(b\)`,
|
||||
`<p><code class="language-math is-loading">a</code> <code class="language-math is-loading">b</code></p>` + nl,
|
||||
},
|
||||
{
|
||||
`$a$.`,
|
||||
`<p><code class="language-math is-loading">a</code>.</p>` + nl,
|
||||
},
|
||||
{
|
||||
`.$a$`,
|
||||
`<p>.$a$</p>` + nl,
|
||||
},
|
||||
{
|
||||
`$a a$b b$`,
|
||||
`<p><code class="language-math is-loading">a a$b b</code></p>` + nl,
|
||||
`<p>$a a$b b$</p>` + nl,
|
||||
},
|
||||
{
|
||||
`a a$b b`,
|
||||
@@ -513,7 +521,15 @@ func TestMathBlock(t *testing.T) {
|
||||
},
|
||||
{
|
||||
`a$b $a a$b b$`,
|
||||
`<p>a$b <code class="language-math is-loading">a a$b b</code></p>` + nl,
|
||||
`<p>a$b $a a$b b$</p>` + nl,
|
||||
},
|
||||
{
|
||||
"a$x$",
|
||||
`<p>a$x$</p>` + nl,
|
||||
},
|
||||
{
|
||||
"$x$a",
|
||||
`<p>$x$a</p>` + nl,
|
||||
},
|
||||
{
|
||||
"$$a$$",
|
||||
|
||||
@@ -41,9 +41,12 @@ func (parser *inlineParser) Trigger() []byte {
|
||||
return parser.start[0:1]
|
||||
}
|
||||
|
||||
func isPunctuation(b byte) bool {
|
||||
return b == '.' || b == '!' || b == '?' || b == ',' || b == ';' || b == ':'
|
||||
}
|
||||
|
||||
func isAlphanumeric(b byte) bool {
|
||||
// Github only cares about 0-9A-Za-z
|
||||
return (b >= '0' && b <= '9') || (b >= 'A' && b <= 'Z') || (b >= 'a' && b <= 'z')
|
||||
return (b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') || (b >= '0' && b <= '9')
|
||||
}
|
||||
|
||||
// Parse parses the current line and returns a result of parsing.
|
||||
@@ -56,7 +59,7 @@ func (parser *inlineParser) Parse(parent ast.Node, block text.Reader, pc parser.
|
||||
}
|
||||
|
||||
precedingCharacter := block.PrecendingCharacter()
|
||||
if precedingCharacter < 256 && isAlphanumeric(byte(precedingCharacter)) {
|
||||
if precedingCharacter < 256 && (isAlphanumeric(byte(precedingCharacter)) || isPunctuation(byte(precedingCharacter))) {
|
||||
// need to exclude things like `a$` from being considered a start
|
||||
return nil
|
||||
}
|
||||
@@ -75,14 +78,19 @@ func (parser *inlineParser) Parse(parent ast.Node, block text.Reader, pc parser.
|
||||
ender += pos
|
||||
|
||||
// Now we want to check the character at the end of our parser section
|
||||
// that is ender + len(parser.end)
|
||||
// that is ender + len(parser.end) and check if char before ender is '\'
|
||||
pos = ender + len(parser.end)
|
||||
if len(line) <= pos {
|
||||
break
|
||||
}
|
||||
if !isAlphanumeric(line[pos]) {
|
||||
suceedingCharacter := line[pos]
|
||||
if !isPunctuation(suceedingCharacter) && !(suceedingCharacter == ' ') {
|
||||
return nil
|
||||
}
|
||||
if line[ender-1] != '\\' {
|
||||
break
|
||||
}
|
||||
|
||||
// move the pointer onwards
|
||||
ender += len(parser.end)
|
||||
}
|
||||
|
||||
+15
-10
@@ -12,6 +12,7 @@ import (
|
||||
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
)
|
||||
|
||||
// Git environment variables
|
||||
@@ -32,13 +33,13 @@ const (
|
||||
)
|
||||
|
||||
// Bool checks for a key in the map and parses as a boolean
|
||||
func (g GitPushOptions) Bool(key string, def bool) bool {
|
||||
func (g GitPushOptions) Bool(key string) util.OptionalBool {
|
||||
if val, ok := g[key]; ok {
|
||||
if b, err := strconv.ParseBool(val); err == nil {
|
||||
return b
|
||||
return util.OptionalBoolOf(b)
|
||||
}
|
||||
}
|
||||
return def
|
||||
return util.OptionalBoolNone
|
||||
}
|
||||
|
||||
// HookOptions represents the options for the Hook calls
|
||||
@@ -87,13 +88,17 @@ type HookProcReceiveResult struct {
|
||||
|
||||
// HookProcReceiveRefResult represents an individual result from ProcReceive
|
||||
type HookProcReceiveRefResult struct {
|
||||
OldOID string
|
||||
NewOID string
|
||||
Ref string
|
||||
OriginalRef git.RefName
|
||||
IsForcePush bool
|
||||
IsNotMatched bool
|
||||
Err string
|
||||
OldOID string
|
||||
NewOID string
|
||||
Ref string
|
||||
OriginalRef git.RefName
|
||||
IsForcePush bool
|
||||
IsNotMatched bool
|
||||
Err string
|
||||
IsCreatePR bool
|
||||
URL string
|
||||
ShouldShowMessage bool
|
||||
HeadBranch string
|
||||
}
|
||||
|
||||
// HookPreReceive check whether the provided commits are allowed
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
var (
|
||||
backoffBegin = 50 * time.Millisecond
|
||||
backoffUpper = 2 * time.Second
|
||||
)
|
||||
@@ -18,6 +18,14 @@ type (
|
||||
backoffFuncErr func() (retry bool, err error)
|
||||
)
|
||||
|
||||
func mockBackoffDuration(d time.Duration) func() {
|
||||
oldBegin, oldUpper := backoffBegin, backoffUpper
|
||||
backoffBegin, backoffUpper = d, d
|
||||
return func() {
|
||||
backoffBegin, backoffUpper = oldBegin, oldUpper
|
||||
}
|
||||
}
|
||||
|
||||
func backoffRetErr[T any](ctx context.Context, begin, upper time.Duration, end <-chan time.Time, fn backoffFuncRetErr[T]) (ret T, err error) {
|
||||
d := begin
|
||||
for {
|
||||
|
||||
@@ -63,6 +63,8 @@ func (q *WorkerPoolQueue[T]) doDispatchBatchToWorker(wg *workerGroup[T], flushCh
|
||||
// TODO: the logic could be improved in the future, to avoid a data-race between "doStartNewWorker" and "workerNum"
|
||||
// The root problem is that if we skip "doStartNewWorker" here, the "workerNum" might be decreased by other workers later
|
||||
// So ideally, it should check whether there are enough workers by some approaches, and start new workers if necessary.
|
||||
// This data-race is not serious, as long as a new worker will be started soon to make sure there are enough workers,
|
||||
// so no need to hugely refactor at the moment.
|
||||
q.workerNumMu.Lock()
|
||||
noWorker := q.workerNum == 0
|
||||
if full || noWorker {
|
||||
@@ -136,6 +138,14 @@ func (q *WorkerPoolQueue[T]) basePushForShutdown(items ...T) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func resetIdleTicker(t *time.Ticker, dur time.Duration) {
|
||||
t.Reset(dur)
|
||||
select {
|
||||
case <-t.C:
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
// doStartNewWorker starts a new worker for the queue, the worker reads from worker's channel and handles the items.
|
||||
func (q *WorkerPoolQueue[T]) doStartNewWorker(wp *workerGroup[T]) {
|
||||
wp.wg.Add(1)
|
||||
@@ -146,8 +156,6 @@ func (q *WorkerPoolQueue[T]) doStartNewWorker(wp *workerGroup[T]) {
|
||||
log.Debug("Queue %q starts new worker", q.GetName())
|
||||
defer log.Debug("Queue %q stops idle worker", q.GetName())
|
||||
|
||||
atomic.AddInt32(&q.workerStartedCounter, 1) // Only increase counter, used for debugging
|
||||
|
||||
t := time.NewTicker(workerIdleDuration)
|
||||
defer t.Stop()
|
||||
|
||||
@@ -169,11 +177,7 @@ func (q *WorkerPoolQueue[T]) doStartNewWorker(wp *workerGroup[T]) {
|
||||
}
|
||||
q.doWorkerHandle(batch)
|
||||
// reset the idle ticker, and drain the tick after reset in case a tick is already triggered
|
||||
t.Reset(workerIdleDuration)
|
||||
select {
|
||||
case <-t.C:
|
||||
default:
|
||||
}
|
||||
resetIdleTicker(t, workerIdleDuration) // key code for TestWorkerPoolQueueWorkerIdleReset
|
||||
case <-t.C:
|
||||
q.workerNumMu.Lock()
|
||||
keepWorking = q.workerNum <= 1 // keep the last worker running
|
||||
|
||||
@@ -40,8 +40,6 @@ type WorkerPoolQueue[T any] struct {
|
||||
workerMaxNum int
|
||||
workerActiveNum int
|
||||
workerNumMu sync.Mutex
|
||||
|
||||
workerStartedCounter int32
|
||||
}
|
||||
|
||||
type flushType chan struct{}
|
||||
|
||||
@@ -5,8 +5,10 @@ package queue
|
||||
|
||||
import (
|
||||
"context"
|
||||
"slices"
|
||||
"strconv"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -250,22 +252,34 @@ func TestWorkerPoolQueueShutdown(t *testing.T) {
|
||||
|
||||
func TestWorkerPoolQueueWorkerIdleReset(t *testing.T) {
|
||||
defer test.MockVariableValue(&workerIdleDuration, 10*time.Millisecond)()
|
||||
defer mockBackoffDuration(5 * time.Millisecond)()
|
||||
|
||||
var q *WorkerPoolQueue[int]
|
||||
var handledCount atomic.Int32
|
||||
var hasOnlyOneWorkerRunning atomic.Bool
|
||||
handler := func(items ...int) (unhandled []int) {
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
handledCount.Add(int32(len(items)))
|
||||
// make each work have different duration, and check the active worker number periodically
|
||||
var activeNums []int
|
||||
for i := 0; i < 5-items[0]%2; i++ {
|
||||
time.Sleep(workerIdleDuration * 2)
|
||||
activeNums = append(activeNums, q.GetWorkerActiveNumber())
|
||||
}
|
||||
// When the queue never becomes empty, the existing workers should keep working
|
||||
// It is not 100% true at the moment because the data-race in workergroup.go is not resolved, see that TODO */
|
||||
// If the "active worker numbers" is like [2 2 ... 1 1], it means that an existing worker exited and the no new worker is started.
|
||||
if slices.Equal([]int{1, 1}, activeNums[len(activeNums)-2:]) {
|
||||
hasOnlyOneWorkerRunning.Store(true)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
q, _ := newWorkerPoolQueueForTest("test-workpoolqueue", setting.QueueSettings{Type: "channel", BatchLength: 1, MaxWorkers: 2, Length: 100}, handler, false)
|
||||
q, _ = newWorkerPoolQueueForTest("test-workpoolqueue", setting.QueueSettings{Type: "channel", BatchLength: 1, MaxWorkers: 2, Length: 100}, handler, false)
|
||||
stop := runWorkerPoolQueue(q)
|
||||
for i := 0; i < 20; i++ {
|
||||
for i := 0; i < 100; i++ {
|
||||
assert.NoError(t, q.Push(i))
|
||||
}
|
||||
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
assert.EqualValues(t, 2, q.GetWorkerNumber())
|
||||
assert.EqualValues(t, 2, q.GetWorkerActiveNumber())
|
||||
// when the queue never becomes empty, the existing workers should keep working
|
||||
assert.EqualValues(t, 2, q.workerStartedCounter)
|
||||
assert.Greater(t, int(handledCount.Load()), 4) // make sure there are enough items handled during the test
|
||||
assert.False(t, hasOnlyOneWorkerRunning.Load(), "a slow handler should not block other workers from starting")
|
||||
stop()
|
||||
}
|
||||
|
||||
@@ -18,6 +18,12 @@ type Store interface {
|
||||
|
||||
// RegenerateSession regenerates the underlying session and returns the new store
|
||||
func RegenerateSession(resp http.ResponseWriter, req *http.Request) (Store, error) {
|
||||
for _, f := range BeforeRegenerateSession {
|
||||
f(resp, req)
|
||||
}
|
||||
s, err := session.RegenerateSession(resp, req)
|
||||
return s, err
|
||||
}
|
||||
|
||||
// BeforeRegenerateSession is a list of functions that are called before a session is regenerated.
|
||||
var BeforeRegenerateSession []func(http.ResponseWriter, *http.Request)
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/user"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
)
|
||||
|
||||
// settings
|
||||
@@ -158,9 +159,11 @@ func loadCommonSettingsFrom(cfg ConfigProvider) error {
|
||||
func loadRunModeFrom(rootCfg ConfigProvider) {
|
||||
rootSec := rootCfg.Section("")
|
||||
RunUser = rootSec.Key("RUN_USER").MustString(user.CurrentUsername())
|
||||
|
||||
// The following is a purposefully undocumented option. Please do not run Gitea as root. It will only cause future headaches.
|
||||
// Please don't use root as a bandaid to "fix" something that is broken, instead the broken thing should instead be fixed properly.
|
||||
unsafeAllowRunAsRoot := ConfigSectionKeyBool(rootSec, "I_AM_BEING_UNSAFE_RUNNING_AS_ROOT")
|
||||
unsafeAllowRunAsRoot = unsafeAllowRunAsRoot || util.OptionalBoolParse(os.Getenv("GITEA_I_AM_BEING_UNSAFE_RUNNING_AS_ROOT")).IsTrue()
|
||||
RunMode = os.Getenv("GITEA_RUN_MODE")
|
||||
if RunMode == "" {
|
||||
RunMode = rootSec.Key("RUN_MODE").MustString("prod")
|
||||
|
||||
@@ -142,35 +142,39 @@ type remoteAddress struct {
|
||||
Password string
|
||||
}
|
||||
|
||||
func mirrorRemoteAddress(ctx context.Context, m *repo_model.Repository, remoteName string, ignoreOriginalURL bool) remoteAddress {
|
||||
a := remoteAddress{}
|
||||
|
||||
remoteURL := m.OriginalURL
|
||||
if ignoreOriginalURL || remoteURL == "" {
|
||||
var err error
|
||||
remoteURL, err = git.GetRemoteAddress(ctx, m.RepoPath(), remoteName)
|
||||
if err != nil {
|
||||
log.Error("GetRemoteURL %v", err)
|
||||
return a
|
||||
}
|
||||
func mirrorRemoteAddress(ctx context.Context, m *repo_model.Repository, remoteName string) remoteAddress {
|
||||
ret := remoteAddress{}
|
||||
remoteURL, err := git.GetRemoteAddress(ctx, m.RepoPath(), remoteName)
|
||||
if err != nil {
|
||||
log.Error("GetRemoteURL %v", err)
|
||||
return ret
|
||||
}
|
||||
|
||||
u, err := giturl.Parse(remoteURL)
|
||||
if err != nil {
|
||||
log.Error("giturl.Parse %v", err)
|
||||
return a
|
||||
return ret
|
||||
}
|
||||
|
||||
if u.Scheme != "ssh" && u.Scheme != "file" {
|
||||
if u.User != nil {
|
||||
a.Username = u.User.Username()
|
||||
a.Password, _ = u.User.Password()
|
||||
ret.Username = u.User.Username()
|
||||
ret.Password, _ = u.User.Password()
|
||||
}
|
||||
u.User = nil
|
||||
}
|
||||
a.Address = u.String()
|
||||
|
||||
return a
|
||||
// The URL stored in the git repo could contain authentication,
|
||||
// erase it, or it will be shown in the UI.
|
||||
u.User = nil
|
||||
ret.Address = u.String()
|
||||
// Why not use m.OriginalURL to set ret.Address?
|
||||
// It should be OK to use it, since m.OriginalURL should be the same as the authentication-erased URL from the Git repository.
|
||||
// However, the old code has already stored authentication in m.OriginalURL when updating mirror settings.
|
||||
// That means we need to use "giturl.Parse" for m.OriginalURL again to ensure authentication is erased.
|
||||
// Instead of doing this, why not directly use the authentication-erased URL from the Git repository?
|
||||
// It should be the same as long as there are no bugs.
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func FilenameIsImage(filename string) bool {
|
||||
|
||||
@@ -45,3 +45,12 @@ func SliceSortedEqual[T comparable](s1, s2 []T) bool {
|
||||
func SliceRemoveAll[T comparable](slice []T, target T) []T {
|
||||
return slices.DeleteFunc(slice, func(t T) bool { return t == target })
|
||||
}
|
||||
|
||||
// TODO: Replace with "maps.Keys" once available, current it only in golang.org/x/exp/maps but not in standard library
|
||||
func KeysOfMap[K comparable, V any](m map[K]V) []K {
|
||||
keys := make([]K, 0, len(m))
|
||||
for k := range m {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
return keys
|
||||
}
|
||||
|
||||
+13
-7
@@ -128,6 +128,16 @@ func hasResponseBeenWritten(argsIn []reflect.Value) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func wrapHandlerProvider[T http.Handler](hp func(next http.Handler) T, funcInfo *routing.FuncInfo) func(next http.Handler) http.Handler {
|
||||
return func(next http.Handler) http.Handler {
|
||||
h := hp(next) // this handle could be dynamically generated, so we can't use it for debug info
|
||||
return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
|
||||
routing.UpdateFuncInfo(req.Context(), funcInfo)
|
||||
h.ServeHTTP(resp, req)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// toHandlerProvider converts a handler to a handler provider
|
||||
// A handler provider is a function that takes a "next" http.Handler, it can be used as a middleware
|
||||
func toHandlerProvider(handler any) func(next http.Handler) http.Handler {
|
||||
@@ -138,13 +148,9 @@ func toHandlerProvider(handler any) func(next http.Handler) http.Handler {
|
||||
}
|
||||
|
||||
if hp, ok := handler.(func(next http.Handler) http.Handler); ok {
|
||||
return func(next http.Handler) http.Handler {
|
||||
h := hp(next) // this handle could be dynamically generated, so we can't use it for debug info
|
||||
return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
|
||||
routing.UpdateFuncInfo(req.Context(), funcInfo)
|
||||
h.ServeHTTP(resp, req)
|
||||
})
|
||||
}
|
||||
return wrapHandlerProvider(hp, funcInfo)
|
||||
} else if hp, ok := handler.(func(http.Handler) http.HandlerFunc); ok {
|
||||
return wrapHandlerProvider(hp, funcInfo)
|
||||
}
|
||||
|
||||
provider := func(next http.Handler) http.Handler {
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/session"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
)
|
||||
|
||||
@@ -45,10 +46,40 @@ func SetSiteCookie(resp http.ResponseWriter, name, value string, maxAge int) {
|
||||
SameSite: setting.SessionConfig.SameSite,
|
||||
}
|
||||
resp.Header().Add("Set-Cookie", cookie.String())
|
||||
if maxAge < 0 {
|
||||
// There was a bug in "setting.SessionConfig.CookiePath" code, the old default value of it was empty "".
|
||||
// So we have to delete the cookie on path="" again, because some old code leaves cookies on path="".
|
||||
cookie.Path = strings.TrimSuffix(setting.SessionConfig.CookiePath, "/")
|
||||
resp.Header().Add("Set-Cookie", cookie.String())
|
||||
}
|
||||
// Previous versions would use a cookie path with a trailing /.
|
||||
// These are more specific than cookies without a trailing /, so
|
||||
// we need to delete these if they exist.
|
||||
deleteLegacySiteCookie(resp, name)
|
||||
}
|
||||
|
||||
// deleteLegacySiteCookie deletes the cookie with the given name at the cookie
|
||||
// path with a trailing /, which would unintentionally override the cookie.
|
||||
func deleteLegacySiteCookie(resp http.ResponseWriter, name string) {
|
||||
if setting.SessionConfig.CookiePath == "" || strings.HasSuffix(setting.SessionConfig.CookiePath, "/") {
|
||||
// If the cookie path ends with /, no legacy cookies will take
|
||||
// precedence, so do nothing. The exception is that cookies with no
|
||||
// path could override other cookies, but it's complicated and we don't
|
||||
// currently handle that.
|
||||
return
|
||||
}
|
||||
|
||||
cookie := &http.Cookie{
|
||||
Name: name,
|
||||
Value: "",
|
||||
MaxAge: -1,
|
||||
Path: setting.SessionConfig.CookiePath + "/",
|
||||
Domain: setting.SessionConfig.Domain,
|
||||
Secure: setting.SessionConfig.Secure,
|
||||
HttpOnly: true,
|
||||
SameSite: setting.SessionConfig.SameSite,
|
||||
}
|
||||
resp.Header().Add("Set-Cookie", cookie.String())
|
||||
}
|
||||
|
||||
func init() {
|
||||
session.BeforeRegenerateSession = append(session.BeforeRegenerateSession, func(resp http.ResponseWriter, _ *http.Request) {
|
||||
// Ensure that a cookie with a trailing slash does not take precedence over
|
||||
// the cookie written by the middleware.
|
||||
deleteLegacySiteCookie(resp, setting.SessionConfig.CookieName)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1247,6 +1247,8 @@ editor.file_editing_no_longer_exists = The file being edited, "%s", no longer ex
|
||||
editor.file_deleting_no_longer_exists = The file being deleted, "%s", no longer exists in this repository.
|
||||
editor.file_changed_while_editing = The file contents have changed since you started editing. <a target="_blank" rel="noopener noreferrer" href="%s">Click here</a> to see them or <strong>Commit Changes again</strong> to overwrite them.
|
||||
editor.file_already_exists = A file named "%s" already exists in this repository.
|
||||
editor.commit_id_not_matching = The Commit ID does not match the ID when you began editing. Commit into a patch branch and then merge.
|
||||
editor.push_out_of_date = The push appears to be out of date.
|
||||
editor.commit_empty_file_header = Commit an empty file
|
||||
editor.commit_empty_file_text = The file you're about to commit is empty. Proceed?
|
||||
editor.no_changes_to_show = There are no changes to show.
|
||||
@@ -3076,7 +3078,6 @@ config.enable_openid_signin = Enable OpenID Sign-In
|
||||
config.show_registration_button = Show Register Button
|
||||
config.require_sign_in_view = Require Sign-In to View Pages
|
||||
config.mail_notify = Enable Email Notifications
|
||||
config.disable_key_size_check = Disable Minimum Key Size Check
|
||||
config.enable_captcha = Enable CAPTCHA
|
||||
config.active_code_lives = Active Code Lives
|
||||
config.reset_password_code_lives = Recover Account Code Expiry Time
|
||||
@@ -3527,6 +3528,7 @@ runs.scheduled = Scheduled
|
||||
runs.pushed_by = pushed by
|
||||
runs.invalid_workflow_helper = Workflow config file is invalid. Please check your config file: %s
|
||||
runs.no_matching_online_runner_helper = No matching online runner with label: %s
|
||||
runs.no_job_without_needs = The workflow must contain at least one job without dependencies.
|
||||
runs.actor = Actor
|
||||
runs.status = Status
|
||||
runs.actors_no_select = All actors
|
||||
|
||||
Generated
+82
-100
@@ -27,10 +27,10 @@
|
||||
"escape-goat": "4.0.0",
|
||||
"fast-glob": "3.3.1",
|
||||
"jquery": "3.7.1",
|
||||
"katex": "0.16.9",
|
||||
"katex": "0.16.10",
|
||||
"license-checker-webpack-plugin": "0.2.1",
|
||||
"lightningcss-loader": "2.1.0",
|
||||
"mermaid": "10.6.1",
|
||||
"mermaid": "10.9.0",
|
||||
"mini-css-extract-plugin": "2.7.6",
|
||||
"minimatch": "9.0.3",
|
||||
"monaco-editor": "0.44.0",
|
||||
@@ -39,6 +39,7 @@
|
||||
"pretty-ms": "8.0.0",
|
||||
"sortablejs": "1.15.0",
|
||||
"swagger-ui-dist": "5.9.0",
|
||||
"temporal-polyfill": "0.2.3",
|
||||
"throttle-debounce": "5.0.0",
|
||||
"tinycolor2": "1.6.0",
|
||||
"tippy.js": "6.3.7",
|
||||
@@ -1903,27 +1904,27 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@types/d3-scale": {
|
||||
"version": "4.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.5.tgz",
|
||||
"integrity": "sha512-w/C++3W394MHzcLKO2kdsIn5KKNTOqeQVzyPSGPLzQbkPw/jpeaGtSRlakcKevGgGsjJxGsbqS0fPrVFDbHrDA==",
|
||||
"version": "4.0.8",
|
||||
"resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.8.tgz",
|
||||
"integrity": "sha512-gkK1VVTr5iNiYJ7vWDI+yUFFlszhNMtVeneJ6lUTKPjprsvLLI9/tgEGiXJOnlINJA8FyA88gfnQsHbybVZrYQ==",
|
||||
"dependencies": {
|
||||
"@types/d3-time": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/d3-scale-chromatic": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.0.0.tgz",
|
||||
"integrity": "sha512-dsoJGEIShosKVRBZB0Vo3C8nqSDqVGujJU6tPznsBJxNJNwMF8utmS83nvCBKQYPpjCzaaHcrf66iTRpZosLPw=="
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.0.3.tgz",
|
||||
"integrity": "sha512-laXM4+1o5ImZv3RpFAsTRn3TEkzqkytiOY0Dz0sq5cnd1dtNlk6sHLon4OvqaiJb28T0S/TdsBI3Sjsy+keJrw=="
|
||||
},
|
||||
"node_modules/@types/d3-time": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.1.tgz",
|
||||
"integrity": "sha512-5j/AnefKAhCw4HpITmLDTPlf4vhi8o/dES+zbegfPb7LaGfNyqkLxBR6E+4yvTAgnJLmhe80EXFMzUs38fw4oA=="
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.3.tgz",
|
||||
"integrity": "sha512-2p6olUZ4w3s+07q3Tm2dbiMZy5pCDfYwtLXXHUnVzXgQlZ/OyPtUz6OL382BkOuGlLXqfT+wqv8Fw2v8/0geBw=="
|
||||
},
|
||||
"node_modules/@types/debug": {
|
||||
"version": "4.1.9",
|
||||
"resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.9.tgz",
|
||||
"integrity": "sha512-8Hz50m2eoS56ldRlepxSBa6PWEVCtzUo/92HgLc2qTMnotJNIm7xP+UZhyWoYsyOdd5dxZ+NZLb24rsKyFs2ow==",
|
||||
"version": "4.1.12",
|
||||
"resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz",
|
||||
"integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==",
|
||||
"dependencies": {
|
||||
"@types/ms": "*"
|
||||
}
|
||||
@@ -1977,9 +1978,9 @@
|
||||
"integrity": "sha512-a79Yc3TOk6dGdituy8hmTTJXjOkZ7zsFYV10L337ttq/rec8lRMDBpV7fL3uLx6TgbFCa5DU/h8FmIBQPSbU0w=="
|
||||
},
|
||||
"node_modules/@types/mdast": {
|
||||
"version": "3.0.13",
|
||||
"resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.13.tgz",
|
||||
"integrity": "sha512-HjiGiWedR0DVFkeNljpa6Lv4/IZU1+30VY5d747K7lBudFc3R0Ibr6yJ9lN3BE28VnZyDfLF/VB1Ql1ZIbKrmg==",
|
||||
"version": "3.0.15",
|
||||
"resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.15.tgz",
|
||||
"integrity": "sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==",
|
||||
"dependencies": {
|
||||
"@types/unist": "^2"
|
||||
}
|
||||
@@ -1991,9 +1992,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/ms": {
|
||||
"version": "0.7.32",
|
||||
"resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.32.tgz",
|
||||
"integrity": "sha512-xPSg0jm4mqgEkNhowKgZFBNtwoEwF6gJ4Dhww+GFpm3IgtNseHQZ5IqdNwnquZEoANxyDAKDRAdVo4Z72VvD/g=="
|
||||
"version": "0.7.34",
|
||||
"resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.34.tgz",
|
||||
"integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g=="
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "20.8.3",
|
||||
@@ -2021,9 +2022,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@types/unist": {
|
||||
"version": "2.0.8",
|
||||
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.8.tgz",
|
||||
"integrity": "sha512-d0XxK3YTObnWVp6rZuev3c49+j4Lo8g4L1ZRm9z5L0xpoZycUPshHgczK5gsUMaZOstjVYYi09p5gYvUtfChYw=="
|
||||
"version": "2.0.10",
|
||||
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz",
|
||||
"integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA=="
|
||||
},
|
||||
"node_modules/@types/urijs": {
|
||||
"version": "1.19.20",
|
||||
@@ -3557,13 +3558,9 @@
|
||||
"integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ=="
|
||||
},
|
||||
"node_modules/cytoscape": {
|
||||
"version": "3.26.0",
|
||||
"resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.26.0.tgz",
|
||||
"integrity": "sha512-IV+crL+KBcrCnVVUCZW+zRRRFUZQcrtdOPXki+o4CFUWLdAEYvuZLcBSJC9EBK++suamERKzeY7roq2hdovV3w==",
|
||||
"dependencies": {
|
||||
"heap": "^0.2.6",
|
||||
"lodash": "^4.17.21"
|
||||
},
|
||||
"version": "3.29.2",
|
||||
"resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.29.2.tgz",
|
||||
"integrity": "sha512-2G1ycU28Nh7OHT9rkXRLpCDP30MKH1dXJORZuBhtEhEW7pKwgPi77ImqlCWinouyE1PNepIOGZBOrE84DG7LyQ==",
|
||||
"engines": {
|
||||
"node": ">=0.10"
|
||||
}
|
||||
@@ -3579,34 +3576,10 @@
|
||||
"cytoscape": "^3.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/cytoscape-fcose": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/cytoscape-fcose/-/cytoscape-fcose-2.2.0.tgz",
|
||||
"integrity": "sha512-ki1/VuRIHFCzxWNrsshHYPs6L7TvLu3DL+TyIGEsRcvVERmxokbf5Gdk7mFxZnTdiGtnA4cfSmjZJMviqSuZrQ==",
|
||||
"dependencies": {
|
||||
"cose-base": "^2.2.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"cytoscape": "^3.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/cytoscape-fcose/node_modules/cose-base": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/cose-base/-/cose-base-2.2.0.tgz",
|
||||
"integrity": "sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g==",
|
||||
"dependencies": {
|
||||
"layout-base": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/cytoscape-fcose/node_modules/layout-base": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/layout-base/-/layout-base-2.0.1.tgz",
|
||||
"integrity": "sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg=="
|
||||
},
|
||||
"node_modules/d3": {
|
||||
"version": "7.8.5",
|
||||
"resolved": "https://registry.npmjs.org/d3/-/d3-7.8.5.tgz",
|
||||
"integrity": "sha512-JgoahDG51ncUfJu6wX/1vWQEqOflgXyl4MaHqlcSruTez7yhaRKR9i8VjjcQGeS2en/jnFivXuaIMnseMMt0XA==",
|
||||
"version": "7.9.0",
|
||||
"resolved": "https://registry.npmjs.org/d3/-/d3-7.9.0.tgz",
|
||||
"integrity": "sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==",
|
||||
"dependencies": {
|
||||
"d3-array": "3",
|
||||
"d3-axis": "3",
|
||||
@@ -3811,9 +3784,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/d3-geo": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.0.tgz",
|
||||
"integrity": "sha512-JEo5HxXDdDYXCaWdwLRt79y7giK8SbhZJbFWXqbRTolCHFI5jRqteLzCsq51NKbUoX0PjBVSohxrx+NoOUujYA==",
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.1.tgz",
|
||||
"integrity": "sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==",
|
||||
"dependencies": {
|
||||
"d3-array": "2.5.0 - 3"
|
||||
},
|
||||
@@ -3923,9 +3896,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/d3-scale-chromatic": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.0.0.tgz",
|
||||
"integrity": "sha512-Lx9thtxAKrO2Pq6OO2Ua474opeziKr279P/TKZsMAhYyNDD3EnCffdbgeSYN5O7m2ByQsxtuP2CSDczNUIZ22g==",
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz",
|
||||
"integrity": "sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==",
|
||||
"dependencies": {
|
||||
"d3-color": "1 - 3",
|
||||
"d3-interpolate": "1 - 3"
|
||||
@@ -4198,11 +4171,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/delaunator": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.0.tgz",
|
||||
"integrity": "sha512-AyLvtyJdbv/U1GkiS6gUUzclRoAY4Gs75qkMygJJhU75LW4DNuSF2RMzpxs9jw9Oz1BobHjTdkG3zdP55VxAqw==",
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.1.tgz",
|
||||
"integrity": "sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==",
|
||||
"dependencies": {
|
||||
"robust-predicates": "^3.0.0"
|
||||
"robust-predicates": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/delayed-stream": {
|
||||
@@ -4243,9 +4216,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/diff": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz",
|
||||
"integrity": "sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==",
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz",
|
||||
"integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==",
|
||||
"engines": {
|
||||
"node": ">=0.3.1"
|
||||
}
|
||||
@@ -4349,9 +4322,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/dompurify": {
|
||||
"version": "3.0.6",
|
||||
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.0.6.tgz",
|
||||
"integrity": "sha512-ilkD8YEnnGh1zJ240uJsW7AzE+2qpbOUYjacomn3AvJ6J4JhKGSZ2nh4wUIXPZrEPppaCLx5jFe8T89Rk8tQ7w=="
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.1.0.tgz",
|
||||
"integrity": "sha512-yoU4rhgPKCo+p5UrWWWNKiIq+ToGqmVVhk0PmMYBK4kRsR3/qhemNFL8f6CFmBd4gMwm3F4T7HBoydP5uY07fA=="
|
||||
},
|
||||
"node_modules/domutils": {
|
||||
"version": "3.1.0",
|
||||
@@ -4399,9 +4372,9 @@
|
||||
"integrity": "sha512-54z7squS1FyFRSUqq/knOFSptjjogLZXbKcYk3B0qkE1KZzvqASwRZnY2KzZQJqIYLVD38XZeoiMRflYSwyO4w=="
|
||||
},
|
||||
"node_modules/elkjs": {
|
||||
"version": "0.8.2",
|
||||
"resolved": "https://registry.npmjs.org/elkjs/-/elkjs-0.8.2.tgz",
|
||||
"integrity": "sha512-L6uRgvZTH+4OF5NE/MBbzQx/WYpru1xCBE9respNj6qznEewGUIfhzmm7horWWxbNO2M0WckQypGctR8lH79xQ=="
|
||||
"version": "0.9.3",
|
||||
"resolved": "https://registry.npmjs.org/elkjs/-/elkjs-0.9.3.tgz",
|
||||
"integrity": "sha512-f/ZeWvW/BCXbhGEf1Ujp29EASo/lk1FDnETgNKwJrsVvGZhUWCZyg3xLJjAsxfOmt8KjswHmI5EwCQcPMpOYhQ=="
|
||||
},
|
||||
"node_modules/emoji-regex": {
|
||||
"version": "8.0.0",
|
||||
@@ -5861,11 +5834,6 @@
|
||||
"resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-2.0.0.tgz",
|
||||
"integrity": "sha512-WdZTbAByD+pHfl/g9QSsBIIwy8IT+EsPiKDs0KNX+zSHhdDLFKdZu0BQHljvO+0QI/BasbMSUa8wYNCZTvhslg=="
|
||||
},
|
||||
"node_modules/heap": {
|
||||
"version": "0.2.7",
|
||||
"resolved": "https://registry.npmjs.org/heap/-/heap-0.2.7.tgz",
|
||||
"integrity": "sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg=="
|
||||
},
|
||||
"node_modules/hosted-git-info": {
|
||||
"version": "2.8.9",
|
||||
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
|
||||
@@ -6726,9 +6694,9 @@
|
||||
"integrity": "sha512-b+z6yF1d4EOyDgylzQo5IminlUmzSeqR1hs/bzjBNjuGras4FXq/6TrzjxfN0j+TmI0ltJzTNlqXUMCniciwKQ=="
|
||||
},
|
||||
"node_modules/katex": {
|
||||
"version": "0.16.9",
|
||||
"resolved": "https://registry.npmjs.org/katex/-/katex-0.16.9.tgz",
|
||||
"integrity": "sha512-fsSYjWS0EEOwvy81j3vRA8TEAhQhKiqO+FQaKWp0m39qwOzHVBgAUBIXWj1pB+O2W3fIpNa6Y9KSKCVbfPhyAQ==",
|
||||
"version": "0.16.10",
|
||||
"resolved": "https://registry.npmjs.org/katex/-/katex-0.16.10.tgz",
|
||||
"integrity": "sha512-ZiqaC04tp2O5utMsl2TEZTXxa6WSC4yo0fv5ML++D3QZv/vx2Mct0mTlRx3O+uUkjfuAgOkzsCmq5MiUEsDDdA==",
|
||||
"funding": [
|
||||
"https://opencollective.com/katex",
|
||||
"https://github.com/sponsors/katex"
|
||||
@@ -6750,9 +6718,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/khroma": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/khroma/-/khroma-2.0.0.tgz",
|
||||
"integrity": "sha512-2J8rDNlQWbtiNYThZRvmMv5yt44ZakX+Tz5ZIp/mN1pt4snn+m030Va5Z4v8xA0cQFDXBwO/8i42xL4QPsVk3g=="
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/khroma/-/khroma-2.1.0.tgz",
|
||||
"integrity": "sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw=="
|
||||
},
|
||||
"node_modules/kind-of": {
|
||||
"version": "6.0.3",
|
||||
@@ -7147,7 +7115,8 @@
|
||||
"node_modules/lodash": {
|
||||
"version": "4.17.21",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
|
||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/lodash-es": {
|
||||
"version": "4.17.21",
|
||||
@@ -7530,22 +7499,22 @@
|
||||
}
|
||||
},
|
||||
"node_modules/mermaid": {
|
||||
"version": "10.6.1",
|
||||
"resolved": "https://registry.npmmirror.com/mermaid/-/mermaid-10.6.1.tgz",
|
||||
"integrity": "sha512-Hky0/RpOw/1il9X8AvzOEChfJtVvmXm+y7JML5C//ePYMy0/9jCEmW1E1g86x9oDfW9+iVEdTV/i+M6KWRNs4A==",
|
||||
"version": "10.9.0",
|
||||
"resolved": "https://registry.npmjs.org/mermaid/-/mermaid-10.9.0.tgz",
|
||||
"integrity": "sha512-swZju0hFox/B/qoLKK0rOxxgh8Cf7rJSfAUc1u8fezVihYMvrJAS45GzAxTVf4Q+xn9uMgitBcmWk7nWGXOs/g==",
|
||||
"dependencies": {
|
||||
"@braintree/sanitize-url": "^6.0.1",
|
||||
"@types/d3-scale": "^4.0.3",
|
||||
"@types/d3-scale-chromatic": "^3.0.0",
|
||||
"cytoscape": "^3.23.0",
|
||||
"cytoscape": "^3.28.1",
|
||||
"cytoscape-cose-bilkent": "^4.1.0",
|
||||
"cytoscape-fcose": "^2.1.0",
|
||||
"d3": "^7.4.0",
|
||||
"d3-sankey": "^0.12.3",
|
||||
"dagre-d3-es": "7.0.10",
|
||||
"dayjs": "^1.11.7",
|
||||
"dompurify": "^3.0.5",
|
||||
"elkjs": "^0.8.2",
|
||||
"elkjs": "^0.9.0",
|
||||
"katex": "^0.16.9",
|
||||
"khroma": "^2.0.0",
|
||||
"lodash-es": "^4.17.21",
|
||||
"mdast-util-from-markdown": "^1.3.0",
|
||||
@@ -10151,9 +10120,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/stylis": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.0.tgz",
|
||||
"integrity": "sha512-E87pIogpwUsUwXw7dNyU4QDjdgVMy52m+XEOPEKUn161cCzWjjhPSQhByfd1CcNvrOLnXQ6OnnZDwnJrz/Z4YQ=="
|
||||
"version": "4.3.2",
|
||||
"resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.2.tgz",
|
||||
"integrity": "sha512-bhtUjWd/z6ltJiQwg0dUfxEJ+W+jdqQd8TbWLWyeIJHlnsqmGLRFFd8e5mA0AZi/zx90smXRlN66YMTcaSFifg=="
|
||||
},
|
||||
"node_modules/stylus": {
|
||||
"version": "0.57.0",
|
||||
@@ -10310,6 +10279,19 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/temporal-polyfill": {
|
||||
"version": "0.2.3",
|
||||
"resolved": "https://registry.npmjs.org/temporal-polyfill/-/temporal-polyfill-0.2.3.tgz",
|
||||
"integrity": "sha512-7ZJRc7wq/1XjrOQYkkNpgo2qfE9XLrUU8D/DS+LAC/T0bYqZ46rW6dow0sOTXTPZS4bwer8bD/0OyuKQBfA3yw==",
|
||||
"dependencies": {
|
||||
"temporal-spec": "^0.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/temporal-spec": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/temporal-spec/-/temporal-spec-0.2.0.tgz",
|
||||
"integrity": "sha512-r1AT0XdEp8TMQ13FLvOt8mOtAxDQsRt2QU5rSWCA7YfshddU651Y1NHVrceLANvixKdf9fYO8B/S9fXHodB7HQ=="
|
||||
},
|
||||
"node_modules/terser": {
|
||||
"version": "5.21.0",
|
||||
"resolved": "https://registry.npmjs.org/terser/-/terser-5.21.0.tgz",
|
||||
@@ -11535,9 +11517,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/web-worker": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/web-worker/-/web-worker-1.2.0.tgz",
|
||||
"integrity": "sha512-PgF341avzqyx60neE9DD+XS26MMNMoUQRz9NOZwW32nPQrF6p77f1htcnjBSEV8BGMKZ16choqUG4hyI0Hx7mA=="
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/web-worker/-/web-worker-1.3.0.tgz",
|
||||
"integrity": "sha512-BSR9wyRsy/KOValMgd5kMyr3JzpdeoR9KVId8u5GVlTTAtNChlsE4yTxeY7zMdNSyOmoKBv8NH2qeRY9Tg+IaA=="
|
||||
},
|
||||
"node_modules/webidl-conversions": {
|
||||
"version": "7.0.0",
|
||||
|
||||
+3
-2
@@ -26,10 +26,10 @@
|
||||
"escape-goat": "4.0.0",
|
||||
"fast-glob": "3.3.1",
|
||||
"jquery": "3.7.1",
|
||||
"katex": "0.16.9",
|
||||
"katex": "0.16.10",
|
||||
"license-checker-webpack-plugin": "0.2.1",
|
||||
"lightningcss-loader": "2.1.0",
|
||||
"mermaid": "10.6.1",
|
||||
"mermaid": "10.9.0",
|
||||
"mini-css-extract-plugin": "2.7.6",
|
||||
"minimatch": "9.0.3",
|
||||
"monaco-editor": "0.44.0",
|
||||
@@ -38,6 +38,7 @@
|
||||
"pretty-ms": "8.0.0",
|
||||
"sortablejs": "1.15.0",
|
||||
"swagger-ui-dist": "5.9.0",
|
||||
"temporal-polyfill": "0.2.3",
|
||||
"throttle-debounce": "5.0.0",
|
||||
"tinycolor2": "1.6.0",
|
||||
"tippy.js": "6.3.7",
|
||||
|
||||
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640" style="enable-background:new 0 0 640 640" xml:space="preserve" width="32" height="32"><path style="fill:#fff" d="m395.9 484.2-126.9-61c-12.5-6-17.9-21.2-11.8-33.8l61-126.9c6-12.5 21.2-17.9 33.8-11.8 17.2 8.3 27.1 13 27.1 13l-.1-109.2 16.7-.1.1 117.1s57.4 24.2 83.1 40.1c3.7 2.3 10.2 6.8 12.9 14.4 2.1 6.1 2 13.1-1 19.3l-61 126.9c-6.2 12.7-21.4 18.1-33.9 12z"/><path style="fill:#609926" d="M622.7 149.8c-4.1-4.1-9.6-4-9.6-4s-117.2 6.6-177.9 8c-13.3.3-26.5.6-39.6.7v117.2c-5.5-2.6-11.1-5.3-16.6-7.9 0-36.4-.1-109.2-.1-109.2-29 .4-89.2-2.2-89.2-2.2s-141.4-7.1-156.8-8.5c-9.8-.6-22.5-2.1-39 1.5-8.7 1.8-33.5 7.4-53.8 26.9C-4.9 212.4 6.6 276.2 8 285.8c1.7 11.7 6.9 44.2 31.7 72.5 45.8 56.1 144.4 54.8 144.4 54.8s12.1 28.9 30.6 55.5c25 33.1 50.7 58.9 75.7 62 63 0 188.9-.1 188.9-.1s12 .1 28.3-10.3c14-8.5 26.5-23.4 26.5-23.4S547 483 565 451.5c5.5-9.7 10.1-19.1 14.1-28 0 0 55.2-117.1 55.2-231.1-1.1-34.5-9.6-40.6-11.6-42.6zM125.6 353.9c-25.9-8.5-36.9-18.7-36.9-18.7S69.6 321.8 60 295.4c-16.5-44.2-1.4-71.2-1.4-71.2s8.4-22.5 38.5-30c13.8-3.7 31-3.1 31-3.1s7.1 59.4 15.7 94.2c7.2 29.2 24.8 77.7 24.8 77.7s-26.1-3.1-43-9.1zm300.3 107.6s-6.1 14.5-19.6 15.4c-5.8.4-10.3-1.2-10.3-1.2s-.3-.1-5.3-2.1l-112.9-55s-10.9-5.7-12.8-15.6c-2.2-8.1 2.7-18.1 2.7-18.1L322 273s4.8-9.7 12.2-13c.6-.3 2.3-1 4.5-1.5 8.1-2.1 18 2.8 18 2.8L467.4 315s12.6 5.7 15.3 16.2c1.9 7.4-.5 14-1.8 17.2-6.3 15.4-55 113.1-55 113.1z"/><path style="fill:#609926" d="M326.8 380.1c-8.2.1-15.4 5.8-17.3 13.8-1.9 8 2 16.3 9.1 20 7.7 4 17.5 1.8 22.7-5.4 5.1-7.1 4.3-16.9-1.8-23.1l24-49.1c1.5.1 3.7.2 6.2-.5 4.1-.9 7.1-3.6 7.1-3.6 4.2 1.8 8.6 3.8 13.2 6.1 4.8 2.4 9.3 4.9 13.4 7.3.9.5 1.8 1.1 2.8 1.9 1.6 1.3 3.4 3.1 4.7 5.5 1.9 5.5-1.9 14.9-1.9 14.9-2.3 7.6-18.4 40.6-18.4 40.6-8.1-.2-15.3 5-17.7 12.5-2.6 8.1 1.1 17.3 8.9 21.3 7.8 4 17.4 1.7 22.5-5.3 5-6.8 4.6-16.3-1.1-22.6 1.9-3.7 3.7-7.4 5.6-11.3 5-10.4 13.5-30.4 13.5-30.4.9-1.7 5.7-10.3 2.7-21.3-2.5-11.4-12.6-16.7-12.6-16.7-12.2-7.9-29.2-15.2-29.2-15.2s0-4.1-1.1-7.1c-1.1-3.1-2.8-5.1-3.9-6.3 4.7-9.7 9.4-19.3 14.1-29-4.1-2-8.1-4-12.2-6.1-4.8 9.8-9.7 19.7-14.5 29.5-6.7-.1-12.9 3.5-16.1 9.4-3.4 6.3-2.7 14.1 1.9 19.8l-24.6 50.4z"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" style="enable-background:new 0 0 640 640" viewBox="0 0 640 640" width="32" height="32"><path d="m395.9 484.2-126.9-61c-12.5-6-17.9-21.2-11.8-33.8l61-126.9c6-12.5 21.2-17.9 33.8-11.8 17.2 8.3 27.1 13 27.1 13l-.1-109.2 16.7-.1.1 117.1s57.4 24.2 83.1 40.1c3.7 2.3 10.2 6.8 12.9 14.4 2.1 6.1 2 13.1-1 19.3l-61 126.9c-6.2 12.7-21.4 18.1-33.9 12z" style="fill:#fff"/><path d="M622.7 149.8c-4.1-4.1-9.6-4-9.6-4s-117.2 6.6-177.9 8c-13.3.3-26.5.6-39.6.7v117.2c-5.5-2.6-11.1-5.3-16.6-7.9 0-36.4-.1-109.2-.1-109.2-29 .4-89.2-2.2-89.2-2.2s-141.4-7.1-156.8-8.5c-9.8-.6-22.5-2.1-39 1.5-8.7 1.8-33.5 7.4-53.8 26.9C-4.9 212.4 6.6 276.2 8 285.8c1.7 11.7 6.9 44.2 31.7 72.5 45.8 56.1 144.4 54.8 144.4 54.8s12.1 28.9 30.6 55.5c25 33.1 50.7 58.9 75.7 62 63 0 188.9-.1 188.9-.1s12 .1 28.3-10.3c14-8.5 26.5-23.4 26.5-23.4S547 483 565 451.5c5.5-9.7 10.1-19.1 14.1-28 0 0 55.2-117.1 55.2-231.1-1.1-34.5-9.6-40.6-11.6-42.6zM125.6 353.9c-25.9-8.5-36.9-18.7-36.9-18.7S69.6 321.8 60 295.4c-16.5-44.2-1.4-71.2-1.4-71.2s8.4-22.5 38.5-30c13.8-3.7 31-3.1 31-3.1s7.1 59.4 15.7 94.2c7.2 29.2 24.8 77.7 24.8 77.7s-26.1-3.1-43-9.1zm300.3 107.6s-6.1 14.5-19.6 15.4c-5.8.4-10.3-1.2-10.3-1.2s-.3-.1-5.3-2.1l-112.9-55s-10.9-5.7-12.8-15.6c-2.2-8.1 2.7-18.1 2.7-18.1L322 273s4.8-9.7 12.2-13c.6-.3 2.3-1 4.5-1.5 8.1-2.1 18 2.8 18 2.8L467.4 315s12.6 5.7 15.3 16.2c1.9 7.4-.5 14-1.8 17.2-6.3 15.4-55 113.1-55 113.1z" style="fill:#609926"/><path d="M326.8 380.1c-8.2.1-15.4 5.8-17.3 13.8-1.9 8 2 16.3 9.1 20 7.7 4 17.5 1.8 22.7-5.4 5.1-7.1 4.3-16.9-1.8-23.1l24-49.1c1.5.1 3.7.2 6.2-.5 4.1-.9 7.1-3.6 7.1-3.6 4.2 1.8 8.6 3.8 13.2 6.1 4.8 2.4 9.3 4.9 13.4 7.3.9.5 1.8 1.1 2.8 1.9 1.6 1.3 3.4 3.1 4.7 5.5 1.9 5.5-1.9 14.9-1.9 14.9-2.3 7.6-18.4 40.6-18.4 40.6-8.1-.2-15.3 5-17.7 12.5-2.6 8.1 1.1 17.3 8.9 21.3 7.8 4 17.4 1.7 22.5-5.3 5-6.8 4.6-16.3-1.1-22.6 1.9-3.7 3.7-7.4 5.6-11.3 5-10.4 13.5-30.4 13.5-30.4.9-1.7 5.7-10.3 2.7-21.3-2.5-11.4-12.6-16.7-12.6-16.7-12.2-7.9-29.2-15.2-29.2-15.2s0-4.1-1.1-7.1c-1.1-3.1-2.8-5.1-3.9-6.3 4.7-9.7 9.4-19.3 14.1-29-4.1-2-8.1-4-12.2-6.1-4.8 9.8-9.7 19.7-14.5 29.5-6.7-.1-12.9 3.5-16.1 9.4-3.4 6.3-2.7 14.1 1.9 19.8l-24.6 50.4z" style="fill:#609926"/></svg>
|
||||
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640" style="enable-background:new 0 0 640 640" xml:space="preserve" width="32" height="32"><path style="fill:#fff" d="m395.9 484.2-126.9-61c-12.5-6-17.9-21.2-11.8-33.8l61-126.9c6-12.5 21.2-17.9 33.8-11.8 17.2 8.3 27.1 13 27.1 13l-.1-109.2 16.7-.1.1 117.1s57.4 24.2 83.1 40.1c3.7 2.3 10.2 6.8 12.9 14.4 2.1 6.1 2 13.1-1 19.3l-61 126.9c-6.2 12.7-21.4 18.1-33.9 12z"/><path style="fill:#609926" d="M622.7 149.8c-4.1-4.1-9.6-4-9.6-4s-117.2 6.6-177.9 8c-13.3.3-26.5.6-39.6.7v117.2c-5.5-2.6-11.1-5.3-16.6-7.9 0-36.4-.1-109.2-.1-109.2-29 .4-89.2-2.2-89.2-2.2s-141.4-7.1-156.8-8.5c-9.8-.6-22.5-2.1-39 1.5-8.7 1.8-33.5 7.4-53.8 26.9C-4.9 212.4 6.6 276.2 8 285.8c1.7 11.7 6.9 44.2 31.7 72.5 45.8 56.1 144.4 54.8 144.4 54.8s12.1 28.9 30.6 55.5c25 33.1 50.7 58.9 75.7 62 63 0 188.9-.1 188.9-.1s12 .1 28.3-10.3c14-8.5 26.5-23.4 26.5-23.4S547 483 565 451.5c5.5-9.7 10.1-19.1 14.1-28 0 0 55.2-117.1 55.2-231.1-1.1-34.5-9.6-40.6-11.6-42.6zM125.6 353.9c-25.9-8.5-36.9-18.7-36.9-18.7S69.6 321.8 60 295.4c-16.5-44.2-1.4-71.2-1.4-71.2s8.4-22.5 38.5-30c13.8-3.7 31-3.1 31-3.1s7.1 59.4 15.7 94.2c7.2 29.2 24.8 77.7 24.8 77.7s-26.1-3.1-43-9.1zm300.3 107.6s-6.1 14.5-19.6 15.4c-5.8.4-10.3-1.2-10.3-1.2s-.3-.1-5.3-2.1l-112.9-55s-10.9-5.7-12.8-15.6c-2.2-8.1 2.7-18.1 2.7-18.1L322 273s4.8-9.7 12.2-13c.6-.3 2.3-1 4.5-1.5 8.1-2.1 18 2.8 18 2.8L467.4 315s12.6 5.7 15.3 16.2c1.9 7.4-.5 14-1.8 17.2-6.3 15.4-55 113.1-55 113.1z"/><path style="fill:#609926" d="M326.8 380.1c-8.2.1-15.4 5.8-17.3 13.8-1.9 8 2 16.3 9.1 20 7.7 4 17.5 1.8 22.7-5.4 5.1-7.1 4.3-16.9-1.8-23.1l24-49.1c1.5.1 3.7.2 6.2-.5 4.1-.9 7.1-3.6 7.1-3.6 4.2 1.8 8.6 3.8 13.2 6.1 4.8 2.4 9.3 4.9 13.4 7.3.9.5 1.8 1.1 2.8 1.9 1.6 1.3 3.4 3.1 4.7 5.5 1.9 5.5-1.9 14.9-1.9 14.9-2.3 7.6-18.4 40.6-18.4 40.6-8.1-.2-15.3 5-17.7 12.5-2.6 8.1 1.1 17.3 8.9 21.3 7.8 4 17.4 1.7 22.5-5.3 5-6.8 4.6-16.3-1.1-22.6 1.9-3.7 3.7-7.4 5.6-11.3 5-10.4 13.5-30.4 13.5-30.4.9-1.7 5.7-10.3 2.7-21.3-2.5-11.4-12.6-16.7-12.6-16.7-12.2-7.9-29.2-15.2-29.2-15.2s0-4.1-1.1-7.1c-1.1-3.1-2.8-5.1-3.9-6.3 4.7-9.7 9.4-19.3 14.1-29-4.1-2-8.1-4-12.2-6.1-4.8 9.8-9.7 19.7-14.5 29.5-6.7-.1-12.9 3.5-16.1 9.4-3.4 6.3-2.7 14.1 1.9 19.8l-24.6 50.4z"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" style="enable-background:new 0 0 640 640" viewBox="0 0 640 640" width="32" height="32"><path d="m395.9 484.2-126.9-61c-12.5-6-17.9-21.2-11.8-33.8l61-126.9c6-12.5 21.2-17.9 33.8-11.8 17.2 8.3 27.1 13 27.1 13l-.1-109.2 16.7-.1.1 117.1s57.4 24.2 83.1 40.1c3.7 2.3 10.2 6.8 12.9 14.4 2.1 6.1 2 13.1-1 19.3l-61 126.9c-6.2 12.7-21.4 18.1-33.9 12z" style="fill:#fff"/><path d="M622.7 149.8c-4.1-4.1-9.6-4-9.6-4s-117.2 6.6-177.9 8c-13.3.3-26.5.6-39.6.7v117.2c-5.5-2.6-11.1-5.3-16.6-7.9 0-36.4-.1-109.2-.1-109.2-29 .4-89.2-2.2-89.2-2.2s-141.4-7.1-156.8-8.5c-9.8-.6-22.5-2.1-39 1.5-8.7 1.8-33.5 7.4-53.8 26.9C-4.9 212.4 6.6 276.2 8 285.8c1.7 11.7 6.9 44.2 31.7 72.5 45.8 56.1 144.4 54.8 144.4 54.8s12.1 28.9 30.6 55.5c25 33.1 50.7 58.9 75.7 62 63 0 188.9-.1 188.9-.1s12 .1 28.3-10.3c14-8.5 26.5-23.4 26.5-23.4S547 483 565 451.5c5.5-9.7 10.1-19.1 14.1-28 0 0 55.2-117.1 55.2-231.1-1.1-34.5-9.6-40.6-11.6-42.6zM125.6 353.9c-25.9-8.5-36.9-18.7-36.9-18.7S69.6 321.8 60 295.4c-16.5-44.2-1.4-71.2-1.4-71.2s8.4-22.5 38.5-30c13.8-3.7 31-3.1 31-3.1s7.1 59.4 15.7 94.2c7.2 29.2 24.8 77.7 24.8 77.7s-26.1-3.1-43-9.1zm300.3 107.6s-6.1 14.5-19.6 15.4c-5.8.4-10.3-1.2-10.3-1.2s-.3-.1-5.3-2.1l-112.9-55s-10.9-5.7-12.8-15.6c-2.2-8.1 2.7-18.1 2.7-18.1L322 273s4.8-9.7 12.2-13c.6-.3 2.3-1 4.5-1.5 8.1-2.1 18 2.8 18 2.8L467.4 315s12.6 5.7 15.3 16.2c1.9 7.4-.5 14-1.8 17.2-6.3 15.4-55 113.1-55 113.1z" style="fill:#609926"/><path d="M326.8 380.1c-8.2.1-15.4 5.8-17.3 13.8-1.9 8 2 16.3 9.1 20 7.7 4 17.5 1.8 22.7-5.4 5.1-7.1 4.3-16.9-1.8-23.1l24-49.1c1.5.1 3.7.2 6.2-.5 4.1-.9 7.1-3.6 7.1-3.6 4.2 1.8 8.6 3.8 13.2 6.1 4.8 2.4 9.3 4.9 13.4 7.3.9.5 1.8 1.1 2.8 1.9 1.6 1.3 3.4 3.1 4.7 5.5 1.9 5.5-1.9 14.9-1.9 14.9-2.3 7.6-18.4 40.6-18.4 40.6-8.1-.2-15.3 5-17.7 12.5-2.6 8.1 1.1 17.3 8.9 21.3 7.8 4 17.4 1.7 22.5-5.3 5-6.8 4.6-16.3-1.1-22.6 1.9-3.7 3.7-7.4 5.6-11.3 5-10.4 13.5-30.4 13.5-30.4.9-1.7 5.7-10.3 2.7-21.3-2.5-11.4-12.6-16.7-12.6-16.7-12.2-7.9-29.2-15.2-29.2-15.2s0-4.1-1.1-7.1c-1.1-3.1-2.8-5.1-3.9-6.3 4.7-9.7 9.4-19.3 14.1-29-4.1-2-8.1-4-12.2-6.1-4.8 9.8-9.7 19.7-14.5 29.5-6.7-.1-12.9 3.5-16.1 9.4-3.4 6.3-2.7 14.1 1.9 19.8l-24.6 50.4z" style="fill:#609926"/></svg>
|
||||
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
@@ -9,6 +9,8 @@ import (
|
||||
"net/http"
|
||||
|
||||
actions_model "code.gitea.io/gitea/models/actions"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/actions"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
@@ -54,6 +56,18 @@ func (s *Service) Register(
|
||||
return nil, errors.New("runner registration token has been invalidated, please use the latest one")
|
||||
}
|
||||
|
||||
if runnerToken.OwnerID > 0 {
|
||||
if _, err := user_model.GetUserByID(ctx, runnerToken.OwnerID); err != nil {
|
||||
return nil, errors.New("owner of the token not found")
|
||||
}
|
||||
}
|
||||
|
||||
if runnerToken.RepoID > 0 {
|
||||
if _, err := repo_model.GetRepositoryByID(ctx, runnerToken.RepoID); err != nil {
|
||||
return nil, errors.New("repository of the token not found")
|
||||
}
|
||||
}
|
||||
|
||||
labels := req.Msg.Labels
|
||||
// TODO: agent_labels should be removed from pb after Gitea 1.20 released.
|
||||
// Old version runner's agent_labels slice is not empty and labels slice is empty.
|
||||
|
||||
@@ -14,7 +14,6 @@ import (
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/json"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
secret_module "code.gitea.io/gitea/modules/secret"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/services/actions"
|
||||
|
||||
@@ -31,14 +30,24 @@ func pickTask(ctx context.Context, runner *actions_model.ActionRunner) (*runnerv
|
||||
return nil, false, nil
|
||||
}
|
||||
|
||||
secrets, err := secret_model.GetSecretsOfTask(ctx, t)
|
||||
if err != nil {
|
||||
return nil, false, fmt.Errorf("GetSecretsOfTask: %w", err)
|
||||
}
|
||||
|
||||
vars, err := actions_model.GetVariablesOfRun(ctx, t.Job.Run)
|
||||
if err != nil {
|
||||
return nil, false, fmt.Errorf("GetVariablesOfRun: %w", err)
|
||||
}
|
||||
|
||||
actions.CreateCommitStatus(ctx, t.Job)
|
||||
|
||||
task := &runnerv1.Task{
|
||||
Id: t.ID,
|
||||
WorkflowPayload: t.Job.WorkflowPayload,
|
||||
Context: generateTaskContext(t),
|
||||
Secrets: getSecretsOfTask(ctx, t),
|
||||
Vars: getVariablesOfTask(ctx, t),
|
||||
Secrets: secrets,
|
||||
Vars: vars,
|
||||
}
|
||||
|
||||
if needs, err := findTaskNeeds(ctx, t); err != nil {
|
||||
@@ -54,65 +63,6 @@ func pickTask(ctx context.Context, runner *actions_model.ActionRunner) (*runnerv
|
||||
return task, true, nil
|
||||
}
|
||||
|
||||
func getSecretsOfTask(ctx context.Context, task *actions_model.ActionTask) map[string]string {
|
||||
secrets := map[string]string{}
|
||||
|
||||
secrets["GITHUB_TOKEN"] = task.Token
|
||||
secrets["GITEA_TOKEN"] = task.Token
|
||||
|
||||
if task.Job.Run.IsForkPullRequest && task.Job.Run.TriggerEvent != actions_module.GithubEventPullRequestTarget {
|
||||
// ignore secrets for fork pull request, except GITHUB_TOKEN and GITEA_TOKEN which are automatically generated.
|
||||
// for the tasks triggered by pull_request_target event, they could access the secrets because they will run in the context of the base branch
|
||||
// see the documentation: https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_target
|
||||
return secrets
|
||||
}
|
||||
|
||||
ownerSecrets, err := secret_model.FindSecrets(ctx, secret_model.FindSecretsOptions{OwnerID: task.Job.Run.Repo.OwnerID})
|
||||
if err != nil {
|
||||
log.Error("find secrets of owner %v: %v", task.Job.Run.Repo.OwnerID, err)
|
||||
// go on
|
||||
}
|
||||
repoSecrets, err := secret_model.FindSecrets(ctx, secret_model.FindSecretsOptions{RepoID: task.Job.Run.RepoID})
|
||||
if err != nil {
|
||||
log.Error("find secrets of repo %v: %v", task.Job.Run.RepoID, err)
|
||||
// go on
|
||||
}
|
||||
|
||||
for _, secret := range append(ownerSecrets, repoSecrets...) {
|
||||
if v, err := secret_module.DecryptSecret(setting.SecretKey, secret.Data); err != nil {
|
||||
log.Error("decrypt secret %v %q: %v", secret.ID, secret.Name, err)
|
||||
// go on
|
||||
} else {
|
||||
secrets[secret.Name] = v
|
||||
}
|
||||
}
|
||||
|
||||
return secrets
|
||||
}
|
||||
|
||||
func getVariablesOfTask(ctx context.Context, task *actions_model.ActionTask) map[string]string {
|
||||
variables := map[string]string{}
|
||||
|
||||
// Org / User level
|
||||
ownerVariables, err := actions_model.FindVariables(ctx, actions_model.FindVariablesOpts{OwnerID: task.Job.Run.Repo.OwnerID})
|
||||
if err != nil {
|
||||
log.Error("find variables of org: %d, error: %v", task.Job.Run.Repo.OwnerID, err)
|
||||
}
|
||||
|
||||
// Repo level
|
||||
repoVariables, err := actions_model.FindVariables(ctx, actions_model.FindVariablesOpts{RepoID: task.Job.Run.RepoID})
|
||||
if err != nil {
|
||||
log.Error("find variables of repo: %d, error: %v", task.Job.Run.RepoID, err)
|
||||
}
|
||||
|
||||
// Level precedence: Repo > Org / User
|
||||
for _, v := range append(ownerVariables, repoVariables...) {
|
||||
variables[v.Name] = v.Data
|
||||
}
|
||||
|
||||
return variables
|
||||
}
|
||||
|
||||
func generateTaskContext(t *actions_model.ActionTask) *structpb.Struct {
|
||||
event := map[string]any{}
|
||||
_ = json.Unmarshal([]byte(t.Job.Run.EventPayload), &event)
|
||||
|
||||
@@ -31,7 +31,7 @@ import (
|
||||
user_service "code.gitea.io/gitea/services/user"
|
||||
)
|
||||
|
||||
func parseAuthSource(ctx *context.APIContext, u *user_model.User, sourceID int64, loginName string) {
|
||||
func parseAuthSource(ctx *context.APIContext, u *user_model.User, sourceID int64) {
|
||||
if sourceID == 0 {
|
||||
return
|
||||
}
|
||||
@@ -48,7 +48,6 @@ func parseAuthSource(ctx *context.APIContext, u *user_model.User, sourceID int64
|
||||
|
||||
u.LoginType = source.Type
|
||||
u.LoginSource = source.ID
|
||||
u.LoginName = loginName
|
||||
}
|
||||
|
||||
// CreateUser create a user
|
||||
@@ -84,12 +83,13 @@ func CreateUser(ctx *context.APIContext) {
|
||||
Passwd: form.Password,
|
||||
MustChangePassword: true,
|
||||
LoginType: auth.Plain,
|
||||
LoginName: form.LoginName,
|
||||
}
|
||||
if form.MustChangePassword != nil {
|
||||
u.MustChangePassword = *form.MustChangePassword
|
||||
}
|
||||
|
||||
parseAuthSource(ctx, u, form.SourceID, form.LoginName)
|
||||
parseAuthSource(ctx, u, form.SourceID)
|
||||
if ctx.Written() {
|
||||
return
|
||||
}
|
||||
@@ -192,7 +192,7 @@ func EditUser(ctx *context.APIContext) {
|
||||
|
||||
form := web.GetForm(ctx).(*api.EditUserOption)
|
||||
|
||||
parseAuthSource(ctx, ctx.ContextUser, form.SourceID, form.LoginName)
|
||||
parseAuthSource(ctx, ctx.ContextUser, form.SourceID)
|
||||
if ctx.Written() {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -864,10 +864,11 @@ func EditIssue(ctx *context.APIContext) {
|
||||
}
|
||||
if form.State != nil {
|
||||
if issue.IsPull {
|
||||
if pr, err := issue.GetPullRequest(); err != nil {
|
||||
if err := issue.LoadPullRequest(ctx); err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "GetPullRequest", err)
|
||||
return
|
||||
} else if pr.HasMerged {
|
||||
}
|
||||
if issue.PullRequest.HasMerged {
|
||||
ctx.Error(http.StatusPreconditionFailed, "MergedPRState", "cannot change state of this pull request, it was already merged")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -240,18 +240,12 @@ func ListPinnedPullRequests(ctx *context.APIContext) {
|
||||
}
|
||||
|
||||
apiPrs := make([]*api.PullRequest, len(issues))
|
||||
if err := issues.LoadPullRequests(ctx); err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "LoadPullRequests", err)
|
||||
return
|
||||
}
|
||||
for i, currentIssue := range issues {
|
||||
pr, err := currentIssue.GetPullRequest()
|
||||
if err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "GetPullRequest", err)
|
||||
return
|
||||
}
|
||||
|
||||
if err = pr.LoadIssue(ctx); err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "LoadIssue", err)
|
||||
return
|
||||
}
|
||||
|
||||
pr := currentIssue.PullRequest
|
||||
if err = pr.LoadAttributes(ctx); err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "LoadAttributes", err)
|
||||
return
|
||||
|
||||
@@ -969,6 +969,8 @@ func parseCompareInfo(ctx *context.APIContext, form api.CreatePullRequestOption)
|
||||
return nil, nil, nil, nil, "", ""
|
||||
}
|
||||
headBranch = headInfos[1]
|
||||
// The head repository can also point to the same repo
|
||||
isSameRepo = ctx.Repo.Owner.ID == headUser.ID
|
||||
|
||||
} else {
|
||||
ctx.NotFound()
|
||||
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
"code.gitea.io/gitea/modules/web"
|
||||
"code.gitea.io/gitea/routers/api/v1/utils"
|
||||
"code.gitea.io/gitea/services/convert"
|
||||
files_service "code.gitea.io/gitea/services/repository/files"
|
||||
commitstatus_service "code.gitea.io/gitea/services/repository/commitstatus"
|
||||
)
|
||||
|
||||
// NewCommitStatus creates a new CommitStatus
|
||||
@@ -63,7 +63,7 @@ func NewCommitStatus(ctx *context.APIContext) {
|
||||
Description: form.Description,
|
||||
Context: form.Context,
|
||||
}
|
||||
if err := files_service.CreateCommitStatus(ctx, ctx.Repo.Repository, ctx.Doer, sha, status); err != nil {
|
||||
if err := commitstatus_service.CreateCommitStatus(ctx, ctx.Repo.Repository, ctx.Doer, sha, status); err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "CreateCommitStatus", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -6,10 +6,11 @@ package private
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
issues_model "code.gitea.io/gitea/models/issues"
|
||||
access_model "code.gitea.io/gitea/models/perm/access"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
gitea_context "code.gitea.io/gitea/modules/context"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
@@ -89,8 +90,10 @@ func HookPostReceive(ctx *gitea_context.PrivateContext) {
|
||||
}
|
||||
}
|
||||
|
||||
isPrivate := opts.GitPushOptions.Bool(private.GitPushOptionRepoPrivate)
|
||||
isTemplate := opts.GitPushOptions.Bool(private.GitPushOptionRepoTemplate)
|
||||
// Handle Push Options
|
||||
if len(opts.GitPushOptions) > 0 {
|
||||
if !isPrivate.IsNone() || !isTemplate.IsNone() {
|
||||
// load the repository
|
||||
if repo == nil {
|
||||
repo = loadRepository(ctx, ownerName, repoName)
|
||||
@@ -101,13 +104,49 @@ func HookPostReceive(ctx *gitea_context.PrivateContext) {
|
||||
wasEmpty = repo.IsEmpty
|
||||
}
|
||||
|
||||
repo.IsPrivate = opts.GitPushOptions.Bool(private.GitPushOptionRepoPrivate, repo.IsPrivate)
|
||||
repo.IsTemplate = opts.GitPushOptions.Bool(private.GitPushOptionRepoTemplate, repo.IsTemplate)
|
||||
if err := repo_model.UpdateRepositoryCols(ctx, repo, "is_private", "is_template"); err != nil {
|
||||
pusher, err := user_model.GetUserByID(ctx, opts.UserID)
|
||||
if err != nil {
|
||||
log.Error("Failed to Update: %s/%s Error: %v", ownerName, repoName, err)
|
||||
ctx.JSON(http.StatusInternalServerError, private.HookPostReceiveResult{
|
||||
Err: fmt.Sprintf("Failed to Update: %s/%s Error: %v", ownerName, repoName, err),
|
||||
})
|
||||
return
|
||||
}
|
||||
perm, err := access_model.GetUserRepoPermission(ctx, repo, pusher)
|
||||
if err != nil {
|
||||
log.Error("Failed to Update: %s/%s Error: %v", ownerName, repoName, err)
|
||||
ctx.JSON(http.StatusInternalServerError, private.HookPostReceiveResult{
|
||||
Err: fmt.Sprintf("Failed to Update: %s/%s Error: %v", ownerName, repoName, err),
|
||||
})
|
||||
return
|
||||
}
|
||||
if !perm.IsOwner() && !perm.IsAdmin() {
|
||||
ctx.JSON(http.StatusNotFound, private.HookPostReceiveResult{
|
||||
Err: "Permissions denied",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
cols := make([]string, 0, len(opts.GitPushOptions))
|
||||
|
||||
if !isPrivate.IsNone() {
|
||||
repo.IsPrivate = isPrivate.IsTrue()
|
||||
cols = append(cols, "is_private")
|
||||
}
|
||||
|
||||
if !isTemplate.IsNone() {
|
||||
repo.IsTemplate = isTemplate.IsTrue()
|
||||
cols = append(cols, "is_template")
|
||||
}
|
||||
|
||||
if len(cols) > 0 {
|
||||
if err := repo_model.UpdateRepositoryCols(ctx, repo, cols...); err != nil {
|
||||
log.Error("Failed to Update: %s/%s Error: %v", ownerName, repoName, err)
|
||||
ctx.JSON(http.StatusInternalServerError, private.HookPostReceiveResult{
|
||||
Err: fmt.Sprintf("Failed to Update: %s/%s Error: %v", ownerName, repoName, err),
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,42 +161,6 @@ func HookPostReceive(ctx *gitea_context.PrivateContext) {
|
||||
refFullName := opts.RefFullNames[i]
|
||||
newCommitID := opts.NewCommitIDs[i]
|
||||
|
||||
// post update for agit pull request
|
||||
// FIXME: use pr.Flow to test whether it's an Agit PR or a GH PR
|
||||
if git.SupportProcReceive && refFullName.IsPull() {
|
||||
if repo == nil {
|
||||
repo = loadRepository(ctx, ownerName, repoName)
|
||||
if ctx.Written() {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
pullIndex, _ := strconv.ParseInt(refFullName.PullName(), 10, 64)
|
||||
if pullIndex <= 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
pr, err := issues_model.GetPullRequestByIndex(ctx, repo.ID, pullIndex)
|
||||
if err != nil && !issues_model.IsErrPullRequestNotExist(err) {
|
||||
log.Error("Failed to get PR by index %v Error: %v", pullIndex, err)
|
||||
ctx.JSON(http.StatusInternalServerError, private.Response{
|
||||
Err: fmt.Sprintf("Failed to get PR by index %v Error: %v", pullIndex, err),
|
||||
})
|
||||
return
|
||||
}
|
||||
if pr == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
results = append(results, private.HookPostReceiveBranchResult{
|
||||
Message: setting.Git.PullRequestPushMessage && repo.AllowsPulls(),
|
||||
Create: false,
|
||||
Branch: "",
|
||||
URL: fmt.Sprintf("%s/pulls/%d", repo.HTMLURL(), pr.Index),
|
||||
})
|
||||
continue
|
||||
}
|
||||
|
||||
// If we've pushed a branch (and not deleted it)
|
||||
if newCommitID != git.EmptySHA && refFullName.IsBranch() {
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user