mirror of
https://github.com/gogs/gogs.git
synced 2026-03-01 17:50:59 +01:00
Compare commits
21 Commits
migrate/go
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e8b6dea462 | ||
|
|
2989605fd8 | ||
|
|
df467d8ff1 | ||
|
|
36d56d5525 | ||
|
|
5f17b670b3 | ||
|
|
ea682c5bbc | ||
|
|
9001a68cdd | ||
|
|
295bfba729 | ||
|
|
ac21150a53 | ||
|
|
a000f0c7a6 | ||
|
|
a976fd2f9c | ||
|
|
441c64d7bd | ||
|
|
5c67d47512 | ||
|
|
94d6e53dc2 | ||
|
|
a1fa62b270 | ||
|
|
317e28b908 | ||
|
|
069d3535d6 | ||
|
|
81ee883644 | ||
|
|
400ae7bd28 | ||
|
|
630ae0b3b0 | ||
|
|
3c358ede6d |
13
.claude/commands/ghsa.md
Normal file
13
.claude/commands/ghsa.md
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
Analyze and help fix the GitHub Security Advisory (GHSA) at: $ARGUMENTS
|
||||||
|
|
||||||
|
Steps:
|
||||||
|
1. Fetch the GHSA page using `gh api repos/gogs/gogs/security-advisories` and understand the vulnerability details (description, severity, affected versions, CWE).
|
||||||
|
2. Verify the reported vulnerability actually exists, and why.
|
||||||
|
3. Identify the affected code in this repository.
|
||||||
|
4. Propose a fix with a clear explanation of the root cause and how the fix addresses it. Check for prior art in the codebase to stay consistent with existing patterns.
|
||||||
|
5. Implement the fix. Only add tests when there is something meaningful to test at our layer.
|
||||||
|
6. Run all the usual build and test commands.
|
||||||
|
7. If a changelog entry is warranted (user will specify), add it to CHANGELOG.md with a placeholder for the PR link.
|
||||||
|
8. Create a branch named after the GHSA ID, commit, and push.
|
||||||
|
9. Create a pull request with a proper title and description, do not reveal too much detail and link the GHSA.
|
||||||
|
10. If a changelog entry was added, update it with the PR link, then commit and push again.
|
||||||
6
.github/CONTRIBUTING.md
vendored
6
.github/CONTRIBUTING.md
vendored
@@ -29,7 +29,7 @@ In addition to the general guides with open source contributions, you would also
|
|||||||
|
|
||||||
### Ask for help
|
### Ask for help
|
||||||
|
|
||||||
Before opening an issue, please make sure the problem you're encountering isn't already addressed on the [Troubleshooting](https://gogs.io/docs/intro/troubleshooting.html) and [FAQs](https://gogs.io/docs/intro/faqs.html) pages.
|
Before opening an issue, please make sure the problem you're encountering isn't already addressed on the [Troubleshooting](https://gogs.io/asking/troubleshooting) and [FAQs](https://gogs.io/asking/faq) pages.
|
||||||
|
|
||||||
### Create a new issue
|
### Create a new issue
|
||||||
|
|
||||||
@@ -65,12 +65,12 @@ Contributing to another codebase is not as simple as code changes, it is also ab
|
|||||||
|
|
||||||
### Things we do not accept
|
### Things we do not accept
|
||||||
|
|
||||||
1. Updates to locale files (`conf/locale_xx-XX.ini`) other than the `conf/locale_en-US.ini`. Please read the [guide for localizing Gogs](https://gogs.io/docs/features/i18n).
|
1. Updates to locale files (`conf/locale_xx-XX.ini`) other than the `conf/locale_en-US.ini`. Please read the [guide for localizing Gogs](https://gogs.io/advancing/localization).
|
||||||
1. Docker compose files.
|
1. Docker compose files.
|
||||||
|
|
||||||
### Coding guidelines
|
### Coding guidelines
|
||||||
|
|
||||||
1. Please read the Sourcegraph's [Go style guide](https://docs.sourcegraph.com/dev/background-information/languages/go).
|
1. Please read the Sourcegraph's [Go style guide](https://github.com/sourcegraph/sourcegraph-public-snapshot/blob/main/doc/dev/background-information/languages/go.md).
|
||||||
1. **NO** direct modifications to `.css` files, `.css` files are all generated by `.less` files. You can regenerate `.css` files by executing `task less`.
|
1. **NO** direct modifications to `.css` files, `.css` files are all generated by `.less` files. You can regenerate `.css` files by executing `task less`.
|
||||||
|
|
||||||
## Your PR is merged!
|
## Your PR is merged!
|
||||||
|
|||||||
2
.github/workflows/codeql.yml
vendored
2
.github/workflows/codeql.yml
vendored
@@ -38,7 +38,7 @@ jobs:
|
|||||||
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
|
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Check out repository
|
||||||
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
||||||
with:
|
with:
|
||||||
# We must fetch at least the immediate parents so that if this is
|
# We must fetch at least the immediate parents so that if this is
|
||||||
|
|||||||
12
.github/workflows/docker.yml
vendored
12
.github/workflows/docker.yml
vendored
@@ -26,7 +26,7 @@ jobs:
|
|||||||
contents: read
|
contents: read
|
||||||
packages: write
|
packages: write
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Check out code
|
||||||
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
||||||
- name: Set up QEMU
|
- name: Set up QEMU
|
||||||
uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0
|
uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0
|
||||||
@@ -85,7 +85,7 @@ jobs:
|
|||||||
contents: read
|
contents: read
|
||||||
packages: write
|
packages: write
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Check out code
|
||||||
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
||||||
- name: Set up QEMU
|
- name: Set up QEMU
|
||||||
uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0
|
uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0
|
||||||
@@ -173,7 +173,7 @@ jobs:
|
|||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Check out code
|
||||||
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
id: buildx
|
id: buildx
|
||||||
@@ -212,7 +212,7 @@ jobs:
|
|||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Check out code
|
||||||
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
id: buildx
|
id: buildx
|
||||||
@@ -274,7 +274,7 @@ jobs:
|
|||||||
echo "TAGS<<EOF" >> $GITHUB_ENV
|
echo "TAGS<<EOF" >> $GITHUB_ENV
|
||||||
echo "$TAGS" >> $GITHUB_ENV
|
echo "$TAGS" >> $GITHUB_ENV
|
||||||
echo "EOF" >> $GITHUB_ENV
|
echo "EOF" >> $GITHUB_ENV
|
||||||
- name: Checkout code
|
- name: Check out code
|
||||||
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
||||||
- name: Set up QEMU
|
- name: Set up QEMU
|
||||||
uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0
|
uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0
|
||||||
@@ -343,7 +343,7 @@ jobs:
|
|||||||
echo "TAGS<<EOF" >> $GITHUB_ENV
|
echo "TAGS<<EOF" >> $GITHUB_ENV
|
||||||
echo "$TAGS" >> $GITHUB_ENV
|
echo "$TAGS" >> $GITHUB_ENV
|
||||||
echo "EOF" >> $GITHUB_ENV
|
echo "EOF" >> $GITHUB_ENV
|
||||||
- name: Checkout code
|
- name: Check out code
|
||||||
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
||||||
- name: Set up QEMU
|
- name: Set up QEMU
|
||||||
uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0
|
uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0
|
||||||
|
|||||||
20
.github/workflows/go.yml
vendored
20
.github/workflows/go.yml
vendored
@@ -29,12 +29,12 @@ jobs:
|
|||||||
name: Lint
|
name: Lint
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Check out code
|
||||||
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
|
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
|
||||||
with:
|
with:
|
||||||
go-version: 1.25.x
|
go-version: 1.26.x
|
||||||
- name: Install Task
|
- name: Install Task
|
||||||
uses: arduino/setup-task@b91d5d2c96a56797b48ac1e0e89220bf64044611 # v2.0.0
|
uses: arduino/setup-task@b91d5d2c96a56797b48ac1e0e89220bf64044611 # v2.0.0
|
||||||
with:
|
with:
|
||||||
@@ -61,11 +61,11 @@ jobs:
|
|||||||
name: Test
|
name: Test
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
go-version: [ 1.25.x ]
|
go-version: [ 1.26.x ]
|
||||||
platform: [ ubuntu-latest, macos-latest ]
|
platform: [ ubuntu-latest, macos-latest ]
|
||||||
runs-on: ${{ matrix.platform }}
|
runs-on: ${{ matrix.platform }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Check out code
|
||||||
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
|
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
|
||||||
@@ -89,11 +89,11 @@ jobs:
|
|||||||
name: Test Windows
|
name: Test Windows
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
go-version: [ 1.25.x ]
|
go-version: [ 1.26.x ]
|
||||||
platform: [ windows-latest ]
|
platform: [ windows-latest ]
|
||||||
runs-on: ${{ matrix.platform }}
|
runs-on: ${{ matrix.platform }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Check out code
|
||||||
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
|
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
|
||||||
@@ -112,7 +112,7 @@ jobs:
|
|||||||
name: Postgres
|
name: Postgres
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
go-version: [ 1.25.x ]
|
go-version: [ 1.26.x ]
|
||||||
platform: [ ubuntu-latest ]
|
platform: [ ubuntu-latest ]
|
||||||
runs-on: ${{ matrix.platform }}
|
runs-on: ${{ matrix.platform }}
|
||||||
services:
|
services:
|
||||||
@@ -128,7 +128,7 @@ jobs:
|
|||||||
ports:
|
ports:
|
||||||
- 5432:5432
|
- 5432:5432
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Check out code
|
||||||
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
|
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
|
||||||
@@ -151,13 +151,13 @@ jobs:
|
|||||||
name: MySQL
|
name: MySQL
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
go-version: [ 1.25.x ]
|
go-version: [ 1.26.x ]
|
||||||
platform: [ ubuntu-22.04 ] # Use the lowest version possible for backwards compatibility
|
platform: [ ubuntu-22.04 ] # Use the lowest version possible for backwards compatibility
|
||||||
runs-on: ${{ matrix.platform }}
|
runs-on: ${{ matrix.platform }}
|
||||||
steps:
|
steps:
|
||||||
- name: Start MySQL server
|
- name: Start MySQL server
|
||||||
run: sudo systemctl start mysql
|
run: sudo systemctl start mysql
|
||||||
- name: Checkout code
|
- name: Check out code
|
||||||
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
|
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
|
||||||
|
|||||||
16
.github/workflows/release.yml
vendored
16
.github/workflows/release.yml
vendored
@@ -40,12 +40,12 @@ jobs:
|
|||||||
- {goos: windows, goarch: arm64, suffix: "_mws", tags: minwinsvc}
|
- {goos: windows, goarch: arm64, suffix: "_mws", tags: minwinsvc}
|
||||||
- {goos: windows, goarch: "386", suffix: "_mws", tags: minwinsvc}
|
- {goos: windows, goarch: "386", suffix: "_mws", tags: minwinsvc}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Check out code
|
||||||
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
|
||||||
- name: Setup Go
|
- name: Set up Go
|
||||||
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
|
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
|
||||||
with:
|
with:
|
||||||
go-version: 1.25.x
|
go-version: 1.26.x
|
||||||
- name: Determine version
|
- name: Determine version
|
||||||
id: version
|
id: version
|
||||||
run: |
|
run: |
|
||||||
@@ -90,7 +90,7 @@ jobs:
|
|||||||
BINARY_NAME="gogs.exe"
|
BINARY_NAME="gogs.exe"
|
||||||
fi
|
fi
|
||||||
cp "$BINARY_NAME" dist/gogs/
|
cp "$BINARY_NAME" dist/gogs/
|
||||||
cp LICENSE README.md README_ZH.md dist/gogs/
|
cp LICENSE README.md dist/gogs/
|
||||||
cp -r scripts dist/gogs/
|
cp -r scripts dist/gogs/
|
||||||
- name: Create archives
|
- name: Create archives
|
||||||
working-directory: dist
|
working-directory: dist
|
||||||
@@ -112,14 +112,14 @@ jobs:
|
|||||||
if [ "${{ github.event_name }}" != "release" ]; then
|
if [ "${{ github.event_name }}" != "release" ]; then
|
||||||
git tag -f "$RELEASE_TAG"
|
git tag -f "$RELEASE_TAG"
|
||||||
git push origin "$RELEASE_TAG" --force || true
|
git push origin "$RELEASE_TAG" --force || true
|
||||||
|
|
||||||
RELEASE_TITLE="Release Archive Testing"
|
RELEASE_TITLE="Release archive testing"
|
||||||
RELEASE_NOTES="Automated testing release for workflow development."
|
RELEASE_NOTES="Automated testing release for workflow development."
|
||||||
if [ "$RELEASE_TAG" = "latest-commit-build" ]; then
|
if [ "$RELEASE_TAG" = "latest-commit-build" ]; then
|
||||||
RELEASE_TITLE="Latest Commit Build"
|
RELEASE_TITLE="Latest commit build"
|
||||||
RELEASE_NOTES="Automated build from the latest commit on main branch. This release is updated automatically with every push to main."
|
RELEASE_NOTES="Automated build from the latest commit on main branch. This release is updated automatically with every push to main."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
gh release view "$RELEASE_TAG" || gh release create "$RELEASE_TAG" --title "$RELEASE_TITLE" --notes "$RELEASE_NOTES" --prerelease
|
gh release view "$RELEASE_TAG" || gh release create "$RELEASE_TAG" --title "$RELEASE_TITLE" --notes "$RELEASE_NOTES" --prerelease
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ This applies to all texts, including but not limited to UI, documentation, code
|
|||||||
|
|
||||||
- Prefer `task` command over vanilla `go` command when available. Use `--force` flag when necessary.
|
- Prefer `task` command over vanilla `go` command when available. Use `--force` flag when necessary.
|
||||||
- Run `task lint` after every time you finish changing code, and fix all linter errors.
|
- Run `task lint` after every time you finish changing code, and fix all linter errors.
|
||||||
|
- Run `go mod tidy` after every time you change `go.mod`, do not manually edit `go.sum` file.
|
||||||
|
|
||||||
## Tool-use guidance
|
## Tool-use guidance
|
||||||
|
|
||||||
@@ -28,5 +29,5 @@ This applies to all texts, including but not limited to UI, documentation, code
|
|||||||
## Source code control
|
## Source code control
|
||||||
|
|
||||||
- When pushing changes to a pull request from a fork, use SSH address and do not add remote.
|
- When pushing changes to a pull request from a fork, use SSH address and do not add remote.
|
||||||
- Never automatically executes commands that touches Git history even if the session does not require approvals, including but not limited to `rebase`, `commit`, `push`, `pull`, `reset`, `amend`. Exceptions are only allowed case-by-case.
|
- Never commit on the `main` branch directly unless being explicitly asked to do so. A single ask only grants a single commit action on the `main` branch.
|
||||||
- Do not amend commits unless being explicitly asked to do so.
|
- Never amend commits unless being explicitly asked to do so.
|
||||||
|
|||||||
17
CHANGELOG.md
17
CHANGELOG.md
@@ -7,6 +7,23 @@ All notable changes to Gogs are documented in this file.
|
|||||||
### Removed
|
### Removed
|
||||||
|
|
||||||
- The `gogs cert` subcommand. [#8153](https://github.com/gogs/gogs/pull/8153)
|
- The `gogs cert` subcommand. [#8153](https://github.com/gogs/gogs/pull/8153)
|
||||||
|
- The `[email] DISABLE_HELO` configuration option. HELO/EHLO is now always sent during SMTP handshake. [#8164](https://github.com/gogs/gogs/pull/8164)
|
||||||
|
- Support for MSSQL as a database backend. Stay on 0.14 for continued usage. [#8173](https://github.com/gogs/gogs/pull/8173)
|
||||||
|
|
||||||
|
## 0.14.2
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- _Security:_ Cross-repository LFS object overwrite via missing content hash verification. [#8166](https://github.com/gogs/gogs/pull/8166) - [GHSA-gmf8-978x-2fg2](https://github.com/gogs/gogs/security/advisories/GHSA-gmf8-978x-2fg2)
|
||||||
|
- _Security:_ Stored XSS via data URI in issue comments. [#8174](https://github.com/gogs/gogs/pull/8174) - [GHSA-xrcr-gmf5-2r8j](https://github.com/gogs/gogs/security/advisories/GHSA-xrcr-gmf5-2r8j)
|
||||||
|
- _Security:_ Release tag option injection in release deletion. [#8175](https://github.com/gogs/gogs/pull/8175) - [GHSA-v9vm-r24h-6rqm](https://github.com/gogs/gogs/security/advisories/GHSA-v9vm-r24h-6rqm)
|
||||||
|
- _Security:_ Stored XSS in branch and wiki views through author and committer names. [#8176](https://github.com/gogs/gogs/pull/8176) - [GHSA-vgvf-m4fw-938j](https://github.com/gogs/gogs/security/advisories/GHSA-vgvf-m4fw-938j)
|
||||||
|
- _Security:_ DOM-based XSS via issue meta selection on the issue page. [#8178](https://github.com/gogs/gogs/pull/8178) - [GHSA-vgjm-2cpf-4g7c](https://github.com/gogs/gogs/security/advisories/GHSA-vgjm-2cpf-4g7c)
|
||||||
|
- Unable to update files via web editor and API. [#8184](https://github.com/gogs/gogs/pull/8184)
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
|
||||||
|
- Support for passing API access tokens via URL query parameters (`token`, `access_token`). Use the `Authorization` header instead. [#8177](https://github.com/gogs/gogs/pull/8177) - [GHSA-x9p5-w45c-7ffc](https://github.com/gogs/gogs/security/advisories/GHSA-x9p5-w45c-7ffc)
|
||||||
|
|
||||||
## 0.14.1
|
## 0.14.1
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM golang:alpine3.21 AS binarybuilder
|
FROM golang:1.26-alpine3.23 AS binarybuilder
|
||||||
RUN apk --no-cache --no-progress add --virtual \
|
RUN apk --no-cache --no-progress add --virtual \
|
||||||
build-deps \
|
build-deps \
|
||||||
build-base \
|
build-base \
|
||||||
@@ -11,7 +11,7 @@ COPY . .
|
|||||||
RUN ./docker/build/install-task.sh
|
RUN ./docker/build/install-task.sh
|
||||||
RUN TAGS="cert pam" task build
|
RUN TAGS="cert pam" task build
|
||||||
|
|
||||||
FROM alpine:3.21
|
FROM alpine:3.23
|
||||||
RUN apk --no-cache --no-progress add \
|
RUN apk --no-cache --no-progress add \
|
||||||
bash \
|
bash \
|
||||||
ca-certificates \
|
ca-certificates \
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM golang:alpine3.23 AS binarybuilder
|
FROM golang:1.26-alpine3.23 AS binarybuilder
|
||||||
RUN apk --no-cache --no-progress add --virtual \
|
RUN apk --no-cache --no-progress add --virtual \
|
||||||
build-deps \
|
build-deps \
|
||||||
build-base \
|
build-base \
|
||||||
|
|||||||
19
README.md
19
README.md
@@ -13,10 +13,10 @@ The Gogs (`/gɑgz/`) project aims to build a simple, stable and extensible self-
|
|||||||
- Please visit [our home page](https://gogs.io) for user documentation.
|
- Please visit [our home page](https://gogs.io) for user documentation.
|
||||||
- Please refer to [CHANGELOG.md](CHANGELOG.md) for list of changes in each releases.
|
- Please refer to [CHANGELOG.md](CHANGELOG.md) for list of changes in each releases.
|
||||||
- Want to try it before doing anything else? Do it [online](https://try.gogs.io/gogs/gogs)!
|
- Want to try it before doing anything else? Do it [online](https://try.gogs.io/gogs/gogs)!
|
||||||
- Having trouble? Help yourself with [troubleshooting](https://gogs.io/docs/intro/troubleshooting.html) or ask questions in [Discussions](https://github.com/gogs/gogs/discussions).
|
- Having trouble? Help yourself with [troubleshooting](https://gogs.io/asking/troubleshooting) or ask questions in [Discussions](https://github.com/gogs/gogs/discussions).
|
||||||
- Want to help with localization? Check out the [localization documentation](https://gogs.io/docs/features/i18n.html).
|
- Want to help with localization? Check out the [localization documentation](https://gogs.io/advancing/localization).
|
||||||
- Ready to get hands dirty? Read our [contributing guide](.github/CONTRIBUTING.md).
|
- Ready to get hands dirty? Read our [contributing guide](.github/CONTRIBUTING.md).
|
||||||
- Hmm... What about APIs? We have experimental support with [documentation](https://github.com/gogs/docs-api).
|
- Hmm... What about APIs? We have experimental support with [documentation](https://gogs.io/api-reference).
|
||||||
|
|
||||||
## 💌 Features
|
## 💌 Features
|
||||||
|
|
||||||
@@ -47,15 +47,7 @@ The Gogs (`/gɑgz/`) project aims to build a simple, stable and extensible self-
|
|||||||
|
|
||||||
## 📜 Installation
|
## 📜 Installation
|
||||||
|
|
||||||
Make sure you install the [prerequisites](https://gogs.io/docs/installation) first.
|
Please follow [the guide in our documentation](https://gogs.io/getting-started/installation).
|
||||||
|
|
||||||
There are 6 ways to install Gogs:
|
|
||||||
|
|
||||||
- [Install from binary](https://gogs.io/docs/installation/install_from_binary.html)
|
|
||||||
- [Install from source](https://gogs.io/docs/installation/install_from_source.html)
|
|
||||||
- [Install from packages](https://gogs.io/docs/installation/install_from_packages.html)
|
|
||||||
- [Ship with Docker](https://github.com/gogs/gogs/tree/main/docker)
|
|
||||||
- [Try with Vagrant](https://github.com/geerlingguy/ansible-vagrant-examples/tree/master/gogs)
|
|
||||||
|
|
||||||
### Deploy to cloud
|
### Deploy to cloud
|
||||||
|
|
||||||
@@ -94,7 +86,8 @@ There are 6 ways to install Gogs:
|
|||||||
Other acknowledgments:
|
Other acknowledgments:
|
||||||
|
|
||||||
- Thanks [Egon Elbre](https://twitter.com/egonelbre) for designing the original version of the logo.
|
- Thanks [Egon Elbre](https://twitter.com/egonelbre) for designing the original version of the logo.
|
||||||
- Thanks [Crowdin](https://crowdin.com/project/gogs) for sponsoring open source translation plan.
|
- Thanks [Mintlify](https://mintlify.com) for sponsoring open source documentation plan.
|
||||||
|
- Thanks [Crowdin](https://crowdin.com) for sponsoring open source translation plan.
|
||||||
- Thanks [Buildkite](https://buildkite.com) for sponsoring open source CI/CD plan.
|
- Thanks [Buildkite](https://buildkite.com) for sponsoring open source CI/CD plan.
|
||||||
|
|
||||||
## 👋 Contributors
|
## 👋 Contributors
|
||||||
|
|||||||
102
README_ZH.md
102
README_ZH.md
@@ -1,102 +0,0 @@
|
|||||||
# Gogs
|
|
||||||
|
|
||||||
Gogs 是一款极易搭建的自助 Git 服务。
|
|
||||||
|
|
||||||
## 项目愿景
|
|
||||||
|
|
||||||
Gogs(`/gɑgz/`)项目旨在打造一个以最简便的方式搭建简单、稳定和可扩展的自助 Git 服务。使用 Go 语言开发使得 Gogs 能够通过独立的二进制分发,并且支持 Go 语言支持的 **所有平台**,包括 Linux、macOS、Windows 和基于 ARM 的操作系统。
|
|
||||||
|
|
||||||
## 概览
|
|
||||||
|
|
||||||
- 请移步[官网](https://gogs.io)查看用户使用文档
|
|
||||||
- 请通过 [CHANGELOG.md](CHANGELOG.md) 文件查看各个版本的变更历史
|
|
||||||
- 想要先睹为快?直接去[在线体验](https://try.gogs.io/gogs/gogs)吧!
|
|
||||||
- 使用过程中遇到问题?尝试[故障排查](https://gogs.io/docs/intro/troubleshooting.html)或者前往[用户论坛](https://discuss.gogs.io/)获取帮助
|
|
||||||
- 希望帮助多国语言的翻译吗?请查看[本地化文档](https://gogs.io/docs/features/i18n.html)
|
|
||||||
- 准备搞点事情?请阅读[开发指南](docs/dev/local_development.md)配置开发环境
|
|
||||||
- 想调用 API 吗?请查看[文档](https://github.com/gogs/docs-api)吧
|
|
||||||
|
|
||||||
## 主要特性
|
|
||||||
|
|
||||||
- 控制面板、用户页面以及活动时间线
|
|
||||||
- 通过 SSH、HTTP 和 HTTPS 协议操作仓库
|
|
||||||
- 管理用户、组织和仓库
|
|
||||||
- 仓库和组织级 Webhook,包括 Slack、Discord 和钉钉
|
|
||||||
- 仓库 Git 钩子、部署密钥和 Git LFS
|
|
||||||
- 仓库工单(Issue)、合并请求(Pull Request)、Wiki、保护分支和多人协作
|
|
||||||
- 从其它代码平台迁移和镜像仓库以及 Wiki
|
|
||||||
- 在线编辑仓库文件和 Wiki
|
|
||||||
- Jupyter Notebook 和 PDF 的渲染
|
|
||||||
- 通过 SMTP、LDAP、反向代理、GitHub.com 和 GitHub 企业版进行用户认证
|
|
||||||
- 开启两步验证(2FA)登录
|
|
||||||
- 自定义 HTML 模板、静态文件和许多其它组件
|
|
||||||
- 多样的数据库后端,包括 PostgreSQL、MySQL、SQLite3 和 [TiDB](https://github.com/pingcap/tidb)
|
|
||||||
- 超过 [31 种语言](https://crowdin.com/project/gogs)的本地化
|
|
||||||
|
|
||||||
## 硬件要求
|
|
||||||
|
|
||||||
- 最低的系统硬件要求为一个廉价的树莓派
|
|
||||||
- 如果用于团队项目管理,建议使用 2 核 CPU 及 512MB 内存
|
|
||||||
- 当团队成员大量增加时,可以考虑添加 CPU 核数,内存占用保持不变
|
|
||||||
|
|
||||||
## 浏览器支持
|
|
||||||
|
|
||||||
- 请根据 [Semantic UI](https://github.com/Semantic-Org/Semantic-UI#browser-support) 查看具体支持的浏览器版本。
|
|
||||||
- 官方支持的最小 UI 尺寸为 **1024*768**,UI 不一定会在更小尺寸的设备上被破坏,但我们无法保证且不会修复。
|
|
||||||
|
|
||||||
## 安装部署
|
|
||||||
|
|
||||||
在安装 Gogs 之前,您需要先安装 [基本环境](https://gogs.io/docs/installation)。
|
|
||||||
|
|
||||||
然后,您可以通过以下 6 种方式来安装 Gogs:
|
|
||||||
|
|
||||||
- [二进制安装](https://gogs.io/docs/installation/install_from_binary.html)
|
|
||||||
- [源码安装](https://gogs.io/docs/installation/install_from_source.html)
|
|
||||||
- [包管理安装](https://gogs.io/docs/installation/install_from_packages.html)
|
|
||||||
- [采用 Docker 部署](https://github.com/gogs/gogs/tree/main/docker)
|
|
||||||
- [通过 Vagrant 安装](https://github.com/geerlingguy/ansible-vagrant-examples/tree/master/gogs)
|
|
||||||
- [通过基于 Kubernetes 的 Helm Charts](https://github.com/helm/charts/tree/master/incubator/gogs)
|
|
||||||
|
|
||||||
### 云端部署
|
|
||||||
|
|
||||||
- [OpenShift](https://github.com/tkisme/gogs-openshift)
|
|
||||||
- [Cloudron](https://cloudron.io/appstore.html#io.gogs.cloudronapp)
|
|
||||||
- [Scaleway](https://www.scaleway.com/imagehub/gogs/)
|
|
||||||
- [Sandstorm](https://github.com/cem/gogs-sandstorm)
|
|
||||||
- [sloppy.io](https://github.com/sloppyio/quickstarters/tree/master/gogs)
|
|
||||||
- [YunoHost](https://github.com/mbugeia/gogs_ynh)
|
|
||||||
- [DPlatform](https://github.com/j8r/DPlatform)
|
|
||||||
- [LunaNode](https://github.com/LunaNode/launchgogs)
|
|
||||||
|
|
||||||
### 使用教程
|
|
||||||
|
|
||||||
- [使用 Gogs 搭建自己的 Git 服务器](https://blog.mynook.info/post/host-your-own-git-server-using-gogs/)
|
|
||||||
- [阿里云上 Ubuntu 14.04 64 位安装 Gogs](http://my.oschina.net/luyao/blog/375654)
|
|
||||||
|
|
||||||
## 软件、服务以及产品支持
|
|
||||||
|
|
||||||
- [Fabric8](http://fabric8.io/)(DevOps)
|
|
||||||
- [Jenkins](https://plugins.jenkins.io/gogs-webhook/)(CI)
|
|
||||||
- [Taiga](https://taiga.io/)(项目管理)
|
|
||||||
- [Puppet](https://forge.puppet.com/Siteminds/gogs)(IT)
|
|
||||||
- [Kanboard](https://github.com/kanboard/plugin-gogs-webhook)(项目管理)
|
|
||||||
- [BearyChat](https://bearychat.com/)(团队交流)
|
|
||||||
- [GitPitch](https://gitpitch.com/)(Markdown 演示)
|
|
||||||
- [Synology](https://www.synology.com)(Docker)
|
|
||||||
- [Syncloud](https://syncloud.org/)(应用商店)
|
|
||||||
|
|
||||||
## 特别鸣谢
|
|
||||||
|
|
||||||
- 感谢 [Egon Elbre](https://twitter.com/egonelbre) 设计的 Logo。
|
|
||||||
- 感谢 [DigitalOcean](https://www.digitalocean.com) 和 [MonoVM](https://monovm.com) 提供服务器赞助。
|
|
||||||
- 感谢 [Crowdin](https://crowdin.com/project/gogs) 提供免费的开源项目本地化支持。
|
|
||||||
- 感谢 [Buildkite](https://buildkite.com) 提供免费的开源项目 CI/CD 支持。
|
|
||||||
|
|
||||||
## 贡献成员
|
|
||||||
|
|
||||||
- 您可以通过查看 [贡献者页面](https://github.com/gogs/gogs/graphs/contributors) 获取 TOP 100 的贡献者列表。
|
|
||||||
- 您可以通过查看 [TRANSLATORS](conf/locale/TRANSLATORS) 文件获取公开的翻译人员列表。
|
|
||||||
|
|
||||||
## 授权许可
|
|
||||||
|
|
||||||
本项目采用 MIT 开源授权许可证,完整的授权说明已放置在 [LICENSE](https://github.com/gogs/gogs/blob/main/LICENSE) 文件中。
|
|
||||||
@@ -10,8 +10,6 @@ tasks:
|
|||||||
web:
|
web:
|
||||||
desc: Build the binary and start the web server
|
desc: Build the binary and start the web server
|
||||||
deps: [build]
|
deps: [build]
|
||||||
env:
|
|
||||||
GOGS_WORK_DIR: '{{.ROOT_DIR}}'
|
|
||||||
cmds:
|
cmds:
|
||||||
- .bin/gogs web
|
- .bin/gogs web
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import (
|
|||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
"github.com/cockroachdb/errors"
|
"github.com/cockroachdb/errors"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v3"
|
||||||
|
|
||||||
"gogs.io/gogs/internal/conf"
|
"gogs.io/gogs/internal/conf"
|
||||||
"gogs.io/gogs/internal/database"
|
"gogs.io/gogs/internal/database"
|
||||||
@@ -19,15 +19,15 @@ var (
|
|||||||
Usage: "Perform admin operations on command line",
|
Usage: "Perform admin operations on command line",
|
||||||
Description: `Allow using internal logic of Gogs without hacking into the source code
|
Description: `Allow using internal logic of Gogs without hacking into the source code
|
||||||
to make automatic initialization process more smoothly`,
|
to make automatic initialization process more smoothly`,
|
||||||
Subcommands: []cli.Command{
|
Commands: []*cli.Command{
|
||||||
subcmdCreateUser,
|
&subcmdCreateUser,
|
||||||
subcmdDeleteInactivateUsers,
|
&subcmdDeleteInactivateUsers,
|
||||||
subcmdDeleteRepositoryArchives,
|
&subcmdDeleteRepositoryArchives,
|
||||||
subcmdDeleteMissingRepositories,
|
&subcmdDeleteMissingRepositories,
|
||||||
subcmdGitGcRepos,
|
&subcmdGitGcRepos,
|
||||||
subcmdRewriteAuthorizedKeys,
|
&subcmdRewriteAuthorizedKeys,
|
||||||
subcmdSyncRepositoryHooks,
|
&subcmdSyncRepositoryHooks,
|
||||||
subcmdReinitMissingRepositories,
|
&subcmdReinitMissingRepositories,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,16 +129,16 @@ to make automatic initialization process more smoothly`,
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func runCreateUser(c *cli.Context) error {
|
func runCreateUser(ctx context.Context, cmd *cli.Command) error {
|
||||||
if !c.IsSet("name") {
|
if !cmd.IsSet("name") {
|
||||||
return errors.New("Username is not specified")
|
return errors.New("Username is not specified")
|
||||||
} else if !c.IsSet("password") {
|
} else if !cmd.IsSet("password") {
|
||||||
return errors.New("Password is not specified")
|
return errors.New("Password is not specified")
|
||||||
} else if !c.IsSet("email") {
|
} else if !cmd.IsSet("email") {
|
||||||
return errors.New("Email is not specified")
|
return errors.New("Email is not specified")
|
||||||
}
|
}
|
||||||
|
|
||||||
err := conf.Init(c.String("config"))
|
err := conf.Init(configFromLineage(cmd))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "init configuration")
|
return errors.Wrap(err, "init configuration")
|
||||||
}
|
}
|
||||||
@@ -149,13 +149,13 @@ func runCreateUser(c *cli.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
user, err := database.Handle.Users().Create(
|
user, err := database.Handle.Users().Create(
|
||||||
context.Background(),
|
ctx,
|
||||||
c.String("name"),
|
cmd.String("name"),
|
||||||
c.String("email"),
|
cmd.String("email"),
|
||||||
database.CreateUserOptions{
|
database.CreateUserOptions{
|
||||||
Password: c.String("password"),
|
Password: cmd.String("password"),
|
||||||
Activated: true,
|
Activated: true,
|
||||||
Admin: c.Bool("admin"),
|
Admin: cmd.Bool("admin"),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -166,9 +166,9 @@ func runCreateUser(c *cli.Context) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func adminDashboardOperation(operation func() error, successMessage string) func(*cli.Context) error {
|
func adminDashboardOperation(operation func() error, successMessage string) func(context.Context, *cli.Command) error {
|
||||||
return func(c *cli.Context) error {
|
return func(_ context.Context, cmd *cli.Command) error {
|
||||||
err := conf.Init(c.String("config"))
|
err := conf.Init(configFromLineage(cmd))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "init configuration")
|
return errors.Wrap(err, "init configuration")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,13 +11,13 @@ import (
|
|||||||
|
|
||||||
"github.com/cockroachdb/errors"
|
"github.com/cockroachdb/errors"
|
||||||
"github.com/unknwon/cae/zip"
|
"github.com/unknwon/cae/zip"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v3"
|
||||||
"gopkg.in/ini.v1"
|
"gopkg.in/ini.v1"
|
||||||
log "unknwon.dev/clog/v2"
|
log "unknwon.dev/clog/v2"
|
||||||
|
|
||||||
"gogs.io/gogs/internal/conf"
|
"gogs.io/gogs/internal/conf"
|
||||||
"gogs.io/gogs/internal/database"
|
"gogs.io/gogs/internal/database"
|
||||||
"gogs.io/gogs/internal/osutil"
|
"gogs.io/gogs/internal/osx"
|
||||||
)
|
)
|
||||||
|
|
||||||
var backupCommand = cli.Command{
|
var backupCommand = cli.Command{
|
||||||
@@ -44,10 +44,10 @@ const (
|
|||||||
archiveRootDir = "gogs-backup"
|
archiveRootDir = "gogs-backup"
|
||||||
)
|
)
|
||||||
|
|
||||||
func runBackup(c *cli.Context) error {
|
func runBackup(ctx context.Context, cmd *cli.Command) error {
|
||||||
zip.Verbose = c.Bool("verbose")
|
zip.Verbose = cmd.Bool("verbose")
|
||||||
|
|
||||||
err := conf.Init(c.String("config"))
|
err := conf.Init(configFromLineage(cmd))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "init configuration")
|
return errors.Wrap(err, "init configuration")
|
||||||
}
|
}
|
||||||
@@ -58,8 +58,8 @@ func runBackup(c *cli.Context) error {
|
|||||||
return errors.Wrap(err, "set engine")
|
return errors.Wrap(err, "set engine")
|
||||||
}
|
}
|
||||||
|
|
||||||
tmpDir := c.String("tempdir")
|
tmpDir := cmd.String("tempdir")
|
||||||
if !osutil.Exist(tmpDir) {
|
if !osx.Exist(tmpDir) {
|
||||||
log.Fatal("'--tempdir' does not exist: %s", tmpDir)
|
log.Fatal("'--tempdir' does not exist: %s", tmpDir)
|
||||||
}
|
}
|
||||||
rootDir, err := os.MkdirTemp(tmpDir, "gogs-backup-")
|
rootDir, err := os.MkdirTemp(tmpDir, "gogs-backup-")
|
||||||
@@ -78,7 +78,7 @@ func runBackup(c *cli.Context) error {
|
|||||||
log.Fatal("Failed to save metadata '%s': %v", metaFile, err)
|
log.Fatal("Failed to save metadata '%s': %v", metaFile, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
archiveName := filepath.Join(c.String("target"), c.String("archive-name"))
|
archiveName := filepath.Join(cmd.String("target"), cmd.String("archive-name"))
|
||||||
log.Info("Packing backup files to: %s", archiveName)
|
log.Info("Packing backup files to: %s", archiveName)
|
||||||
|
|
||||||
z, err := zip.Create(archiveName)
|
z, err := zip.Create(archiveName)
|
||||||
@@ -91,14 +91,14 @@ func runBackup(c *cli.Context) error {
|
|||||||
|
|
||||||
// Database
|
// Database
|
||||||
dbDir := filepath.Join(rootDir, "db")
|
dbDir := filepath.Join(rootDir, "db")
|
||||||
if err = database.DumpDatabase(context.Background(), conn, dbDir, c.Bool("verbose")); err != nil {
|
if err = database.DumpDatabase(ctx, conn, dbDir, cmd.Bool("verbose")); err != nil {
|
||||||
log.Fatal("Failed to dump database: %v", err)
|
log.Fatal("Failed to dump database: %v", err)
|
||||||
}
|
}
|
||||||
if err = z.AddDir(archiveRootDir+"/db", dbDir); err != nil {
|
if err = z.AddDir(archiveRootDir+"/db", dbDir); err != nil {
|
||||||
log.Fatal("Failed to include 'db': %v", err)
|
log.Fatal("Failed to include 'db': %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !c.Bool("database-only") {
|
if !cmd.Bool("database-only") {
|
||||||
// Custom files
|
// Custom files
|
||||||
err = addCustomDirToBackup(z)
|
err = addCustomDirToBackup(z)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -108,7 +108,7 @@ func runBackup(c *cli.Context) error {
|
|||||||
// Data files
|
// Data files
|
||||||
for _, dir := range []string{"ssh", "attachments", "avatars", "repo-avatars"} {
|
for _, dir := range []string{"ssh", "attachments", "avatars", "repo-avatars"} {
|
||||||
dirPath := filepath.Join(conf.Server.AppDataPath, dir)
|
dirPath := filepath.Join(conf.Server.AppDataPath, dir)
|
||||||
if !osutil.IsDir(dirPath) {
|
if !osx.IsDir(dirPath) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,10 +119,10 @@ func runBackup(c *cli.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Repositories
|
// Repositories
|
||||||
if !c.Bool("exclude-repos") && !c.Bool("database-only") {
|
if !cmd.Bool("exclude-repos") && !cmd.Bool("database-only") {
|
||||||
reposDump := filepath.Join(rootDir, "repositories.zip")
|
reposDump := filepath.Join(rootDir, "repositories.zip")
|
||||||
log.Info("Dumping repositories in %q", conf.Repository.Root)
|
log.Info("Dumping repositories in %q", conf.Repository.Root)
|
||||||
if c.Bool("exclude-mirror-repos") {
|
if cmd.Bool("exclude-mirror-repos") {
|
||||||
repos, err := database.GetNonMirrorRepositories()
|
repos, err := database.GetNonMirrorRepositories()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("Failed to get non-mirror repositories: %v", err)
|
log.Fatal("Failed to get non-mirror repositories: %v", err)
|
||||||
|
|||||||
@@ -1,20 +1,43 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/urfave/cli"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/urfave/cli/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
func stringFlag(name, value, usage string) cli.StringFlag {
|
func stringFlag(name, value, usage string) *cli.StringFlag {
|
||||||
return cli.StringFlag{
|
parts := strings.SplitN(name, ", ", 2)
|
||||||
Name: name,
|
f := &cli.StringFlag{
|
||||||
|
Name: parts[0],
|
||||||
Value: value,
|
Value: value,
|
||||||
Usage: usage,
|
Usage: usage,
|
||||||
}
|
}
|
||||||
|
if len(parts) > 1 {
|
||||||
|
f.Aliases = []string{parts[1]}
|
||||||
|
}
|
||||||
|
return f
|
||||||
}
|
}
|
||||||
|
|
||||||
func boolFlag(name, usage string) cli.BoolFlag {
|
// configFromLineage walks the command lineage to find the --config flag value.
|
||||||
return cli.BoolFlag{
|
// This is needed because subcommands may not directly see flags set on parent commands.
|
||||||
Name: name,
|
func configFromLineage(cmd *cli.Command) string {
|
||||||
|
for _, c := range cmd.Lineage() {
|
||||||
|
if c.IsSet("config") {
|
||||||
|
return c.String("config")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func boolFlag(name, usage string) *cli.BoolFlag {
|
||||||
|
parts := strings.SplitN(name, ", ", 2)
|
||||||
|
f := &cli.BoolFlag{
|
||||||
|
Name: parts[0],
|
||||||
Usage: usage,
|
Usage: usage,
|
||||||
}
|
}
|
||||||
|
if len(parts) > 1 {
|
||||||
|
f.Aliases = []string{parts[1]}
|
||||||
|
}
|
||||||
|
return f
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package main
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/url"
|
"net/url"
|
||||||
@@ -12,7 +13,7 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v3"
|
||||||
log "unknwon.dev/clog/v2"
|
log "unknwon.dev/clog/v2"
|
||||||
|
|
||||||
"github.com/gogs/git-module"
|
"github.com/gogs/git-module"
|
||||||
@@ -21,7 +22,7 @@ import (
|
|||||||
"gogs.io/gogs/internal/database"
|
"gogs.io/gogs/internal/database"
|
||||||
"gogs.io/gogs/internal/email"
|
"gogs.io/gogs/internal/email"
|
||||||
"gogs.io/gogs/internal/httplib"
|
"gogs.io/gogs/internal/httplib"
|
||||||
"gogs.io/gogs/internal/osutil"
|
"gogs.io/gogs/internal/osx"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -32,10 +33,10 @@ var (
|
|||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
stringFlag("config, c", "", "Custom configuration file path"),
|
stringFlag("config, c", "", "Custom configuration file path"),
|
||||||
},
|
},
|
||||||
Subcommands: []cli.Command{
|
Commands: []*cli.Command{
|
||||||
subcmdHookPreReceive,
|
&subcmdHookPreReceive,
|
||||||
subcmdHookUpadte,
|
&subcmdHookUpadte,
|
||||||
subcmdHookPostReceive,
|
&subcmdHookPostReceive,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,11 +60,11 @@ var (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func runHookPreReceive(c *cli.Context) error {
|
func runHookPreReceive(_ context.Context, cmd *cli.Command) error {
|
||||||
if os.Getenv("SSH_ORIGINAL_COMMAND") == "" {
|
if os.Getenv("SSH_ORIGINAL_COMMAND") == "" {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
setup(c, "pre-receive.log", true)
|
setup(cmd, "pre-receive.log", true)
|
||||||
|
|
||||||
isWiki := strings.Contains(os.Getenv(database.EnvRepoCustomHooksPath), ".wiki.git/")
|
isWiki := strings.Contains(os.Getenv(database.EnvRepoCustomHooksPath), ".wiki.git/")
|
||||||
|
|
||||||
@@ -132,7 +133,7 @@ func runHookPreReceive(c *cli.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
customHooksPath := filepath.Join(os.Getenv(database.EnvRepoCustomHooksPath), "pre-receive")
|
customHooksPath := filepath.Join(os.Getenv(database.EnvRepoCustomHooksPath), "pre-receive")
|
||||||
if !osutil.IsFile(customHooksPath) {
|
if !osx.IsFile(customHooksPath) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,13 +153,13 @@ func runHookPreReceive(c *cli.Context) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func runHookUpdate(c *cli.Context) error {
|
func runHookUpdate(_ context.Context, cmd *cli.Command) error {
|
||||||
if os.Getenv("SSH_ORIGINAL_COMMAND") == "" {
|
if os.Getenv("SSH_ORIGINAL_COMMAND") == "" {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
setup(c, "update.log", false)
|
setup(cmd, "update.log", false)
|
||||||
|
|
||||||
args := c.Args()
|
args := cmd.Args().Slice()
|
||||||
if len(args) != 3 {
|
if len(args) != 3 {
|
||||||
fail("Arguments received are not equal to three", "Arguments received are not equal to three")
|
fail("Arguments received are not equal to three", "Arguments received are not equal to three")
|
||||||
} else if args[0] == "" {
|
} else if args[0] == "" {
|
||||||
@@ -166,7 +167,7 @@ func runHookUpdate(c *cli.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
customHooksPath := filepath.Join(os.Getenv(database.EnvRepoCustomHooksPath), "update")
|
customHooksPath := filepath.Join(os.Getenv(database.EnvRepoCustomHooksPath), "update")
|
||||||
if !osutil.IsFile(customHooksPath) {
|
if !osx.IsFile(customHooksPath) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,11 +187,11 @@ func runHookUpdate(c *cli.Context) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func runHookPostReceive(c *cli.Context) error {
|
func runHookPostReceive(_ context.Context, cmd *cli.Command) error {
|
||||||
if os.Getenv("SSH_ORIGINAL_COMMAND") == "" {
|
if os.Getenv("SSH_ORIGINAL_COMMAND") == "" {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
setup(c, "post-receive.log", true)
|
setup(cmd, "post-receive.log", true)
|
||||||
|
|
||||||
// Post-receive hook does more than just gather Git information,
|
// Post-receive hook does more than just gather Git information,
|
||||||
// so we need to setup additional services for email notifications.
|
// so we need to setup additional services for email notifications.
|
||||||
@@ -251,7 +252,7 @@ func runHookPostReceive(c *cli.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
customHooksPath := filepath.Join(os.Getenv(database.EnvRepoCustomHooksPath), "post-receive")
|
customHooksPath := filepath.Join(os.Getenv(database.EnvRepoCustomHooksPath), "post-receive")
|
||||||
if !osutil.IsFile(customHooksPath) {
|
if !osx.IsFile(customHooksPath) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,16 +3,17 @@ package main
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/cockroachdb/errors"
|
"github.com/cockroachdb/errors"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v3"
|
||||||
|
|
||||||
"gogs.io/gogs/internal/conf"
|
"gogs.io/gogs/internal/conf"
|
||||||
"gogs.io/gogs/internal/osutil"
|
"gogs.io/gogs/internal/osx"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -21,8 +22,8 @@ var (
|
|||||||
Usage: "Import portable data as local Gogs data",
|
Usage: "Import portable data as local Gogs data",
|
||||||
Description: `Allow user import data from other Gogs installations to local instance
|
Description: `Allow user import data from other Gogs installations to local instance
|
||||||
without manually hacking the data files`,
|
without manually hacking the data files`,
|
||||||
Subcommands: []cli.Command{
|
Commands: []*cli.Command{
|
||||||
subcmdImportLocale,
|
&subcmdImportLocale,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,19 +39,19 @@ without manually hacking the data files`,
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func runImportLocale(c *cli.Context) error {
|
func runImportLocale(_ context.Context, cmd *cli.Command) error {
|
||||||
if !c.IsSet("source") {
|
if !cmd.IsSet("source") {
|
||||||
return errors.New("source directory is not specified")
|
return errors.New("source directory is not specified")
|
||||||
} else if !c.IsSet("target") {
|
} else if !cmd.IsSet("target") {
|
||||||
return errors.New("target directory is not specified")
|
return errors.New("target directory is not specified")
|
||||||
}
|
}
|
||||||
if !osutil.IsDir(c.String("source")) {
|
if !osx.IsDir(cmd.String("source")) {
|
||||||
return errors.Newf("source directory %q does not exist or is not a directory", c.String("source"))
|
return errors.Newf("source directory %q does not exist or is not a directory", cmd.String("source"))
|
||||||
} else if !osutil.IsDir(c.String("target")) {
|
} else if !osx.IsDir(cmd.String("target")) {
|
||||||
return errors.Newf("target directory %q does not exist or is not a directory", c.String("target"))
|
return errors.Newf("target directory %q does not exist or is not a directory", cmd.String("target"))
|
||||||
}
|
}
|
||||||
|
|
||||||
err := conf.Init(c.String("config"))
|
err := conf.Init(configFromLineage(cmd))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "init configuration")
|
return errors.Wrap(err, "init configuration")
|
||||||
}
|
}
|
||||||
@@ -64,9 +65,9 @@ func runImportLocale(c *cli.Context) error {
|
|||||||
// Cut out en-US.
|
// Cut out en-US.
|
||||||
for _, lang := range conf.I18n.Langs[1:] {
|
for _, lang := range conf.I18n.Langs[1:] {
|
||||||
name := fmt.Sprintf("locale_%s.ini", lang)
|
name := fmt.Sprintf("locale_%s.ini", lang)
|
||||||
source := filepath.Join(c.String("source"), name)
|
source := filepath.Join(cmd.String("source"), name)
|
||||||
target := filepath.Join(c.String("target"), name)
|
target := filepath.Join(cmd.String("target"), name)
|
||||||
if !osutil.IsFile(source) {
|
if !osx.IsFile(source) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,9 +2,10 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v3"
|
||||||
log "unknwon.dev/clog/v2"
|
log "unknwon.dev/clog/v2"
|
||||||
|
|
||||||
"gogs.io/gogs/internal/conf"
|
"gogs.io/gogs/internal/conf"
|
||||||
@@ -15,20 +16,21 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
app := cli.NewApp()
|
cmd := &cli.Command{
|
||||||
app.Name = "Gogs"
|
Name: "Gogs",
|
||||||
app.Usage = "A painless self-hosted Git service"
|
Usage: "A painless self-hosted Git service",
|
||||||
app.Version = conf.App.Version
|
Version: conf.App.Version,
|
||||||
app.Commands = []cli.Command{
|
Commands: []*cli.Command{
|
||||||
webCommand,
|
&webCommand,
|
||||||
servCommand,
|
&servCommand,
|
||||||
hookCommand,
|
&hookCommand,
|
||||||
adminCommand,
|
&adminCommand,
|
||||||
importCommand,
|
&importCommand,
|
||||||
backupCommand,
|
&backupCommand,
|
||||||
restoreCommand,
|
&restoreCommand,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
if err := app.Run(os.Args); err != nil {
|
if err := cmd.Run(context.Background(), os.Args); err != nil {
|
||||||
log.Fatal("Failed to start application: %v", err)
|
log.Fatal("Failed to start application: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,14 +8,14 @@ import (
|
|||||||
|
|
||||||
"github.com/cockroachdb/errors"
|
"github.com/cockroachdb/errors"
|
||||||
"github.com/unknwon/cae/zip"
|
"github.com/unknwon/cae/zip"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v3"
|
||||||
"gopkg.in/ini.v1"
|
"gopkg.in/ini.v1"
|
||||||
log "unknwon.dev/clog/v2"
|
log "unknwon.dev/clog/v2"
|
||||||
|
|
||||||
"gogs.io/gogs/internal/conf"
|
"gogs.io/gogs/internal/conf"
|
||||||
"gogs.io/gogs/internal/database"
|
"gogs.io/gogs/internal/database"
|
||||||
"gogs.io/gogs/internal/osutil"
|
"gogs.io/gogs/internal/osx"
|
||||||
"gogs.io/gogs/internal/semverutil"
|
"gogs.io/gogs/internal/semverx"
|
||||||
)
|
)
|
||||||
|
|
||||||
var restoreCommand = cli.Command{
|
var restoreCommand = cli.Command{
|
||||||
@@ -42,11 +42,11 @@ be skipped and remain unchanged.`,
|
|||||||
// format that is able to import.
|
// format that is able to import.
|
||||||
var lastSupportedVersionOfFormat = map[int]string{}
|
var lastSupportedVersionOfFormat = map[int]string{}
|
||||||
|
|
||||||
func runRestore(c *cli.Context) error {
|
func runRestore(ctx context.Context, cmd *cli.Command) error {
|
||||||
zip.Verbose = c.Bool("verbose")
|
zip.Verbose = cmd.Bool("verbose")
|
||||||
|
|
||||||
tmpDir := c.String("tempdir")
|
tmpDir := cmd.String("tempdir")
|
||||||
if !osutil.IsDir(tmpDir) {
|
if !osx.IsDir(tmpDir) {
|
||||||
log.Fatal("'--tempdir' does not exist: %s", tmpDir)
|
log.Fatal("'--tempdir' does not exist: %s", tmpDir)
|
||||||
}
|
}
|
||||||
archivePath := path.Join(tmpDir, archiveRootDir)
|
archivePath := path.Join(tmpDir, archiveRootDir)
|
||||||
@@ -58,15 +58,15 @@ func runRestore(c *cli.Context) error {
|
|||||||
}
|
}
|
||||||
defer func() { _ = os.RemoveAll(archivePath) }()
|
defer func() { _ = os.RemoveAll(archivePath) }()
|
||||||
|
|
||||||
log.Info("Restoring backup from: %s", c.String("from"))
|
log.Info("Restoring backup from: %s", cmd.String("from"))
|
||||||
err = zip.ExtractTo(c.String("from"), tmpDir)
|
err = zip.ExtractTo(cmd.String("from"), tmpDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("Failed to extract backup archive: %v", err)
|
log.Fatal("Failed to extract backup archive: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check backup version
|
// Check backup version
|
||||||
metaFile := filepath.Join(archivePath, "metadata.ini")
|
metaFile := filepath.Join(archivePath, "metadata.ini")
|
||||||
if !osutil.IsFile(metaFile) {
|
if !osx.IsFile(metaFile) {
|
||||||
log.Fatal("File 'metadata.ini' is missing")
|
log.Fatal("File 'metadata.ini' is missing")
|
||||||
}
|
}
|
||||||
metadata, err := ini.Load(metaFile)
|
metadata, err := ini.Load(metaFile)
|
||||||
@@ -74,7 +74,7 @@ func runRestore(c *cli.Context) error {
|
|||||||
log.Fatal("Failed to load metadata '%s': %v", metaFile, err)
|
log.Fatal("Failed to load metadata '%s': %v", metaFile, err)
|
||||||
}
|
}
|
||||||
backupVersion := metadata.Section("").Key("GOGS_VERSION").MustString("999.0")
|
backupVersion := metadata.Section("").Key("GOGS_VERSION").MustString("999.0")
|
||||||
if semverutil.Compare(conf.App.Version, "<", backupVersion) {
|
if semverx.Compare(conf.App.Version, "<", backupVersion) {
|
||||||
log.Fatal("Current Gogs version is lower than backup version: %s < %s", conf.App.Version, backupVersion)
|
log.Fatal("Current Gogs version is lower than backup version: %s < %s", conf.App.Version, backupVersion)
|
||||||
}
|
}
|
||||||
formatVersion := metadata.Section("").Key("VERSION").MustInt()
|
formatVersion := metadata.Section("").Key("VERSION").MustInt()
|
||||||
@@ -90,9 +90,9 @@ func runRestore(c *cli.Context) error {
|
|||||||
// Otherwise, it's optional to set config file flag.
|
// Otherwise, it's optional to set config file flag.
|
||||||
configFile := filepath.Join(archivePath, "custom", "conf", "app.ini")
|
configFile := filepath.Join(archivePath, "custom", "conf", "app.ini")
|
||||||
var customConf string
|
var customConf string
|
||||||
if c.IsSet("config") {
|
if lineageConf := configFromLineage(cmd); lineageConf != "" {
|
||||||
customConf = c.String("config")
|
customConf = lineageConf
|
||||||
} else if !osutil.IsFile(configFile) {
|
} else if !osx.IsFile(configFile) {
|
||||||
log.Fatal("'--config' is not specified and custom config file is not found in backup")
|
log.Fatal("'--config' is not specified and custom config file is not found in backup")
|
||||||
} else {
|
} else {
|
||||||
customConf = configFile
|
customConf = configFile
|
||||||
@@ -111,13 +111,13 @@ func runRestore(c *cli.Context) error {
|
|||||||
|
|
||||||
// Database
|
// Database
|
||||||
dbDir := path.Join(archivePath, "db")
|
dbDir := path.Join(archivePath, "db")
|
||||||
if err = database.ImportDatabase(context.Background(), conn, dbDir, c.Bool("verbose")); err != nil {
|
if err = database.ImportDatabase(ctx, conn, dbDir, cmd.Bool("verbose")); err != nil {
|
||||||
log.Fatal("Failed to import database: %v", err)
|
log.Fatal("Failed to import database: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !c.Bool("database-only") {
|
if !cmd.Bool("database-only") {
|
||||||
// Custom files
|
// Custom files
|
||||||
if osutil.IsDir(conf.CustomDir()) {
|
if osx.IsDir(conf.CustomDir()) {
|
||||||
if err = os.Rename(conf.CustomDir(), conf.CustomDir()+".bak"); err != nil {
|
if err = os.Rename(conf.CustomDir(), conf.CustomDir()+".bak"); err != nil {
|
||||||
log.Fatal("Failed to backup current 'custom': %v", err)
|
log.Fatal("Failed to backup current 'custom': %v", err)
|
||||||
}
|
}
|
||||||
@@ -131,12 +131,12 @@ func runRestore(c *cli.Context) error {
|
|||||||
for _, dir := range []string{"attachments", "avatars", "repo-avatars"} {
|
for _, dir := range []string{"attachments", "avatars", "repo-avatars"} {
|
||||||
// Skip if backup archive does not have corresponding data
|
// Skip if backup archive does not have corresponding data
|
||||||
srcPath := filepath.Join(archivePath, "data", dir)
|
srcPath := filepath.Join(archivePath, "data", dir)
|
||||||
if !osutil.IsDir(srcPath) {
|
if !osx.IsDir(srcPath) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
dirPath := filepath.Join(conf.Server.AppDataPath, dir)
|
dirPath := filepath.Join(conf.Server.AppDataPath, dir)
|
||||||
if osutil.IsDir(dirPath) {
|
if osx.IsDir(dirPath) {
|
||||||
if err = os.Rename(dirPath, dirPath+".bak"); err != nil {
|
if err = os.Rename(dirPath, dirPath+".bak"); err != nil {
|
||||||
log.Fatal("Failed to backup current 'data': %v", err)
|
log.Fatal("Failed to backup current 'data': %v", err)
|
||||||
}
|
}
|
||||||
@@ -149,7 +149,7 @@ func runRestore(c *cli.Context) error {
|
|||||||
|
|
||||||
// Repositories
|
// Repositories
|
||||||
reposPath := filepath.Join(archivePath, "repositories.zip")
|
reposPath := filepath.Join(archivePath, "repositories.zip")
|
||||||
if !c.Bool("exclude-repos") && !c.Bool("database-only") && osutil.IsFile(reposPath) {
|
if !cmd.Bool("exclude-repos") && !cmd.Bool("database-only") && osx.IsFile(reposPath) {
|
||||||
if err := zip.ExtractTo(reposPath, filepath.Dir(conf.Repository.Root)); err != nil {
|
if err := zip.ExtractTo(reposPath, filepath.Dir(conf.Repository.Root)); err != nil {
|
||||||
log.Fatal("Failed to extract 'repositories.zip': %v", err)
|
log.Fatal("Failed to extract 'repositories.zip': %v", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v3"
|
||||||
log "unknwon.dev/clog/v2"
|
log "unknwon.dev/clog/v2"
|
||||||
|
|
||||||
"gogs.io/gogs/internal/conf"
|
"gogs.io/gogs/internal/conf"
|
||||||
@@ -48,15 +48,10 @@ func fail(userMessage, errMessage string, args ...any) {
|
|||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func setup(c *cli.Context, logFile string, connectDB bool) {
|
func setup(cmd *cli.Command, logFile string, connectDB bool) {
|
||||||
conf.HookMode = true
|
conf.HookMode = true
|
||||||
|
|
||||||
var customConf string
|
customConf := configFromLineage(cmd)
|
||||||
if c.IsSet("config") {
|
|
||||||
customConf = c.String("config")
|
|
||||||
} else if c.GlobalIsSet("config") {
|
|
||||||
customConf = c.GlobalString("config")
|
|
||||||
}
|
|
||||||
|
|
||||||
err := conf.Init(customConf)
|
err := conf.Init(customConf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -128,16 +123,15 @@ var allowedCommands = map[string]database.AccessMode{
|
|||||||
"git-receive-pack": database.AccessModeWrite,
|
"git-receive-pack": database.AccessModeWrite,
|
||||||
}
|
}
|
||||||
|
|
||||||
func runServ(c *cli.Context) error {
|
func runServ(ctx context.Context, cmd *cli.Command) error {
|
||||||
ctx := context.Background()
|
setup(cmd, "serv.log", true)
|
||||||
setup(c, "serv.log", true)
|
|
||||||
|
|
||||||
if conf.SSH.Disabled {
|
if conf.SSH.Disabled {
|
||||||
println("Gogs: SSH has been disabled")
|
println("Gogs: SSH has been disabled")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(c.Args()) < 1 {
|
if cmd.Args().Len() < 1 {
|
||||||
fail("Not enough arguments", "Not enough arguments")
|
fail("Not enough arguments", "Not enough arguments")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,10 +182,10 @@ func runServ(c *cli.Context) error {
|
|||||||
// Allow anonymous (user is nil) clone for public repositories.
|
// Allow anonymous (user is nil) clone for public repositories.
|
||||||
var user *database.User
|
var user *database.User
|
||||||
|
|
||||||
keyID, _ := strconv.ParseInt(strings.TrimPrefix(c.Args()[0], "key-"), 10, 64)
|
keyID, _ := strconv.ParseInt(strings.TrimPrefix(cmd.Args().Get(0), "key-"), 10, 64)
|
||||||
key, err := database.GetPublicKeyByID(keyID)
|
key, err := database.GetPublicKeyByID(keyID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fail("Invalid key ID", "Invalid key ID '%s': %v", c.Args()[0], err)
|
fail("Invalid key ID", "Invalid key ID '%s': %v", cmd.Args().Get(0), err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if requestMode == database.AccessModeWrite || repo.IsPrivate {
|
if requestMode == database.AccessModeWrite || repo.IsPrivate {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
stdctx "context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
@@ -20,7 +21,7 @@ import (
|
|||||||
"github.com/go-macaron/session"
|
"github.com/go-macaron/session"
|
||||||
"github.com/go-macaron/toolbox"
|
"github.com/go-macaron/toolbox"
|
||||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v3"
|
||||||
"gopkg.in/macaron.v1"
|
"gopkg.in/macaron.v1"
|
||||||
log "unknwon.dev/clog/v2"
|
log "unknwon.dev/clog/v2"
|
||||||
|
|
||||||
@@ -30,7 +31,7 @@ import (
|
|||||||
"gogs.io/gogs/internal/context"
|
"gogs.io/gogs/internal/context"
|
||||||
"gogs.io/gogs/internal/database"
|
"gogs.io/gogs/internal/database"
|
||||||
"gogs.io/gogs/internal/form"
|
"gogs.io/gogs/internal/form"
|
||||||
"gogs.io/gogs/internal/osutil"
|
"gogs.io/gogs/internal/osx"
|
||||||
"gogs.io/gogs/internal/route"
|
"gogs.io/gogs/internal/route"
|
||||||
"gogs.io/gogs/internal/route/admin"
|
"gogs.io/gogs/internal/route/admin"
|
||||||
apiv1 "gogs.io/gogs/internal/route/api/v1"
|
apiv1 "gogs.io/gogs/internal/route/api/v1"
|
||||||
@@ -158,8 +159,8 @@ func newMacaron() *macaron.Macaron {
|
|||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
func runWeb(c *cli.Context) error {
|
func runWeb(_ stdctx.Context, cmd *cli.Command) error {
|
||||||
err := route.GlobalInit(c.String("config"))
|
err := route.GlobalInit(configFromLineage(cmd))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("Failed to initialize application: %v", err)
|
log.Fatal("Failed to initialize application: %v", err)
|
||||||
}
|
}
|
||||||
@@ -307,7 +308,7 @@ func runWeb(c *cli.Context) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
c.NotFoundOrError(err, "get attachment by UUID")
|
c.NotFoundOrError(err, "get attachment by UUID")
|
||||||
return
|
return
|
||||||
} else if !osutil.IsFile(attach.LocalPath()) {
|
} else if !osx.IsFile(attach.LocalPath()) {
|
||||||
c.NotFound()
|
c.NotFound()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -697,10 +698,10 @@ func runWeb(c *cli.Context) error {
|
|||||||
m.NotFound(route.NotFound)
|
m.NotFound(route.NotFound)
|
||||||
|
|
||||||
// Flag for port number in case first time run conflict.
|
// Flag for port number in case first time run conflict.
|
||||||
if c.IsSet("port") {
|
if cmd.IsSet("port") {
|
||||||
conf.Server.URL.Host = strings.Replace(conf.Server.URL.Host, ":"+conf.Server.URL.Port(), ":"+c.String("port"), 1)
|
conf.Server.URL.Host = strings.Replace(conf.Server.URL.Host, ":"+conf.Server.URL.Port(), ":"+cmd.String("port"), 1)
|
||||||
conf.Server.ExternalURL = conf.Server.URL.String()
|
conf.Server.ExternalURL = conf.Server.URL.String()
|
||||||
conf.Server.HTTPPort = c.String("port")
|
conf.Server.HTTPPort = cmd.String("port")
|
||||||
}
|
}
|
||||||
|
|
||||||
var listenAddr string
|
var listenAddr string
|
||||||
@@ -749,7 +750,7 @@ func runWeb(c *cli.Context) error {
|
|||||||
err = fcgi.Serve(nil, m)
|
err = fcgi.Serve(nil, m)
|
||||||
|
|
||||||
case "unix":
|
case "unix":
|
||||||
if osutil.Exist(listenAddr) {
|
if osx.Exist(listenAddr) {
|
||||||
err = os.Remove(listenAddr)
|
err = os.Remove(listenAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("Failed to remove existing Unix domain socket: %v", err)
|
log.Fatal("Failed to remove existing Unix domain socket: %v", err)
|
||||||
|
|||||||
@@ -141,8 +141,7 @@ FILE_MAX_SIZE = 3
|
|||||||
MAX_FILES = 5
|
MAX_FILES = 5
|
||||||
|
|
||||||
[database]
|
[database]
|
||||||
; The database backend, either "postgres", "mysql" "sqlite3" or "mssql".
|
; The database backend, either "postgres", "mysql" or "sqlite3".
|
||||||
; You can connect to TiDB with MySQL protocol.
|
|
||||||
TYPE = postgres
|
TYPE = postgres
|
||||||
HOST = 127.0.0.1:5432
|
HOST = 127.0.0.1:5432
|
||||||
NAME = gogs
|
NAME = gogs
|
||||||
@@ -197,8 +196,6 @@ USER = noreply@gogs.localhost
|
|||||||
; The login password.
|
; The login password.
|
||||||
PASSWORD =
|
PASSWORD =
|
||||||
|
|
||||||
; Whether to disable HELO operation when the hostname is different.
|
|
||||||
DISABLE_HELO =
|
|
||||||
; The custom hostname for HELO operation, default is from system.
|
; The custom hostname for HELO operation, default is from system.
|
||||||
HELO_HOSTNAME =
|
HELO_HOSTNAME =
|
||||||
|
|
||||||
@@ -279,6 +276,8 @@ ACCESS_CONTROL_ALLOW_ORIGIN =
|
|||||||
STORAGE = local
|
STORAGE = local
|
||||||
; The root path to store LFS objects on local file system.
|
; The root path to store LFS objects on local file system.
|
||||||
OBJECTS_PATH = data/lfs-objects
|
OBJECTS_PATH = data/lfs-objects
|
||||||
|
; The path to temporarily store LFS objects during upload verification.
|
||||||
|
OBJECTS_TEMP_PATH = data/tmp/lfs-objects
|
||||||
|
|
||||||
[attachment]
|
[attachment]
|
||||||
; Whether to enabled upload attachments in general.
|
; Whether to enabled upload attachments in general.
|
||||||
|
|||||||
@@ -120,7 +120,6 @@ confirm_password = Confirm Password
|
|||||||
admin_email = Admin Email
|
admin_email = Admin Email
|
||||||
install_gogs = Install Gogs
|
install_gogs = Install Gogs
|
||||||
test_git_failed = Failed to test 'git' command: %v
|
test_git_failed = Failed to test 'git' command: %v
|
||||||
sqlite3_not_available = Your release version does not support SQLite3, please download the official binary version from %s, NOT the gobuild version.
|
|
||||||
invalid_db_setting = Database setting is not correct: %v
|
invalid_db_setting = Database setting is not correct: %v
|
||||||
invalid_repo_path = Repository root path is invalid: %v
|
invalid_repo_path = Repository root path is invalid: %v
|
||||||
run_user_not_match = Run user isn't the current user: %s -> %s
|
run_user_not_match = Run user isn't the current user: %s -> %s
|
||||||
@@ -1263,7 +1262,6 @@ config.email.subject_prefix = Subject prefix
|
|||||||
config.email.host = Host
|
config.email.host = Host
|
||||||
config.email.from = From
|
config.email.from = From
|
||||||
config.email.user = User
|
config.email.user = User
|
||||||
config.email.disable_helo = Disable HELO
|
|
||||||
config.email.helo_hostname = HELO hostname
|
config.email.helo_hostname = HELO hostname
|
||||||
config.email.skip_verify = Skip certificate verify
|
config.email.skip_verify = Skip certificate verify
|
||||||
config.email.use_certificate = Use custom certificate
|
config.email.use_certificate = Use custom certificate
|
||||||
|
|||||||
67
docs/advancing/cli-reference.mdx
Normal file
67
docs/advancing/cli-reference.mdx
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
---
|
||||||
|
title: "CLI reference"
|
||||||
|
description: "Discover all the commands available in the gogs binary"
|
||||||
|
icon: "terminal"
|
||||||
|
---
|
||||||
|
|
||||||
|
Most people know `gogs web` for starting the server, but the `gogs` binary ships with several other commands that help you manage your instance from the command line.
|
||||||
|
|
||||||
|
Run `gogs --help` at any time to see the full list of available commands, and `gogs <command> --help` for details on a specific command.
|
||||||
|
|
||||||
|
<Tip>
|
||||||
|
Every command accepts a `--config` (`-c`) flag to specify a custom configuration file path. The default is `custom/conf/app.ini`.
|
||||||
|
</Tip>
|
||||||
|
|
||||||
|
## Starting the server
|
||||||
|
|
||||||
|
```bash
|
||||||
|
gogs web
|
||||||
|
```
|
||||||
|
|
||||||
|
The `web` command starts the HTTP server that powers the web UI, the REST API, and Git HTTP operations. Use the `--port` (`-p`) flag to override the default listening port.
|
||||||
|
|
||||||
|
## Administration
|
||||||
|
|
||||||
|
```bash
|
||||||
|
gogs admin <subcommand>
|
||||||
|
```
|
||||||
|
|
||||||
|
The `admin` command lets you perform maintenance tasks without going through the web interface. Available subcommands include:
|
||||||
|
|
||||||
|
| Subcommand | Purpose |
|
||||||
|
|---|---|
|
||||||
|
| `create-user` | Create a new user account (with optional `--admin` flag). |
|
||||||
|
| `delete-inactive-users` | Remove user accounts that were never activated. |
|
||||||
|
| `delete-repository-archives` | Clean up generated repository archive files. |
|
||||||
|
| `delete-missing-repositories` | Remove database records for repositories whose Git data is missing on disk. |
|
||||||
|
| `collect-garbage` | Run `git gc` across all repositories. |
|
||||||
|
| `rewrite-authorized-keys` | Regenerate the SSH `authorized_keys` file from the database. |
|
||||||
|
| `resync-hooks` | Re-write Git server-side hooks for all repositories. |
|
||||||
|
| `reinit-missing-repositories` | Re-initialize bare Git repositories that are missing on disk. |
|
||||||
|
|
||||||
|
<Warning>
|
||||||
|
`rewrite-authorized-keys` replaces the entire `authorized_keys` file. Any non-Gogs keys in that file will be lost.
|
||||||
|
</Warning>
|
||||||
|
|
||||||
|
## Importing data
|
||||||
|
|
||||||
|
```bash
|
||||||
|
gogs import locale --source <dir> --target <dir>
|
||||||
|
```
|
||||||
|
|
||||||
|
The `import` command helps you bring portable data from other Gogs installations into your local instance. Currently the only subcommand is `locale`, which merges locale files from a source directory into a target directory.
|
||||||
|
|
||||||
|
## Backup and restore
|
||||||
|
|
||||||
|
```bash
|
||||||
|
gogs backup
|
||||||
|
gogs restore --from <archive>
|
||||||
|
```
|
||||||
|
|
||||||
|
`backup` dumps the database, repositories, and related files into a single zip archive. `restore` imports everything back from an archive, which is useful for migrating Gogs to another server or switching database engines.
|
||||||
|
|
||||||
|
Both commands support `--database-only` and `--exclude-repos` flags to narrow the scope. `backup` additionally supports `--exclude-mirror-repos` and `--target` to control where the archive is saved.
|
||||||
|
|
||||||
|
## Internal commands
|
||||||
|
|
||||||
|
The `serv` and `hook` commands are used internally by the SSH and Git subsystems. You generally do not need to invoke them directly, but they are the reason Gogs can handle SSH authentication and server-side Git hooks without any external tooling.
|
||||||
@@ -55,23 +55,11 @@ There are two ways to authenticate through the Gogs API. Requests that require a
|
|||||||
</Warning>
|
</Warning>
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab title="Access token">
|
<Tab title="Access token">
|
||||||
Personal access tokens are the recommended way to authenticate. They can be sent via a request **header** or a **URL query parameter**.
|
Personal access tokens must be sent via the `Authorization` request header.
|
||||||
|
|
||||||
**Using a header:**
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl -H "Authorization: token {YOUR_ACCESS_TOKEN}" https://gogs.example.com/api/v1/user/repos
|
curl -H "Authorization: token {YOUR_ACCESS_TOKEN}" https://gogs.example.com/api/v1/user/repos
|
||||||
```
|
```
|
||||||
|
|
||||||
**Using a query parameter:**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
curl https://gogs.example.com/api/v1/user/repos?token={YOUR_ACCESS_TOKEN}
|
|
||||||
```
|
|
||||||
|
|
||||||
<Tip>
|
|
||||||
Using the `Authorization` header is preferred over the query parameter, as URLs may be logged by proxies and servers.
|
|
||||||
</Tip>
|
|
||||||
</Tab>
|
</Tab>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|
||||||
|
|||||||
@@ -5449,12 +5449,6 @@
|
|||||||
"in": "header",
|
"in": "header",
|
||||||
"name": "Authorization",
|
"name": "Authorization",
|
||||||
"description": "Personal access token. Use format: token {YOUR_ACCESS_TOKEN}"
|
"description": "Personal access token. Use format: token {YOUR_ACCESS_TOKEN}"
|
||||||
},
|
|
||||||
"TokenQuery": {
|
|
||||||
"type": "apiKey",
|
|
||||||
"in": "query",
|
|
||||||
"name": "token",
|
|
||||||
"description": "Access token as query parameter"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"schemas": {
|
"schemas": {
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ Answers to common questions about Gogs configuration, administration, and usage.
|
|||||||
You can change the listening port on the first run by passing the `-port` flag:
|
You can change the listening port on the first run by passing the `-port` flag:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./gogs web -port 3001
|
gogs web -port 3001
|
||||||
```
|
```
|
||||||
|
|
||||||
This flag also updates the port number shown on the install page, so pick the port you intend to keep using.
|
This flag also updates the port number shown on the install page, so pick the port you intend to keep using.
|
||||||
@@ -58,7 +58,7 @@ Answers to common questions about Gogs configuration, administration, and usage.
|
|||||||
```bash
|
```bash
|
||||||
su git
|
su git
|
||||||
cd /home/git/gogs
|
cd /home/git/gogs
|
||||||
./gogs admin create-user --name tmpuser --password tmppassword --admin --email tmp@example.com
|
gogs admin create-user --name tmpuser --password tmppassword --admin --email tmp@example.com
|
||||||
```
|
```
|
||||||
|
|
||||||
2. **Start Gogs** again, then log in as `tmpuser` in your browser. Navigate to **Admin Panel** > **Users**, click **Edit** next to the original administrator account, and set a new password.
|
2. **Start Gogs** again, then log in as `tmpuser` in your browser. Navigate to **Admin Panel** > **Users**, click **Edit** next to the original administrator account, and set a new password.
|
||||||
|
|||||||
@@ -50,7 +50,8 @@
|
|||||||
"advancing/webhooks",
|
"advancing/webhooks",
|
||||||
"advancing/git-lfs",
|
"advancing/git-lfs",
|
||||||
"advancing/custom-templates",
|
"advancing/custom-templates",
|
||||||
"advancing/localization"
|
"advancing/localization",
|
||||||
|
"advancing/cli-reference"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ The work directory (parent of `custom/`) can also be overridden with `GOGS_WORK_
|
|||||||
Every Gogs subcommand accepts `-c, --config` to point to a configuration file at a non-default location:
|
Every Gogs subcommand accepts `-c, --config` to point to a configuration file at a non-default location:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./gogs web --config /etc/gogs/app.ini
|
gogs web --config /etc/gogs/app.ini
|
||||||
```
|
```
|
||||||
|
|
||||||
### What lives in `custom/`
|
### What lives in `custom/`
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ If you choose to use MySQL or PostgreSQL as your database backend, you need to f
|
|||||||
Release archives containing `mws` come with built-in Windows service support. If you prefer to manage the service using [NSSM](https://nssm.cc), download the standard version instead.
|
Release archives containing `mws` come with built-in Windows service support. If you prefer to manage the service using [NSSM](https://nssm.cc), download the standard version instead.
|
||||||
</Note>
|
</Note>
|
||||||
|
|
||||||
Once extracted the archive, run `./gogs web` to start the server. Use `./gogs web --help` to see all available options.
|
Once extracted the archive, run `gogs web` to start the server. Use `gogs web --help` to see all available options.
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab title="Docker">
|
<Tab title="Docker">
|
||||||
Two types of Docker images are provided:
|
Two types of Docker images are provided:
|
||||||
|
|||||||
@@ -5,14 +5,14 @@ description: "The painless way to host your own Git service"
|
|||||||
icon: "book-open"
|
icon: "book-open"
|
||||||
---
|
---
|
||||||
|
|
||||||
<img
|
<img
|
||||||
className="block dark:hidden"
|
className="block dark:hidden"
|
||||||
src="/images/logo-light.svg"
|
src="/images/logo-light.svg"
|
||||||
noZoom
|
noZoom
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<img
|
<img
|
||||||
className="hidden dark:block"
|
className="hidden dark:block"
|
||||||
src="/images/logo-dark.svg"
|
src="/images/logo-dark.svg"
|
||||||
noZoom
|
noZoom
|
||||||
/>
|
/>
|
||||||
@@ -34,14 +34,14 @@ The growth of the Gogs project wasn't possible without our world-class sponsors!
|
|||||||
|
|
||||||
<Columns cols={2}>
|
<Columns cols={2}>
|
||||||
<a href="https://www.digitalocean.com/?refcode=5aeb02268b55&utm_campaign=Referral_Invite&utm_medium=Referral_Program&utm_source=badge" target="_blank" style={{borderBottom: "none"}}>
|
<a href="https://www.digitalocean.com/?refcode=5aeb02268b55&utm_campaign=Referral_Invite&utm_medium=Referral_Program&utm_source=badge" target="_blank" style={{borderBottom: "none"}}>
|
||||||
<img
|
<img
|
||||||
className="block dark:hidden"
|
className="block dark:hidden"
|
||||||
src="/images/sponsors/digitalocean-light.png"
|
src="/images/sponsors/digitalocean-light.png"
|
||||||
width={320}
|
width={320}
|
||||||
noZoom
|
noZoom
|
||||||
/>
|
/>
|
||||||
<img
|
<img
|
||||||
className="hidden dark:block"
|
className="hidden dark:block"
|
||||||
src="/images/sponsors/digitalocean-dark.png"
|
src="/images/sponsors/digitalocean-dark.png"
|
||||||
width={320}
|
width={320}
|
||||||
noZoom
|
noZoom
|
||||||
@@ -50,13 +50,13 @@ The growth of the Gogs project wasn't possible without our world-class sponsors!
|
|||||||
|
|
||||||
<a href="https://www.mintlify.com" target="_blank" style={{borderBottom: "none"}}>
|
<a href="https://www.mintlify.com" target="_blank" style={{borderBottom: "none"}}>
|
||||||
<img
|
<img
|
||||||
className="block dark:hidden"
|
className="block dark:hidden"
|
||||||
src="/images/sponsors/mintlify-light.svg"
|
src="/images/sponsors/mintlify-light.svg"
|
||||||
width={320}
|
width={320}
|
||||||
noZoom
|
noZoom
|
||||||
/>
|
/>
|
||||||
<img
|
<img
|
||||||
className="hidden dark:block"
|
className="hidden dark:block"
|
||||||
src="/images/sponsors/mintlify-dark.svg"
|
src="/images/sponsors/mintlify-dark.svg"
|
||||||
width={320}
|
width={320}
|
||||||
noZoom
|
noZoom
|
||||||
@@ -64,14 +64,14 @@ The growth of the Gogs project wasn't possible without our world-class sponsors!
|
|||||||
</a>
|
</a>
|
||||||
|
|
||||||
<a href="https://www.crowdin.com" target="_blank" style={{borderBottom: "none"}}>
|
<a href="https://www.crowdin.com" target="_blank" style={{borderBottom: "none"}}>
|
||||||
<img
|
<img
|
||||||
className="block dark:hidden"
|
className="block dark:hidden"
|
||||||
src="/images/sponsors/crowdin-light.svg"
|
src="/images/sponsors/crowdin-light.svg"
|
||||||
width={320}
|
width={320}
|
||||||
noZoom
|
noZoom
|
||||||
/>
|
/>
|
||||||
<img
|
<img
|
||||||
className="hidden dark:block"
|
className="hidden dark:block"
|
||||||
src="/images/sponsors/crowdin-dark.svg"
|
src="/images/sponsors/crowdin-dark.svg"
|
||||||
width={320}
|
width={320}
|
||||||
noZoom
|
noZoom
|
||||||
@@ -79,14 +79,14 @@ The growth of the Gogs project wasn't possible without our world-class sponsors!
|
|||||||
</a>
|
</a>
|
||||||
|
|
||||||
<a href="https://www.buildkite.com" target="_blank" style={{borderBottom: "none", paddingTop: "5px"}}>
|
<a href="https://www.buildkite.com" target="_blank" style={{borderBottom: "none", paddingTop: "5px"}}>
|
||||||
<img
|
<img
|
||||||
className="block dark:hidden"
|
className="block dark:hidden"
|
||||||
src="/images/sponsors/buildkite-light.svg"
|
src="/images/sponsors/buildkite-light.svg"
|
||||||
width={320}
|
width={320}
|
||||||
noZoom
|
noZoom
|
||||||
/>
|
/>
|
||||||
<img
|
<img
|
||||||
className="hidden dark:block"
|
className="hidden dark:block"
|
||||||
src="/images/sponsors/buildkite-dark.svg"
|
src="/images/sponsors/buildkite-dark.svg"
|
||||||
width={320}
|
width={320}
|
||||||
noZoom
|
noZoom
|
||||||
|
|||||||
24
go.mod
24
go.mod
@@ -1,6 +1,6 @@
|
|||||||
module gogs.io/gogs
|
module gogs.io/gogs
|
||||||
|
|
||||||
go 1.25.0
|
go 1.26.0
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/DATA-DOG/go-sqlmock v1.5.2
|
github.com/DATA-DOG/go-sqlmock v1.5.2
|
||||||
@@ -21,21 +21,20 @@ require (
|
|||||||
github.com/go-macaron/toolbox v0.0.0-20190813233741-94defb8383c6
|
github.com/go-macaron/toolbox v0.0.0-20190813233741-94defb8383c6
|
||||||
github.com/gogs/chardet v0.0.0-20150115103509-2404f7772561
|
github.com/gogs/chardet v0.0.0-20150115103509-2404f7772561
|
||||||
github.com/gogs/cron v0.0.0-20171120032916-9f6c956d3e14
|
github.com/gogs/cron v0.0.0-20171120032916-9f6c956d3e14
|
||||||
github.com/gogs/git-module v1.8.6
|
github.com/gogs/git-module v1.8.7
|
||||||
github.com/gogs/go-gogs-client v0.0.0-20200128182646-c69cb7680fd4
|
|
||||||
github.com/gogs/go-libravatar v0.0.0-20191106065024-33a75213d0a0
|
github.com/gogs/go-libravatar v0.0.0-20191106065024-33a75213d0a0
|
||||||
github.com/gogs/minwinsvc v0.0.0-20170301035411-95be6356811a
|
github.com/gogs/minwinsvc v0.0.0-20170301035411-95be6356811a
|
||||||
github.com/google/go-github v17.0.0+incompatible
|
github.com/google/go-github v17.0.0+incompatible
|
||||||
github.com/google/uuid v1.6.0
|
github.com/google/uuid v1.6.0
|
||||||
github.com/inbucket/html2text v1.0.0
|
github.com/inbucket/html2text v1.0.0
|
||||||
github.com/issue9/identicon v1.2.1
|
github.com/issue9/identicon v1.2.1
|
||||||
github.com/json-iterator/go v1.1.12
|
|
||||||
github.com/microcosm-cc/bluemonday v1.0.27
|
github.com/microcosm-cc/bluemonday v1.0.27
|
||||||
github.com/msteinert/pam v1.2.0
|
github.com/msteinert/pam v1.2.0
|
||||||
github.com/niklasfasching/go-org v1.9.1
|
github.com/niklasfasching/go-org v1.9.1
|
||||||
github.com/olekukonko/tablewriter v1.1.3
|
github.com/olekukonko/tablewriter v1.1.3
|
||||||
github.com/pquerna/otp v1.5.0
|
github.com/pquerna/otp v1.5.0
|
||||||
github.com/prometheus/client_golang v1.23.0
|
github.com/prometheus/client_golang v1.23.0
|
||||||
|
github.com/russross/blackfriday v1.6.0
|
||||||
github.com/sergi/go-diff v1.4.0
|
github.com/sergi/go-diff v1.4.0
|
||||||
github.com/sourcegraph/run v0.12.0
|
github.com/sourcegraph/run v0.12.0
|
||||||
github.com/stretchr/testify v1.11.1
|
github.com/stretchr/testify v1.11.1
|
||||||
@@ -43,18 +42,16 @@ require (
|
|||||||
github.com/unknwon/com v1.0.1
|
github.com/unknwon/com v1.0.1
|
||||||
github.com/unknwon/i18n v0.0.0-20190805065654-5c6446a380b6
|
github.com/unknwon/i18n v0.0.0-20190805065654-5c6446a380b6
|
||||||
github.com/unknwon/paginater v0.0.0-20170405233947-45e5d631308e
|
github.com/unknwon/paginater v0.0.0-20170405233947-45e5d631308e
|
||||||
github.com/urfave/cli v1.22.17
|
github.com/urfave/cli/v3 v3.6.2
|
||||||
github.com/yuin/goldmark v1.7.16
|
github.com/wneessen/go-mail v0.7.2
|
||||||
golang.org/x/crypto v0.47.0
|
golang.org/x/crypto v0.47.0
|
||||||
golang.org/x/image v0.35.0
|
golang.org/x/image v0.35.0
|
||||||
golang.org/x/net v0.48.0
|
golang.org/x/net v0.48.0
|
||||||
golang.org/x/text v0.33.0
|
golang.org/x/text v0.33.0
|
||||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
|
|
||||||
gopkg.in/ini.v1 v1.67.0
|
gopkg.in/ini.v1 v1.67.0
|
||||||
gopkg.in/macaron.v1 v1.5.1
|
gopkg.in/macaron.v1 v1.5.1
|
||||||
gorm.io/driver/mysql v1.5.2
|
gorm.io/driver/mysql v1.5.2
|
||||||
gorm.io/driver/postgres v1.6.0
|
gorm.io/driver/postgres v1.6.0
|
||||||
gorm.io/driver/sqlserver v1.4.1
|
|
||||||
gorm.io/gorm v1.25.12
|
gorm.io/gorm v1.25.12
|
||||||
unknwon.dev/clog/v2 v2.2.0
|
unknwon.dev/clog/v2 v2.2.0
|
||||||
xorm.io/builder v0.3.6
|
xorm.io/builder v0.3.6
|
||||||
@@ -75,9 +72,7 @@ require (
|
|||||||
github.com/clipperhouse/uax29/v2 v2.3.0 // indirect
|
github.com/clipperhouse/uax29/v2 v2.3.0 // indirect
|
||||||
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect
|
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect
|
||||||
github.com/cockroachdb/redact v1.1.5 // indirect
|
github.com/cockroachdb/redact v1.1.5 // indirect
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect
|
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/denisenkom/go-mssqldb v0.12.0 // indirect
|
|
||||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||||
github.com/djherbis/buffer v1.2.0 // indirect
|
github.com/djherbis/buffer v1.2.0 // indirect
|
||||||
github.com/djherbis/nio/v3 v3.0.1 // indirect
|
github.com/djherbis/nio/v3 v3.0.1 // indirect
|
||||||
@@ -91,8 +86,6 @@ require (
|
|||||||
github.com/go-redis/redis/v8 v8.11.5 // indirect
|
github.com/go-redis/redis/v8 v8.11.5 // indirect
|
||||||
github.com/go-sql-driver/mysql v1.7.0 // indirect
|
github.com/go-sql-driver/mysql v1.7.0 // indirect
|
||||||
github.com/gogo/protobuf v1.3.2 // indirect
|
github.com/gogo/protobuf v1.3.2 // indirect
|
||||||
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect
|
|
||||||
github.com/golang-sql/sqlexp v0.1.0 // indirect
|
|
||||||
github.com/google/go-querystring v1.0.0 // indirect
|
github.com/google/go-querystring v1.0.0 // indirect
|
||||||
github.com/gorilla/css v1.0.1 // indirect
|
github.com/gorilla/css v1.0.1 // indirect
|
||||||
github.com/itchyny/gojq v0.12.11 // indirect
|
github.com/itchyny/gojq v0.12.11 // indirect
|
||||||
@@ -112,9 +105,6 @@ require (
|
|||||||
github.com/mattn/go-runewidth v0.0.19 // indirect
|
github.com/mattn/go-runewidth v0.0.19 // indirect
|
||||||
github.com/mattn/go-sqlite3 v1.14.24 // indirect
|
github.com/mattn/go-sqlite3 v1.14.24 // indirect
|
||||||
github.com/mcuadros/go-version v0.0.0-20190830083331-035f6764e8d2 // indirect
|
github.com/mcuadros/go-version v0.0.0-20190830083331-035f6764e8d2 // indirect
|
||||||
github.com/microsoft/go-mssqldb v0.17.0 // indirect
|
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
|
||||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
|
||||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||||
github.com/ncruces/go-strftime v0.1.9 // indirect
|
github.com/ncruces/go-strftime v0.1.9 // indirect
|
||||||
github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6 // indirect
|
github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6 // indirect
|
||||||
@@ -127,7 +117,6 @@ require (
|
|||||||
github.com/prometheus/procfs v0.16.1 // indirect
|
github.com/prometheus/procfs v0.16.1 // indirect
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||||
github.com/rogpeppe/go-internal v1.10.0 // indirect
|
github.com/rogpeppe/go-internal v1.10.0 // indirect
|
||||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
|
||||||
github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca // indirect
|
github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca // indirect
|
||||||
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect
|
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect
|
||||||
go.bobheadxi.dev/streamline v1.2.1 // indirect
|
go.bobheadxi.dev/streamline v1.2.1 // indirect
|
||||||
@@ -138,7 +127,6 @@ require (
|
|||||||
golang.org/x/sync v0.19.0 // indirect
|
golang.org/x/sync v0.19.0 // indirect
|
||||||
golang.org/x/sys v0.40.0 // indirect
|
golang.org/x/sys v0.40.0 // indirect
|
||||||
google.golang.org/protobuf v1.36.6 // indirect
|
google.golang.org/protobuf v1.36.6 // indirect
|
||||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
|
||||||
gopkg.in/bufio.v1 v1.0.0-20140618132640-567b2bfa514e // indirect
|
gopkg.in/bufio.v1 v1.0.0-20140618132640-567b2bfa514e // indirect
|
||||||
gopkg.in/redis.v2 v2.3.2 // indirect
|
gopkg.in/redis.v2 v2.3.2 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
@@ -148,5 +136,5 @@ require (
|
|||||||
modernc.org/sqlite v1.39.0 // indirect
|
modernc.org/sqlite v1.39.0 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
// +heroku goVersion go1.25
|
// +heroku goVersion go1.26
|
||||||
// +heroku install ./cmd/gogs
|
// +heroku install ./cmd/gogs
|
||||||
|
|||||||
89
go.sum
89
go.sum
@@ -2,20 +2,13 @@ bitbucket.org/creachadair/shell v0.0.7 h1:Z96pB6DkSb7F3Y3BBnJeOZH2gazyMTWlvecSD4
|
|||||||
bitbucket.org/creachadair/shell v0.0.7/go.mod h1:oqtXSSvSYr4624lnnabXHaBsYW6RD80caLi2b3hJk0U=
|
bitbucket.org/creachadair/shell v0.0.7/go.mod h1:oqtXSSvSYr4624lnnabXHaBsYW6RD80caLi2b3hJk0U=
|
||||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||||
|
cloud.google.com/go v0.37.4 h1:glPeL3BQJsbF6aIIYfZizMwc5LTYz250bDMjttbBGAU=
|
||||||
cloud.google.com/go v0.37.4/go.mod h1:NHPJ89PdicEuT9hdPXMROBD91xc5uRDxsMtSB16k7hw=
|
cloud.google.com/go v0.37.4/go.mod h1:NHPJ89PdicEuT9hdPXMROBD91xc5uRDxsMtSB16k7hw=
|
||||||
gitea.com/lunny/log v0.0.0-20190322053110-01b5df579c4e/go.mod h1:uJEsN4LQpeGYRCjuPXPZBClU7N5pWzGuyF4uqLpE/e0=
|
gitea.com/lunny/log v0.0.0-20190322053110-01b5df579c4e/go.mod h1:uJEsN4LQpeGYRCjuPXPZBClU7N5pWzGuyF4uqLpE/e0=
|
||||||
gitea.com/lunny/nodb v0.0.0-20200923032308-3238c4655727/go.mod h1:h0OwsgcpJLSYtHcM5+Xciw9OEeuxi6ty4HDiO8C7aIY=
|
gitea.com/lunny/nodb v0.0.0-20200923032308-3238c4655727/go.mod h1:h0OwsgcpJLSYtHcM5+Xciw9OEeuxi6ty4HDiO8C7aIY=
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v0.19.0/go.mod h1:h6H6c8enJmmocHUbLiiGY6sx7f9i+X3m1CHdd5c6Rdw=
|
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.0.0/go.mod h1:uGG2W01BaETf0Ozp+QxxKJdMBNRWPdstHG0Fmdwn1/U=
|
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.11.0/go.mod h1:HcM1YX14R7CJcghJGOYCgdezslRSVzqwLf/q+4Y2r/0=
|
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.0.0/go.mod h1:+6sju8gk8FRmSajX3Oz4G5Gm7P+mbqE9FVaXXFYTkCM=
|
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/internal v0.7.0/go.mod h1:yqy467j36fJxcRV2TzfVZ1pCb5vxm4BtZPUdYWe/Xo8=
|
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w=
|
|
||||||
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 h1:mFRzDkZVAjdal+s7s0MwaRv9igoPqLRdzOLzw/8Xvq8=
|
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 h1:mFRzDkZVAjdal+s7s0MwaRv9igoPqLRdzOLzw/8Xvq8=
|
||||||
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
|
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
|
||||||
github.com/AzureAD/microsoft-authentication-library-for-go v0.4.0/go.mod h1:Vt9sXTKwMyGcOxSmLDMnGPgqsUg7m8pe215qMLrDXw4=
|
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
|
||||||
github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU=
|
github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU=
|
||||||
github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU=
|
github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU=
|
||||||
github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0=
|
github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0=
|
||||||
@@ -61,16 +54,13 @@ github.com/couchbase/gomemcached v0.1.1/go.mod h1:mxliKQxOv84gQ0bJWbI+w9Wxdpt9Hj
|
|||||||
github.com/couchbase/goutils v0.0.0-20190315194238-f9d42b11473b/go.mod h1:BQwMFlJzDjFDG3DJUdU0KORxn88UlsOULuxLExMh3Hs=
|
github.com/couchbase/goutils v0.0.0-20190315194238-f9d42b11473b/go.mod h1:BQwMFlJzDjFDG3DJUdU0KORxn88UlsOULuxLExMh3Hs=
|
||||||
github.com/couchbase/goutils v0.0.0-20201030094643-5e82bb967e67/go.mod h1:BQwMFlJzDjFDG3DJUdU0KORxn88UlsOULuxLExMh3Hs=
|
github.com/couchbase/goutils v0.0.0-20201030094643-5e82bb967e67/go.mod h1:BQwMFlJzDjFDG3DJUdU0KORxn88UlsOULuxLExMh3Hs=
|
||||||
github.com/couchbaselabs/go-couchbase v0.0.0-20190708161019-23e7ca2ce2b7/go.mod h1:mby/05p8HE5yHEAKiIH/555NoblMs7PtW6NrYshDruc=
|
github.com/couchbaselabs/go-couchbase v0.0.0-20190708161019-23e7ca2ce2b7/go.mod h1:mby/05p8HE5yHEAKiIH/555NoblMs7PtW6NrYshDruc=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.7 h1:zbFlGlXEAKlwXpmvle3d8Oe3YnkKIK4xSRTd3sHPnBo=
|
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.7/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
|
||||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||||
github.com/cupcake/rdb v0.0.0-20161107195141-43ba34106c76/go.mod h1:vYwsqCOLxGiisLwp9rITslkFNpZD5rz43tf41QFkTWY=
|
github.com/cupcake/rdb v0.0.0-20161107195141-43ba34106c76/go.mod h1:vYwsqCOLxGiisLwp9rITslkFNpZD5rz43tf41QFkTWY=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/denisenkom/go-mssqldb v0.0.0-20190707035753-2be1aa521ff4 h1:YcpmyvADGYw5LqMnHqSkyIELsHCGF6PkrmM31V8rF7o=
|
||||||
github.com/denisenkom/go-mssqldb v0.0.0-20190707035753-2be1aa521ff4/go.mod h1:zAg7JM8CkOJ43xKXIj7eRO9kmWm/TW578qo+oDO6tuM=
|
github.com/denisenkom/go-mssqldb v0.0.0-20190707035753-2be1aa521ff4/go.mod h1:zAg7JM8CkOJ43xKXIj7eRO9kmWm/TW578qo+oDO6tuM=
|
||||||
github.com/denisenkom/go-mssqldb v0.12.0 h1:VtrkII767ttSPNRfFekePK3sctr+joXgO58stqQbtUA=
|
|
||||||
github.com/denisenkom/go-mssqldb v0.12.0/go.mod h1:iiK0YP1ZeepvmBQk/QpLEhhTNJgfzrpArPY/aFvc9yU=
|
|
||||||
github.com/derision-test/go-mockgen/v2 v2.1.1 h1:MXG9rzyvsrDBfa1a1GatvHjCrbmEug3hVt0rSOXipCw=
|
github.com/derision-test/go-mockgen/v2 v2.1.1 h1:MXG9rzyvsrDBfa1a1GatvHjCrbmEug3hVt0rSOXipCw=
|
||||||
github.com/derision-test/go-mockgen/v2 v2.1.1/go.mod h1:cDK2Y9IF5roTJgugWV23IvlOJsllhDN5zxRDN+g4cZo=
|
github.com/derision-test/go-mockgen/v2 v2.1.1/go.mod h1:cDK2Y9IF5roTJgugWV23IvlOJsllhDN5zxRDN+g4cZo=
|
||||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
||||||
@@ -80,8 +70,6 @@ github.com/djherbis/buffer v1.2.0 h1:PH5Dd2ss0C7CRRhQCZ2u7MssF+No9ide8Ye71nPHcrQ
|
|||||||
github.com/djherbis/buffer v1.2.0/go.mod h1:fjnebbZjCUpPinBRD+TDwXSOeNQ7fPQWLfGQqiAiUyE=
|
github.com/djherbis/buffer v1.2.0/go.mod h1:fjnebbZjCUpPinBRD+TDwXSOeNQ7fPQWLfGQqiAiUyE=
|
||||||
github.com/djherbis/nio/v3 v3.0.1 h1:6wxhnuppteMa6RHA4L81Dq7ThkZH8SwnDzXDYy95vB4=
|
github.com/djherbis/nio/v3 v3.0.1 h1:6wxhnuppteMa6RHA4L81Dq7ThkZH8SwnDzXDYy95vB4=
|
||||||
github.com/djherbis/nio/v3 v3.0.1/go.mod h1:Ng4h80pbZFMla1yKzm61cF0tqqilXZYrogmWgZxOcmg=
|
github.com/djherbis/nio/v3 v3.0.1/go.mod h1:Ng4h80pbZFMla1yKzm61cF0tqqilXZYrogmWgZxOcmg=
|
||||||
github.com/dnaeon/go-vcr v1.1.0/go.mod h1:M7tiix8f0r6mKKJ3Yq/kqU1OYf3MnfmBWVbPx/yU9ko=
|
|
||||||
github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ=
|
|
||||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||||
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
|
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
|
||||||
@@ -154,23 +142,12 @@ github.com/gogs/chardet v0.0.0-20150115103509-2404f7772561 h1:aBzukfDxQlCTVS0NBU
|
|||||||
github.com/gogs/chardet v0.0.0-20150115103509-2404f7772561/go.mod h1:Pcatq5tYkCW2Q6yrR2VRHlbHpZ/R4/7qyL1TCF7vl14=
|
github.com/gogs/chardet v0.0.0-20150115103509-2404f7772561/go.mod h1:Pcatq5tYkCW2Q6yrR2VRHlbHpZ/R4/7qyL1TCF7vl14=
|
||||||
github.com/gogs/cron v0.0.0-20171120032916-9f6c956d3e14 h1:yXtpJr/LV6PFu4nTLgfjQdcMdzjbqqXMEnHfq0Or6p8=
|
github.com/gogs/cron v0.0.0-20171120032916-9f6c956d3e14 h1:yXtpJr/LV6PFu4nTLgfjQdcMdzjbqqXMEnHfq0Or6p8=
|
||||||
github.com/gogs/cron v0.0.0-20171120032916-9f6c956d3e14/go.mod h1:jPoNZLWDAqA5N3G5amEoiNbhVrmM+ZQEcnQvNQ2KaZk=
|
github.com/gogs/cron v0.0.0-20171120032916-9f6c956d3e14/go.mod h1:jPoNZLWDAqA5N3G5amEoiNbhVrmM+ZQEcnQvNQ2KaZk=
|
||||||
github.com/gogs/git-module v1.8.6 h1:4Io9vWZYQyIjdIPxfKgeYZXnDKNgydc6OZTxII5xCH4=
|
github.com/gogs/git-module v1.8.7 h1:GDyfzB1Z8ytld3LajTfUE4PuIcGcuCHpWB6j8/oD7Tk=
|
||||||
github.com/gogs/git-module v1.8.6/go.mod h1:IiMSJqi8XH62Kjqjt5Rw8IawSo+DHfM2dDjkSzWLjhs=
|
github.com/gogs/git-module v1.8.7/go.mod h1:IiMSJqi8XH62Kjqjt5Rw8IawSo+DHfM2dDjkSzWLjhs=
|
||||||
github.com/gogs/go-gogs-client v0.0.0-20200128182646-c69cb7680fd4 h1:C7NryI/RQhsIWwC2bHN601P1wJKeuQ6U/UCOYTn3Cic=
|
|
||||||
github.com/gogs/go-gogs-client v0.0.0-20200128182646-c69cb7680fd4/go.mod h1:fR6z1Ie6rtF7kl/vBYMfgD5/G5B1blui7z426/sj2DU=
|
|
||||||
github.com/gogs/go-libravatar v0.0.0-20191106065024-33a75213d0a0 h1:K02vod+sn3M1OOkdqi2tPxN2+xESK4qyITVQ3JkGEv4=
|
github.com/gogs/go-libravatar v0.0.0-20191106065024-33a75213d0a0 h1:K02vod+sn3M1OOkdqi2tPxN2+xESK4qyITVQ3JkGEv4=
|
||||||
github.com/gogs/go-libravatar v0.0.0-20191106065024-33a75213d0a0/go.mod h1:Zas3BtO88pk1cwUfEYlvnl/CRwh0ybDxRWSwRjG8I3w=
|
github.com/gogs/go-libravatar v0.0.0-20191106065024-33a75213d0a0/go.mod h1:Zas3BtO88pk1cwUfEYlvnl/CRwh0ybDxRWSwRjG8I3w=
|
||||||
github.com/gogs/minwinsvc v0.0.0-20170301035411-95be6356811a h1:8DZwxETOVWIinYxDK+i6L+rMb7eGATGaakD6ZucfHVk=
|
github.com/gogs/minwinsvc v0.0.0-20170301035411-95be6356811a h1:8DZwxETOVWIinYxDK+i6L+rMb7eGATGaakD6ZucfHVk=
|
||||||
github.com/gogs/minwinsvc v0.0.0-20170301035411-95be6356811a/go.mod h1:TUIZ+29jodWQ8Gk6Pvtg4E09aMsc3C/VLZiVYfUhWQU=
|
github.com/gogs/minwinsvc v0.0.0-20170301035411-95be6356811a/go.mod h1:TUIZ+29jodWQ8Gk6Pvtg4E09aMsc3C/VLZiVYfUhWQU=
|
||||||
github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
|
||||||
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
|
||||||
github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
|
|
||||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
|
||||||
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA=
|
|
||||||
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
|
||||||
github.com/golang-sql/sqlexp v0.0.0-20170517235910-f1bb20e5a188/go.mod h1:vXjM/+wXQnTPR4KqTKDgJukSZ6amVRtWMPEjE6sQoK8=
|
|
||||||
github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A=
|
|
||||||
github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI=
|
|
||||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||||
@@ -200,14 +177,11 @@ github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4r
|
|||||||
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
|
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
|
||||||
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
|
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
|
||||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
|
||||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs=
|
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs=
|
||||||
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
|
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
|
||||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
|
||||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
|
||||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||||
@@ -263,11 +237,8 @@ github.com/jcmturner/rpc/v2 v2.0.3 h1:7FXXj8Ti1IaVFpSAziCZWNzbNuZmnvw/i6CqLNdWfZ
|
|||||||
github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc=
|
github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc=
|
||||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||||
github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
|
||||||
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
||||||
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
|
||||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
|
||||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||||
github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||||
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||||
@@ -313,15 +284,6 @@ github.com/mcuadros/go-version v0.0.0-20190830083331-035f6764e8d2 h1:YocNLcTBdEd
|
|||||||
github.com/mcuadros/go-version v0.0.0-20190830083331-035f6764e8d2/go.mod h1:76rfSfYPWj01Z85hUf/ituArm797mNKcvINh1OlsZKo=
|
github.com/mcuadros/go-version v0.0.0-20190830083331-035f6764e8d2/go.mod h1:76rfSfYPWj01Z85hUf/ituArm797mNKcvINh1OlsZKo=
|
||||||
github.com/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwXFM08ygZfk=
|
github.com/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwXFM08ygZfk=
|
||||||
github.com/microcosm-cc/bluemonday v1.0.27/go.mod h1:jFi9vgW+H7c3V0lb6nR74Ib/DIB5OBs92Dimizgw2cA=
|
github.com/microcosm-cc/bluemonday v1.0.27/go.mod h1:jFi9vgW+H7c3V0lb6nR74Ib/DIB5OBs92Dimizgw2cA=
|
||||||
github.com/microsoft/go-mssqldb v0.17.0 h1:Fto83dMZPnYv1Zwx5vHHxpNraeEaUlQ/hhHLgZiaenE=
|
|
||||||
github.com/microsoft/go-mssqldb v0.17.0/go.mod h1:OkoNGhGEs8EZqchVTtochlXruEhEOaO4S0d2sB5aeGQ=
|
|
||||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
|
||||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
|
||||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
|
||||||
github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8=
|
|
||||||
github.com/montanaflynn/stats v0.6.6/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow=
|
|
||||||
github.com/msteinert/pam v1.2.0 h1:mYfjlvN2KYs2Pb9G6nb/1f/nPfAttT/Jee5Sq9r3bGE=
|
github.com/msteinert/pam v1.2.0 h1:mYfjlvN2KYs2Pb9G6nb/1f/nPfAttT/Jee5Sq9r3bGE=
|
||||||
github.com/msteinert/pam v1.2.0/go.mod h1:d2n0DCUK8rGecChV3JzvmsDjOY4R7AYbsNxAT+ftQl0=
|
github.com/msteinert/pam v1.2.0/go.mod h1:d2n0DCUK8rGecChV3JzvmsDjOY4R7AYbsNxAT+ftQl0=
|
||||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
||||||
@@ -366,9 +328,6 @@ github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrap
|
|||||||
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
||||||
github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4=
|
github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4=
|
||||||
github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8=
|
github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8=
|
||||||
github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA=
|
|
||||||
github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4/go.mod h1:N6UoU20jOqggOuDwUaBQpluzLNDqif3kq9z2wpdYEfQ=
|
|
||||||
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
|
|
||||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
@@ -399,8 +358,8 @@ github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qq
|
|||||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||||
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
|
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
|
||||||
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
|
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
|
||||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww=
|
||||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY=
|
||||||
github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca h1:NugYot0LIVPxTvN8n+Kvkn6TrbMyxQiuvKdEwFdR9vI=
|
github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca h1:NugYot0LIVPxTvN8n+Kvkn6TrbMyxQiuvKdEwFdR9vI=
|
||||||
github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca/go.mod h1:uugorj2VCxiV1x+LzaIdVa9b4S4qGAcH6cbhh4qVxOU=
|
github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca/go.mod h1:uugorj2VCxiV1x+LzaIdVa9b4S4qGAcH6cbhh4qVxOU=
|
||||||
github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw=
|
github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw=
|
||||||
@@ -426,19 +385,12 @@ github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf h1:pvbZ0lM0XWPBqUKqFU8cma
|
|||||||
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf/go.mod h1:RJID2RhlZKId02nZ62WenDCkgHFerpIOmW0iT7GKmXM=
|
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf/go.mod h1:RJID2RhlZKId02nZ62WenDCkgHFerpIOmW0iT7GKmXM=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
|
||||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
|
||||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
|
||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
|
||||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
|
||||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
|
||||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||||
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
|
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
|
||||||
@@ -451,12 +403,12 @@ github.com/unknwon/i18n v0.0.0-20190805065654-5c6446a380b6 h1:sRrkJEHtNoaSvyXMbR
|
|||||||
github.com/unknwon/i18n v0.0.0-20190805065654-5c6446a380b6/go.mod h1:+5rDk6sDGpl3azws3O+f+GpFSyN9GVr0K8cvQLQM2ZQ=
|
github.com/unknwon/i18n v0.0.0-20190805065654-5c6446a380b6/go.mod h1:+5rDk6sDGpl3azws3O+f+GpFSyN9GVr0K8cvQLQM2ZQ=
|
||||||
github.com/unknwon/paginater v0.0.0-20170405233947-45e5d631308e h1:Qf3QQl/zmEbWDajFEiisbKN83hLY+eq2MhbA0I1/two=
|
github.com/unknwon/paginater v0.0.0-20170405233947-45e5d631308e h1:Qf3QQl/zmEbWDajFEiisbKN83hLY+eq2MhbA0I1/two=
|
||||||
github.com/unknwon/paginater v0.0.0-20170405233947-45e5d631308e/go.mod h1:TBwoao3Q4Eb/cp+dHbXDfRTrZSsj/k7kLr2j1oWRWC0=
|
github.com/unknwon/paginater v0.0.0-20170405233947-45e5d631308e/go.mod h1:TBwoao3Q4Eb/cp+dHbXDfRTrZSsj/k7kLr2j1oWRWC0=
|
||||||
github.com/urfave/cli v1.22.17 h1:SYzXoiPfQjHBbkYxbew5prZHS1TOLT3ierW8SYLqtVQ=
|
github.com/urfave/cli/v3 v3.6.2 h1:lQuqiPrZ1cIz8hz+HcrG0TNZFxU70dPZ3Yl+pSrH9A8=
|
||||||
github.com/urfave/cli v1.22.17/go.mod h1:b0ht0aqgH/6pBYzzxURyrM4xXNgsoT/n2ZzwQiEhNVo=
|
github.com/urfave/cli/v3 v3.6.2/go.mod h1:ysVLtOEmg2tOy6PknnYVhDoouyC/6N42TMeoMzskhso=
|
||||||
|
github.com/wneessen/go-mail v0.7.2 h1:xxPnhZ6IZLSgxShebmZ6DPKh1b6OJcoHfzy7UjOkzS8=
|
||||||
|
github.com/wneessen/go-mail v0.7.2/go.mod h1:+TkW6QP3EVkgTEqHtVmnAE/1MRhmzb8Y9/W3pweuS+k=
|
||||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.7.16 h1:n+CJdUxaFMiDUNnWC3dMWCIQJSkxH4uz3ZwQBkAlVNE=
|
|
||||||
github.com/yuin/goldmark v1.7.16/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg=
|
|
||||||
github.com/ziutek/mymysql v1.5.4 h1:GB0qdRGsTwQSBVYuVShFBKaXSnSnYYC2d9knnE1LHFs=
|
github.com/ziutek/mymysql v1.5.4 h1:GB0qdRGsTwQSBVYuVShFBKaXSnSnYYC2d9knnE1LHFs=
|
||||||
github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0=
|
github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0=
|
||||||
go.bobheadxi.dev/streamline v1.2.1 h1:IqKSA1TbeuDqCzYNAwtlh8sqf3tsQus8XgJdkCWFT8c=
|
go.bobheadxi.dev/streamline v1.2.1 h1:IqKSA1TbeuDqCzYNAwtlh8sqf3tsQus8XgJdkCWFT8c=
|
||||||
@@ -479,8 +431,6 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
|
|||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20201124201722-c8d3bf9c5392/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
golang.org/x/crypto v0.0.0-20201124201722-c8d3bf9c5392/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||||
golang.org/x/crypto v0.0.0-20220511200225-c6db032c6c88/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
|
||||||
golang.org/x/crypto v0.0.0-20221005025214-4161e89ecf1b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
|
||||||
golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8=
|
golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8=
|
||||||
golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A=
|
golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
@@ -509,12 +459,8 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
|
|||||||
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
|
||||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
|
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
|
||||||
golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
|
||||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
|
||||||
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
|
||||||
golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU=
|
golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU=
|
||||||
golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY=
|
golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
@@ -548,18 +494,13 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220224120231-95c6836cb0e7/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
|
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
|
||||||
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
|
||||||
golang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY=
|
golang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY=
|
||||||
golang.org/x/term v0.39.0/go.mod h1:yxzUCTP/U+FzoxfdKmLaA0RV1WgE0VY7hXBwKtY/4ww=
|
golang.org/x/term v0.39.0/go.mod h1:yxzUCTP/U+FzoxfdKmLaA0RV1WgE0VY7hXBwKtY/4ww=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
@@ -567,7 +508,6 @@ golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3
|
|||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
|
||||||
golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE=
|
golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE=
|
||||||
golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8=
|
golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8=
|
||||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
@@ -611,8 +551,6 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ
|
|||||||
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
|
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
|
||||||
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
||||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk=
|
|
||||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk=
|
|
||||||
gopkg.in/bufio.v1 v1.0.0-20140618132640-567b2bfa514e h1:wGA78yza6bu/mWcc4QfBuIEHEtc06xdiU0X8sY36yUU=
|
gopkg.in/bufio.v1 v1.0.0-20140618132640-567b2bfa514e h1:wGA78yza6bu/mWcc4QfBuIEHEtc06xdiU0X8sY36yUU=
|
||||||
gopkg.in/bufio.v1 v1.0.0-20140618132640-567b2bfa514e/go.mod h1:xsQCaysVCudhrYTfzYWe577fCe7Ceci+6qjO2Rdc0Z4=
|
gopkg.in/bufio.v1 v1.0.0-20140618132640-567b2bfa514e/go.mod h1:xsQCaysVCudhrYTfzYWe577fCe7Ceci+6qjO2Rdc0Z4=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
@@ -621,8 +559,6 @@ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8
|
|||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df h1:n7WqCuqOuCbNr617RXOY0AWRXxgwEyPp2z+p0+hgMuE=
|
|
||||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df/go.mod h1:LRQQ+SO6ZHR7tOkpBDuZnXENFzX8qRjMDMyPD6BRkCw=
|
|
||||||
gopkg.in/ini.v1 v1.46.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
gopkg.in/ini.v1 v1.46.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||||
gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||||
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
||||||
@@ -639,22 +575,17 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWD
|
|||||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|
||||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20210105161348-2e78108cf5f8/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20210105161348-2e78108cf5f8/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gorm.io/driver/mysql v1.5.2 h1:QC2HRskSE75wBuOxe0+iCkyJZ+RqpudsQtqkp+IMuXs=
|
gorm.io/driver/mysql v1.5.2 h1:QC2HRskSE75wBuOxe0+iCkyJZ+RqpudsQtqkp+IMuXs=
|
||||||
gorm.io/driver/mysql v1.5.2/go.mod h1:pQLhh1Ut/WUAySdTHwBpBv6+JKcj+ua4ZFx1QQTBzb8=
|
gorm.io/driver/mysql v1.5.2/go.mod h1:pQLhh1Ut/WUAySdTHwBpBv6+JKcj+ua4ZFx1QQTBzb8=
|
||||||
gorm.io/driver/postgres v1.6.0 h1:2dxzU8xJ+ivvqTRph34QX+WrRaJlmfyPqXmoGVjMBa4=
|
gorm.io/driver/postgres v1.6.0 h1:2dxzU8xJ+ivvqTRph34QX+WrRaJlmfyPqXmoGVjMBa4=
|
||||||
gorm.io/driver/postgres v1.6.0/go.mod h1:vUw0mrGgrTK+uPHEhAdV4sfFELrByKVGnaVRkXDhtWo=
|
gorm.io/driver/postgres v1.6.0/go.mod h1:vUw0mrGgrTK+uPHEhAdV4sfFELrByKVGnaVRkXDhtWo=
|
||||||
gorm.io/driver/sqlserver v1.4.1 h1:t4r4r6Jam5E6ejqP7N82qAJIJAht27EGT41HyPfXRw0=
|
|
||||||
gorm.io/driver/sqlserver v1.4.1/go.mod h1:DJ4P+MeZbc5rvY58PnmN1Lnyvb5gw5NPzGshHDnJLig=
|
|
||||||
gorm.io/gorm v1.24.0/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA=
|
|
||||||
gorm.io/gorm v1.25.2-0.20230530020048-26663ab9bf55/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
|
gorm.io/gorm v1.25.2-0.20230530020048-26663ab9bf55/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
|
||||||
gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8=
|
gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8=
|
||||||
gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ=
|
gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ=
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
|
|
||||||
"gopkg.in/macaron.v1"
|
"gopkg.in/macaron.v1"
|
||||||
|
|
||||||
"gogs.io/gogs/internal/authutil"
|
"gogs.io/gogs/internal/authx"
|
||||||
"gogs.io/gogs/internal/conf"
|
"gogs.io/gogs/internal/conf"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@ func MetricsFilter() macaron.Handler {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
username, password := authutil.DecodeBasic(r.Header)
|
username, password := authx.DecodeBasic(r.Header)
|
||||||
if username != conf.Prometheus.BasicAuthUsername || password != conf.Prometheus.BasicAuthPassword {
|
if username != conf.Prometheus.BasicAuthUsername || password != conf.Prometheus.BasicAuthPassword {
|
||||||
w.WriteHeader(http.StatusForbidden)
|
w.WriteHeader(http.StatusForbidden)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
|
|
||||||
"github.com/cockroachdb/errors"
|
"github.com/cockroachdb/errors"
|
||||||
|
|
||||||
"gogs.io/gogs/internal/errutil"
|
"gogs.io/gogs/internal/errx"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Type int
|
type Type int
|
||||||
@@ -34,10 +34,10 @@ func Name(typ Type) string {
|
|||||||
}[typ]
|
}[typ]
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ errutil.NotFound = (*ErrBadCredentials)(nil)
|
var _ errx.NotFound = (*ErrBadCredentials)(nil)
|
||||||
|
|
||||||
type ErrBadCredentials struct {
|
type ErrBadCredentials struct {
|
||||||
Args errutil.Args
|
Args errx.Args
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsErrBadCredentials returns true if the underlying error has the type
|
// IsErrBadCredentials returns true if the underlying error has the type
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package authutil
|
package authx
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package authutil
|
package authx
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
@@ -7,7 +7,7 @@ import (
|
|||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
"gogs.io/gogs/internal/testutil"
|
"gogs.io/gogs/internal/testx"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestIsProdMode(t *testing.T) {
|
func TestIsProdMode(t *testing.T) {
|
||||||
@@ -36,7 +36,7 @@ func TestIsProdMode(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestWorkDirHelper(_ *testing.T) {
|
func TestWorkDirHelper(_ *testing.T) {
|
||||||
if !testutil.WantHelperProcess() {
|
if !testx.WantHelperProcess() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,7 +53,7 @@ func TestWorkDir(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run("", func(t *testing.T) {
|
t.Run("", func(t *testing.T) {
|
||||||
out, err := testutil.Exec("TestWorkDirHelper", test.env)
|
out, err := testx.Exec("TestWorkDirHelper", test.env)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -64,7 +64,7 @@ func TestWorkDir(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestCustomDirHelper(_ *testing.T) {
|
func TestCustomDirHelper(_ *testing.T) {
|
||||||
if !testutil.WantHelperProcess() {
|
if !testx.WantHelperProcess() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,7 +81,7 @@ func TestCustomDir(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run("", func(t *testing.T) {
|
t.Run("", func(t *testing.T) {
|
||||||
out, err := testutil.Exec("TestCustomDirHelper", test.env)
|
out, err := testx.Exec("TestCustomDirHelper", test.env)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -92,7 +92,7 @@ func TestCustomDir(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestHomeDirHelper(_ *testing.T) {
|
func TestHomeDirHelper(_ *testing.T) {
|
||||||
if !testutil.WantHelperProcess() {
|
if !testx.WantHelperProcess() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,7 +111,7 @@ func TestHomeDir(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run("", func(t *testing.T) {
|
t.Run("", func(t *testing.T) {
|
||||||
out, err := testutil.Exec("TestHomeDirHelper", test.envs...)
|
out, err := testx.Exec("TestHomeDirHelper", test.envs...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ import (
|
|||||||
log "unknwon.dev/clog/v2"
|
log "unknwon.dev/clog/v2"
|
||||||
|
|
||||||
"gogs.io/gogs/conf"
|
"gogs.io/gogs/conf"
|
||||||
"gogs.io/gogs/internal/osutil"
|
"gogs.io/gogs/internal/osx"
|
||||||
"gogs.io/gogs/internal/semverutil"
|
"gogs.io/gogs/internal/semverx"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@@ -66,7 +66,7 @@ func Init(customConf string) error {
|
|||||||
}
|
}
|
||||||
CustomConf = customConf
|
CustomConf = customConf
|
||||||
|
|
||||||
if osutil.IsFile(customConf) {
|
if osx.IsFile(customConf) {
|
||||||
if err = File.Append(customConf); err != nil {
|
if err = File.Append(customConf); err != nil {
|
||||||
return errors.Wrapf(err, "append %q", customConf)
|
return errors.Wrapf(err, "append %q", customConf)
|
||||||
}
|
}
|
||||||
@@ -141,7 +141,7 @@ func Init(customConf string) error {
|
|||||||
return errors.Wrap(err, "get OpenSSH version")
|
return errors.Wrap(err, "get OpenSSH version")
|
||||||
}
|
}
|
||||||
|
|
||||||
if IsWindowsRuntime() || semverutil.Compare(sshVersion, "<", "5.1") {
|
if IsWindowsRuntime() || semverx.Compare(sshVersion, "<", "5.1") {
|
||||||
if !HookMode {
|
if !HookMode {
|
||||||
log.Warn(`SSH minimum key size check is forced to be disabled because server is not eligible:
|
log.Warn(`SSH minimum key size check is forced to be disabled because server is not eligible:
|
||||||
1. Windows server
|
1. Windows server
|
||||||
@@ -346,6 +346,7 @@ func Init(customConf string) error {
|
|||||||
return errors.Wrap(err, "mapping [lfs] section")
|
return errors.Wrap(err, "mapping [lfs] section")
|
||||||
}
|
}
|
||||||
LFS.ObjectsPath = ensureAbs(LFS.ObjectsPath)
|
LFS.ObjectsPath = ensureAbs(LFS.ObjectsPath)
|
||||||
|
LFS.ObjectsTempPath = ensureAbs(LFS.ObjectsTempPath)
|
||||||
|
|
||||||
handleDeprecated()
|
handleDeprecated()
|
||||||
if !HookMode {
|
if !HookMode {
|
||||||
@@ -382,7 +383,7 @@ func Init(customConf string) error {
|
|||||||
return errors.Wrap(err, "mapping [other] section")
|
return errors.Wrap(err, "mapping [other] section")
|
||||||
}
|
}
|
||||||
|
|
||||||
HasRobotsTxt = osutil.IsFile(filepath.Join(CustomDir(), "robots.txt"))
|
HasRobotsTxt = osx.IsFile(filepath.Join(CustomDir(), "robots.txt"))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"gopkg.in/ini.v1"
|
"gopkg.in/ini.v1"
|
||||||
|
|
||||||
"gogs.io/gogs/internal/testutil"
|
"gogs.io/gogs/internal/testx"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestInit(t *testing.T) {
|
func TestInit(t *testing.T) {
|
||||||
@@ -55,5 +55,5 @@ func TestInit(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
testutil.AssertGolden(t, filepath.Join("testdata", "TestInit.golden.ini"), testutil.Update("TestInit"), buf.String())
|
testx.AssertGolden(t, filepath.Join("testdata", "TestInit.golden.ini"), testx.Update("TestInit"), buf.String())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,7 +56,6 @@ var (
|
|||||||
User string
|
User string
|
||||||
Password string
|
Password string
|
||||||
|
|
||||||
DisableHELO bool `ini:"DISABLE_HELO"`
|
|
||||||
HELOHostname string `ini:"HELO_HOSTNAME"`
|
HELOHostname string `ini:"HELO_HOSTNAME"`
|
||||||
|
|
||||||
SkipVerify bool
|
SkipVerify bool
|
||||||
@@ -361,8 +360,9 @@ type DatabaseOpts struct {
|
|||||||
var Database DatabaseOpts
|
var Database DatabaseOpts
|
||||||
|
|
||||||
type LFSOpts struct {
|
type LFSOpts struct {
|
||||||
Storage string
|
Storage string
|
||||||
ObjectsPath string
|
ObjectsPath string
|
||||||
|
ObjectsTempPath string
|
||||||
}
|
}
|
||||||
|
|
||||||
// LFS settings
|
// LFS settings
|
||||||
@@ -510,7 +510,6 @@ var (
|
|||||||
UseSQLite3 bool
|
UseSQLite3 bool
|
||||||
UseMySQL bool
|
UseMySQL bool
|
||||||
UsePostgreSQL bool
|
UsePostgreSQL bool
|
||||||
UseMSSQL bool
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// UsersAvatarPathPrefix is the path prefix to user avatars.
|
// UsersAvatarPathPrefix is the path prefix to user avatars.
|
||||||
|
|||||||
1
internal/conf/testdata/TestInit.golden.ini
vendored
1
internal/conf/testdata/TestInit.golden.ini
vendored
@@ -88,7 +88,6 @@ HOST=smtp.mailgun.org:587
|
|||||||
FROM=noreply@gogs.localhost
|
FROM=noreply@gogs.localhost
|
||||||
USER=noreply@gogs.localhost
|
USER=noreply@gogs.localhost
|
||||||
PASSWORD=87654321
|
PASSWORD=87654321
|
||||||
DISABLE_HELO=false
|
|
||||||
HELO_HOSTNAME=
|
HELO_HOSTNAME=
|
||||||
SKIP_VERIFY=false
|
SKIP_VERIFY=false
|
||||||
USE_CERTIFICATE=false
|
USE_CERTIFICATE=false
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import (
|
|||||||
|
|
||||||
"github.com/cockroachdb/errors"
|
"github.com/cockroachdb/errors"
|
||||||
|
|
||||||
"gogs.io/gogs/internal/osutil"
|
"gogs.io/gogs/internal/osx"
|
||||||
"gogs.io/gogs/internal/process"
|
"gogs.io/gogs/internal/process"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -44,6 +44,6 @@ func CheckRunUser(runUser string) (string, bool) {
|
|||||||
return "", true
|
return "", true
|
||||||
}
|
}
|
||||||
|
|
||||||
currentUser := osutil.CurrentUsername()
|
currentUser := osx.CurrentUsername()
|
||||||
return currentUser, runUser == currentUser
|
return currentUser, runUser == currentUser
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import (
|
|||||||
log "unknwon.dev/clog/v2"
|
log "unknwon.dev/clog/v2"
|
||||||
|
|
||||||
"gogs.io/gogs/internal/conf"
|
"gogs.io/gogs/internal/conf"
|
||||||
"gogs.io/gogs/internal/errutil"
|
"gogs.io/gogs/internal/errx"
|
||||||
)
|
)
|
||||||
|
|
||||||
type APIContext struct {
|
type APIContext struct {
|
||||||
@@ -62,7 +62,7 @@ func (c *APIContext) Errorf(err error, format string, args ...any) {
|
|||||||
// is about not found. It responses with 404 status code for not found error,
|
// is about not found. It responses with 404 status code for not found error,
|
||||||
// or error context description for logging purpose of 500 server error.
|
// or error context description for logging purpose of 500 server error.
|
||||||
func (c *APIContext) NotFoundOrError(err error, msg string) {
|
func (c *APIContext) NotFoundOrError(err error, msg string) {
|
||||||
if errutil.IsNotFound(err) {
|
if errx.IsNotFound(err) {
|
||||||
c.NotFound()
|
c.NotFound()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -146,18 +146,12 @@ func authenticatedUserID(store AuthStore, c *macaron.Context, sess session.Store
|
|||||||
|
|
||||||
// Check access token.
|
// Check access token.
|
||||||
if isAPIPath(c.Req.URL.Path) {
|
if isAPIPath(c.Req.URL.Path) {
|
||||||
tokenSHA := c.Query("token")
|
var tokenSHA string
|
||||||
if len(tokenSHA) <= 0 {
|
auHead := c.Req.Header.Get("Authorization")
|
||||||
tokenSHA = c.Query("access_token")
|
if auHead != "" {
|
||||||
}
|
auths := strings.Fields(auHead)
|
||||||
if tokenSHA == "" {
|
if len(auths) == 2 && auths[0] == "token" {
|
||||||
// Well, check with header again.
|
tokenSHA = auths[1]
|
||||||
auHead := c.Req.Header.Get("Authorization")
|
|
||||||
if len(auHead) > 0 {
|
|
||||||
auths := strings.Fields(auHead)
|
|
||||||
if len(auths) == 2 && auths[0] == "token" {
|
|
||||||
tokenSHA = auths[1]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import (
|
|||||||
|
|
||||||
"gogs.io/gogs/internal/conf"
|
"gogs.io/gogs/internal/conf"
|
||||||
"gogs.io/gogs/internal/database"
|
"gogs.io/gogs/internal/database"
|
||||||
"gogs.io/gogs/internal/errutil"
|
"gogs.io/gogs/internal/errx"
|
||||||
"gogs.io/gogs/internal/form"
|
"gogs.io/gogs/internal/form"
|
||||||
"gogs.io/gogs/internal/lazyregexp"
|
"gogs.io/gogs/internal/lazyregexp"
|
||||||
"gogs.io/gogs/internal/template"
|
"gogs.io/gogs/internal/template"
|
||||||
@@ -182,7 +182,7 @@ func (c *Context) Errorf(err error, format string, args ...any) {
|
|||||||
|
|
||||||
// NotFoundOrError responses with 404 page for not found error and 500 page otherwise.
|
// NotFoundOrError responses with 404 page for not found error and 500 page otherwise.
|
||||||
func (c *Context) NotFoundOrError(err error, msg string) {
|
func (c *Context) NotFoundOrError(err error, msg string) {
|
||||||
if errutil.IsNotFound(err) {
|
if errx.IsNotFound(err) {
|
||||||
c.NotFound()
|
c.NotFound()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import (
|
|||||||
|
|
||||||
"gogs.io/gogs/internal/conf"
|
"gogs.io/gogs/internal/conf"
|
||||||
"gogs.io/gogs/internal/database"
|
"gogs.io/gogs/internal/database"
|
||||||
"gogs.io/gogs/internal/repoutil"
|
"gogs.io/gogs/internal/repox"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ServeGoGet does quick responses for appropriate go-get meta with status OK
|
// ServeGoGet does quick responses for appropriate go-get meta with status OK
|
||||||
@@ -53,7 +53,7 @@ func ServeGoGet() macaron.Handler {
|
|||||||
`,
|
`,
|
||||||
map[string]string{
|
map[string]string{
|
||||||
"GoGetImport": path.Join(conf.Server.URL.Host, conf.Server.Subpath, ownerName, repoName),
|
"GoGetImport": path.Join(conf.Server.URL.Host, conf.Server.Subpath, ownerName, repoName),
|
||||||
"CloneLink": repoutil.HTTPSCloneURL(ownerName, repoName),
|
"CloneLink": repox.HTTPSCloneURL(ownerName, repoName),
|
||||||
"GoDocDirectory": prefix + "{/dir}",
|
"GoDocDirectory": prefix + "{/dir}",
|
||||||
"GoDocFile": prefix + "{/dir}/{file}#L{line}",
|
"GoDocFile": prefix + "{/dir}/{file}#L{line}",
|
||||||
"InsecureFlag": insecureFlag,
|
"InsecureFlag": insecureFlag,
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
|
|
||||||
"gogs.io/gogs/internal/conf"
|
"gogs.io/gogs/internal/conf"
|
||||||
"gogs.io/gogs/internal/markup"
|
"gogs.io/gogs/internal/markup"
|
||||||
"gogs.io/gogs/internal/osutil"
|
"gogs.io/gogs/internal/osx"
|
||||||
"gogs.io/gogs/internal/tool"
|
"gogs.io/gogs/internal/tool"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@ import (
|
|||||||
// on all pages.
|
// on all pages.
|
||||||
func (c *Context) renderNoticeBanner() {
|
func (c *Context) renderNoticeBanner() {
|
||||||
fpath := filepath.Join(conf.CustomDir(), "notice", "banner.md")
|
fpath := filepath.Join(conf.CustomDir(), "notice", "banner.md")
|
||||||
if !osutil.Exist(fpath) {
|
if !osx.Exist(fpath) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,5 +54,5 @@ func (c *Context) renderNoticeBanner() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Data["ServerNotice"] = string(markup.SanitizeBytes(markup.RawMarkdown(buf, "")))
|
c.Data["ServerNotice"] = string(markup.RawMarkdown(buf, ""))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import (
|
|||||||
|
|
||||||
"gogs.io/gogs/internal/conf"
|
"gogs.io/gogs/internal/conf"
|
||||||
"gogs.io/gogs/internal/database"
|
"gogs.io/gogs/internal/database"
|
||||||
"gogs.io/gogs/internal/repoutil"
|
"gogs.io/gogs/internal/repox"
|
||||||
)
|
)
|
||||||
|
|
||||||
type PullRequest struct {
|
type PullRequest struct {
|
||||||
@@ -40,7 +40,7 @@ type Repository struct {
|
|||||||
TreePath string
|
TreePath string
|
||||||
CommitID string
|
CommitID string
|
||||||
RepoLink string
|
RepoLink string
|
||||||
CloneLink repoutil.CloneLink
|
CloneLink repox.CloneLink
|
||||||
CommitsCount int64
|
CommitsCount int64
|
||||||
Mirror *database.Mirror
|
Mirror *database.Mirror
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package cryptoutil
|
package cryptox
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/aes"
|
"crypto/aes"
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package cryptoutil
|
package cryptox
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package cryptoutil
|
package cryptox
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/md5"
|
"crypto/md5"
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package cryptoutil
|
package cryptox
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package cryptoutil
|
package cryptox
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/sha1"
|
"crypto/sha1"
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package cryptoutil
|
package cryptox
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
@@ -9,8 +9,8 @@ import (
|
|||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
|
|
||||||
"gogs.io/gogs/internal/cryptoutil"
|
"gogs.io/gogs/internal/cryptox"
|
||||||
"gogs.io/gogs/internal/errutil"
|
"gogs.io/gogs/internal/errx"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AccessToken is a personal access token.
|
// AccessToken is a personal access token.
|
||||||
@@ -58,7 +58,7 @@ func newAccessTokensStore(db *gorm.DB) *AccessTokensStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ErrAccessTokenAlreadyExist struct {
|
type ErrAccessTokenAlreadyExist struct {
|
||||||
args errutil.Args
|
args errx.Args
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsErrAccessTokenAlreadyExist(err error) bool {
|
func IsErrAccessTokenAlreadyExist(err error) bool {
|
||||||
@@ -75,13 +75,13 @@ func (err ErrAccessTokenAlreadyExist) Error() string {
|
|||||||
func (s *AccessTokensStore) Create(ctx context.Context, userID int64, name string) (*AccessToken, error) {
|
func (s *AccessTokensStore) Create(ctx context.Context, userID int64, name string) (*AccessToken, error) {
|
||||||
err := s.db.WithContext(ctx).Where("uid = ? AND name = ?", userID, name).First(new(AccessToken)).Error
|
err := s.db.WithContext(ctx).Where("uid = ? AND name = ?", userID, name).First(new(AccessToken)).Error
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return nil, ErrAccessTokenAlreadyExist{args: errutil.Args{"userID": userID, "name": name}}
|
return nil, ErrAccessTokenAlreadyExist{args: errx.Args{"userID": userID, "name": name}}
|
||||||
} else if !errors.Is(err, gorm.ErrRecordNotFound) {
|
} else if !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
token := cryptoutil.SHA1(uuid.New().String())
|
token := cryptox.SHA1(uuid.New().String())
|
||||||
sha256 := cryptoutil.SHA256(token)
|
sha256 := cryptox.SHA256(token)
|
||||||
|
|
||||||
accessToken := &AccessToken{
|
accessToken := &AccessToken{
|
||||||
UserID: userID,
|
UserID: userID,
|
||||||
@@ -106,10 +106,10 @@ func (s *AccessTokensStore) DeleteByID(ctx context.Context, userID, id int64) er
|
|||||||
return s.db.WithContext(ctx).Where("id = ? AND uid = ?", id, userID).Delete(new(AccessToken)).Error
|
return s.db.WithContext(ctx).Where("id = ? AND uid = ?", id, userID).Delete(new(AccessToken)).Error
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ errutil.NotFound = (*ErrAccessTokenNotExist)(nil)
|
var _ errx.NotFound = (*ErrAccessTokenNotExist)(nil)
|
||||||
|
|
||||||
type ErrAccessTokenNotExist struct {
|
type ErrAccessTokenNotExist struct {
|
||||||
args errutil.Args
|
args errx.Args
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsErrAccessTokenNotExist returns true if the underlying error has the type
|
// IsErrAccessTokenNotExist returns true if the underlying error has the type
|
||||||
@@ -131,14 +131,14 @@ func (ErrAccessTokenNotExist) NotFound() bool {
|
|||||||
func (s *AccessTokensStore) GetBySHA1(ctx context.Context, sha1 string) (*AccessToken, error) {
|
func (s *AccessTokensStore) GetBySHA1(ctx context.Context, sha1 string) (*AccessToken, error) {
|
||||||
// No need to waste a query for an empty SHA1.
|
// No need to waste a query for an empty SHA1.
|
||||||
if sha1 == "" {
|
if sha1 == "" {
|
||||||
return nil, ErrAccessTokenNotExist{args: errutil.Args{"sha": sha1}}
|
return nil, ErrAccessTokenNotExist{args: errx.Args{"sha": sha1}}
|
||||||
}
|
}
|
||||||
|
|
||||||
sha256 := cryptoutil.SHA256(sha1)
|
sha256 := cryptox.SHA256(sha1)
|
||||||
token := new(AccessToken)
|
token := new(AccessToken)
|
||||||
err := s.db.WithContext(ctx).Where("sha256 = ?", sha256).First(token).Error
|
err := s.db.WithContext(ctx).Where("sha256 = ?", sha256).First(token).Error
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
return nil, ErrAccessTokenNotExist{args: errutil.Args{"sha": sha1}}
|
return nil, ErrAccessTokenNotExist{args: errx.Args{"sha": sha1}}
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import (
|
|||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
|
|
||||||
"gogs.io/gogs/internal/errutil"
|
"gogs.io/gogs/internal/errx"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestAccessToken_BeforeCreate(t *testing.T) {
|
func TestAccessToken_BeforeCreate(t *testing.T) {
|
||||||
@@ -138,7 +138,7 @@ func accessTokensCreate(t *testing.T, ctx context.Context, s *AccessTokensStore)
|
|||||||
// Try create second access token with same name should fail
|
// Try create second access token with same name should fail
|
||||||
_, err = s.Create(ctx, token.UserID, token.Name)
|
_, err = s.Create(ctx, token.UserID, token.Name)
|
||||||
wantErr := ErrAccessTokenAlreadyExist{
|
wantErr := ErrAccessTokenAlreadyExist{
|
||||||
args: errutil.Args{
|
args: errx.Args{
|
||||||
"userID": token.UserID,
|
"userID": token.UserID,
|
||||||
"name": token.Name,
|
"name": token.Name,
|
||||||
},
|
},
|
||||||
@@ -166,7 +166,7 @@ func accessTokensDeleteByID(t *testing.T, ctx context.Context, s *AccessTokensSt
|
|||||||
// We should get token not found error
|
// We should get token not found error
|
||||||
_, err = s.GetBySHA1(ctx, token.Sha1)
|
_, err = s.GetBySHA1(ctx, token.Sha1)
|
||||||
wantErr := ErrAccessTokenNotExist{
|
wantErr := ErrAccessTokenNotExist{
|
||||||
args: errutil.Args{
|
args: errx.Args{
|
||||||
"sha": token.Sha1,
|
"sha": token.Sha1,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -185,7 +185,7 @@ func accessTokensGetBySHA(t *testing.T, ctx context.Context, s *AccessTokensStor
|
|||||||
// Try to get a non-existent token
|
// Try to get a non-existent token
|
||||||
_, err = s.GetBySHA1(ctx, "bad_sha")
|
_, err = s.GetBySHA1(ctx, "bad_sha")
|
||||||
wantErr := ErrAccessTokenNotExist{
|
wantErr := ErrAccessTokenNotExist{
|
||||||
args: errutil.Args{
|
args: errx.Args{
|
||||||
"sha": "bad_sha",
|
"sha": "bad_sha",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package database
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"path"
|
"path"
|
||||||
"strconv"
|
"strconv"
|
||||||
@@ -11,16 +12,15 @@ import (
|
|||||||
|
|
||||||
"github.com/cockroachdb/errors"
|
"github.com/cockroachdb/errors"
|
||||||
"github.com/gogs/git-module"
|
"github.com/gogs/git-module"
|
||||||
api "github.com/gogs/go-gogs-client"
|
|
||||||
jsoniter "github.com/json-iterator/go"
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
log "unknwon.dev/clog/v2"
|
log "unknwon.dev/clog/v2"
|
||||||
|
|
||||||
"gogs.io/gogs/internal/conf"
|
"gogs.io/gogs/internal/conf"
|
||||||
"gogs.io/gogs/internal/lazyregexp"
|
"gogs.io/gogs/internal/lazyregexp"
|
||||||
"gogs.io/gogs/internal/repoutil"
|
"gogs.io/gogs/internal/repox"
|
||||||
"gogs.io/gogs/internal/strutil"
|
apiv1types "gogs.io/gogs/internal/route/api/v1/types"
|
||||||
"gogs.io/gogs/internal/testutil"
|
"gogs.io/gogs/internal/strx"
|
||||||
|
"gogs.io/gogs/internal/testx"
|
||||||
"gogs.io/gogs/internal/tool"
|
"gogs.io/gogs/internal/tool"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -218,19 +218,19 @@ func (s *ActionsStore) MirrorSyncPush(ctx context.Context, opts MirrorSyncPushOp
|
|||||||
|
|
||||||
apiCommits, err := opts.Commits.APIFormat(ctx,
|
apiCommits, err := opts.Commits.APIFormat(ctx,
|
||||||
newUsersStore(s.db),
|
newUsersStore(s.db),
|
||||||
repoutil.RepositoryPath(opts.Owner.Name, opts.Repo.Name),
|
repox.RepositoryPath(opts.Owner.Name, opts.Repo.Name),
|
||||||
repoutil.HTMLURL(opts.Owner.Name, opts.Repo.Name),
|
repox.HTMLURL(opts.Owner.Name, opts.Repo.Name),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "convert commits to API format")
|
return errors.Wrap(err, "convert commits to API format")
|
||||||
}
|
}
|
||||||
|
|
||||||
opts.Commits.CompareURL = repoutil.CompareCommitsPath(opts.Owner.Name, opts.Repo.Name, opts.OldCommitID, opts.NewCommitID)
|
opts.Commits.CompareURL = repox.CompareCommitsPath(opts.Owner.Name, opts.Repo.Name, opts.OldCommitID, opts.NewCommitID)
|
||||||
apiPusher := opts.Owner.APIFormat()
|
apiPusher := opts.Owner.APIFormat()
|
||||||
err = PrepareWebhooks(
|
err = PrepareWebhooks(
|
||||||
opts.Repo,
|
opts.Repo,
|
||||||
HookEventTypePush,
|
HookEventTypePush,
|
||||||
&api.PushPayload{
|
&apiv1types.WebhookPushPayload{
|
||||||
Ref: opts.RefName,
|
Ref: opts.RefName,
|
||||||
Before: opts.OldCommitID,
|
Before: opts.OldCommitID,
|
||||||
After: opts.NewCommitID,
|
After: opts.NewCommitID,
|
||||||
@@ -245,7 +245,7 @@ func (s *ActionsStore) MirrorSyncPush(ctx context.Context, opts MirrorSyncPushOp
|
|||||||
return errors.Wrap(err, "prepare webhooks")
|
return errors.Wrap(err, "prepare webhooks")
|
||||||
}
|
}
|
||||||
|
|
||||||
data, err := jsoniter.Marshal(opts.Commits)
|
data, err := json.Marshal(opts.Commits)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "marshal JSON")
|
return errors.Wrap(err, "marshal JSON")
|
||||||
}
|
}
|
||||||
@@ -476,7 +476,7 @@ func (s *ActionsStore) CommitRepo(ctx context.Context, opts CommitRepoOptions) e
|
|||||||
|
|
||||||
// If not the first commit, set the compare URL.
|
// If not the first commit, set the compare URL.
|
||||||
if !isNewRef && !isDelRef {
|
if !isNewRef && !isDelRef {
|
||||||
opts.Commits.CompareURL = repoutil.CompareCommitsPath(opts.Owner.Name, opts.Repo.Name, opts.OldCommitID, opts.NewCommitID)
|
opts.Commits.CompareURL = repox.CompareCommitsPath(opts.Owner.Name, opts.Repo.Name, opts.OldCommitID, opts.NewCommitID)
|
||||||
}
|
}
|
||||||
|
|
||||||
refName := git.RefShortName(opts.RefFullName)
|
refName := git.RefShortName(opts.RefFullName)
|
||||||
@@ -496,10 +496,10 @@ func (s *ActionsStore) CommitRepo(ctx context.Context, opts CommitRepoOptions) e
|
|||||||
err = PrepareWebhooks(
|
err = PrepareWebhooks(
|
||||||
opts.Repo,
|
opts.Repo,
|
||||||
HookEventTypeDelete,
|
HookEventTypeDelete,
|
||||||
&api.DeletePayload{
|
&apiv1types.WebhookDeletePayload{
|
||||||
Ref: refName,
|
Ref: refName,
|
||||||
RefType: "branch",
|
RefType: "branch",
|
||||||
PusherType: api.PUSHER_TYPE_USER,
|
PusherType: apiv1types.WebhookPusherTypeUser,
|
||||||
Repo: apiRepo,
|
Repo: apiRepo,
|
||||||
Sender: apiPusher,
|
Sender: apiPusher,
|
||||||
},
|
},
|
||||||
@@ -529,7 +529,7 @@ func (s *ActionsStore) CommitRepo(ctx context.Context, opts CommitRepoOptions) e
|
|||||||
opts.Commits.Commits = opts.Commits.Commits[:conf.UI.FeedMaxCommitNum]
|
opts.Commits.Commits = opts.Commits.Commits[:conf.UI.FeedMaxCommitNum]
|
||||||
}
|
}
|
||||||
|
|
||||||
data, err := jsoniter.Marshal(opts.Commits)
|
data, err := json.Marshal(opts.Commits)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "marshal JSON")
|
return errors.Wrap(err, "marshal JSON")
|
||||||
}
|
}
|
||||||
@@ -540,7 +540,7 @@ func (s *ActionsStore) CommitRepo(ctx context.Context, opts CommitRepoOptions) e
|
|||||||
err = PrepareWebhooks(
|
err = PrepareWebhooks(
|
||||||
opts.Repo,
|
opts.Repo,
|
||||||
HookEventTypeCreate,
|
HookEventTypeCreate,
|
||||||
&api.CreatePayload{
|
&apiv1types.WebhookCreatePayload{
|
||||||
Ref: refName,
|
Ref: refName,
|
||||||
RefType: "branch",
|
RefType: "branch",
|
||||||
DefaultBranch: opts.Repo.DefaultBranch,
|
DefaultBranch: opts.Repo.DefaultBranch,
|
||||||
@@ -563,8 +563,8 @@ func (s *ActionsStore) CommitRepo(ctx context.Context, opts CommitRepoOptions) e
|
|||||||
|
|
||||||
commits, err := opts.Commits.APIFormat(ctx,
|
commits, err := opts.Commits.APIFormat(ctx,
|
||||||
newUsersStore(s.db),
|
newUsersStore(s.db),
|
||||||
repoutil.RepositoryPath(opts.Owner.Name, opts.Repo.Name),
|
repox.RepositoryPath(opts.Owner.Name, opts.Repo.Name),
|
||||||
repoutil.HTMLURL(opts.Owner.Name, opts.Repo.Name),
|
repox.HTMLURL(opts.Owner.Name, opts.Repo.Name),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "convert commits to API format")
|
return errors.Wrap(err, "convert commits to API format")
|
||||||
@@ -573,7 +573,7 @@ func (s *ActionsStore) CommitRepo(ctx context.Context, opts CommitRepoOptions) e
|
|||||||
err = PrepareWebhooks(
|
err = PrepareWebhooks(
|
||||||
opts.Repo,
|
opts.Repo,
|
||||||
HookEventTypePush,
|
HookEventTypePush,
|
||||||
&api.PushPayload{
|
&apiv1types.WebhookPushPayload{
|
||||||
Ref: opts.RefFullName,
|
Ref: opts.RefFullName,
|
||||||
Before: opts.OldCommitID,
|
Before: opts.OldCommitID,
|
||||||
After: opts.NewCommitID,
|
After: opts.NewCommitID,
|
||||||
@@ -635,10 +635,10 @@ func (s *ActionsStore) PushTag(ctx context.Context, opts PushTagOptions) error {
|
|||||||
err = PrepareWebhooks(
|
err = PrepareWebhooks(
|
||||||
opts.Repo,
|
opts.Repo,
|
||||||
HookEventTypeDelete,
|
HookEventTypeDelete,
|
||||||
&api.DeletePayload{
|
&apiv1types.WebhookDeletePayload{
|
||||||
Ref: refName,
|
Ref: refName,
|
||||||
RefType: "tag",
|
RefType: "tag",
|
||||||
PusherType: api.PUSHER_TYPE_USER,
|
PusherType: apiv1types.WebhookPusherTypeUser,
|
||||||
Repo: apiRepo,
|
Repo: apiRepo,
|
||||||
Sender: apiPusher,
|
Sender: apiPusher,
|
||||||
},
|
},
|
||||||
@@ -658,7 +658,7 @@ func (s *ActionsStore) PushTag(ctx context.Context, opts PushTagOptions) error {
|
|||||||
err = PrepareWebhooks(
|
err = PrepareWebhooks(
|
||||||
opts.Repo,
|
opts.Repo,
|
||||||
HookEventTypeCreate,
|
HookEventTypeCreate,
|
||||||
&api.CreatePayload{
|
&apiv1types.WebhookCreatePayload{
|
||||||
Ref: refName,
|
Ref: refName,
|
||||||
RefType: "tag",
|
RefType: "tag",
|
||||||
Sha: opts.NewCommitID,
|
Sha: opts.NewCommitID,
|
||||||
@@ -751,7 +751,7 @@ func (a *Action) GetActUserName() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *Action) ShortActUserName() string {
|
func (a *Action) ShortActUserName() string {
|
||||||
return strutil.Ellipsis(a.ActUserName, 20)
|
return strx.Ellipsis(a.ActUserName, 20)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Action) GetRepoUserName() string {
|
func (a *Action) GetRepoUserName() string {
|
||||||
@@ -759,7 +759,7 @@ func (a *Action) GetRepoUserName() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *Action) ShortRepoUserName() string {
|
func (a *Action) ShortRepoUserName() string {
|
||||||
return strutil.Ellipsis(a.RepoUserName, 20)
|
return strx.Ellipsis(a.RepoUserName, 20)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Action) GetRepoName() string {
|
func (a *Action) GetRepoName() string {
|
||||||
@@ -767,7 +767,7 @@ func (a *Action) GetRepoName() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *Action) ShortRepoName() string {
|
func (a *Action) ShortRepoName() string {
|
||||||
return strutil.Ellipsis(a.RepoName, 33)
|
return strx.Ellipsis(a.RepoName, 33)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Action) GetRepoPath() string {
|
func (a *Action) GetRepoPath() string {
|
||||||
@@ -848,7 +848,7 @@ func NewPushCommits() *PushCommits {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pcs *PushCommits) APIFormat(ctx context.Context, usersStore *UsersStore, repoPath, repoURL string) ([]*api.PayloadCommit, error) {
|
func (pcs *PushCommits) APIFormat(ctx context.Context, usersStore *UsersStore, repoPath, repoURL string) ([]*apiv1types.WebhookPayloadCommit, error) {
|
||||||
// NOTE: We cache query results in case there are many commits in a single push.
|
// NOTE: We cache query results in case there are many commits in a single push.
|
||||||
usernameByEmail := make(map[string]string)
|
usernameByEmail := make(map[string]string)
|
||||||
getUsernameByEmail := func(email string) (string, error) {
|
getUsernameByEmail := func(email string) (string, error) {
|
||||||
@@ -870,7 +870,7 @@ func (pcs *PushCommits) APIFormat(ctx context.Context, usersStore *UsersStore, r
|
|||||||
return user.Name, nil
|
return user.Name, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
commits := make([]*api.PayloadCommit, len(pcs.Commits))
|
commits := make([]*apiv1types.WebhookPayloadCommit, len(pcs.Commits))
|
||||||
for i, commit := range pcs.Commits {
|
for i, commit := range pcs.Commits {
|
||||||
authorUsername, err := getUsernameByEmail(commit.AuthorEmail)
|
authorUsername, err := getUsernameByEmail(commit.AuthorEmail)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -883,23 +883,23 @@ func (pcs *PushCommits) APIFormat(ctx context.Context, usersStore *UsersStore, r
|
|||||||
}
|
}
|
||||||
|
|
||||||
nameStatus := &git.NameStatus{}
|
nameStatus := &git.NameStatus{}
|
||||||
if !testutil.InTest {
|
if !testx.InTest {
|
||||||
nameStatus, err = git.ShowNameStatus(repoPath, commit.Sha1)
|
nameStatus, err = git.ShowNameStatus(repoPath, commit.Sha1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "show name status [commit_sha1: %s]", commit.Sha1)
|
return nil, errors.Wrapf(err, "show name status [commit_sha1: %s]", commit.Sha1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
commits[i] = &api.PayloadCommit{
|
commits[i] = &apiv1types.WebhookPayloadCommit{
|
||||||
ID: commit.Sha1,
|
ID: commit.Sha1,
|
||||||
Message: commit.Message,
|
Message: commit.Message,
|
||||||
URL: fmt.Sprintf("%s/commit/%s", repoURL, commit.Sha1),
|
URL: fmt.Sprintf("%s/commit/%s", repoURL, commit.Sha1),
|
||||||
Author: &api.PayloadUser{
|
Author: &apiv1types.WebhookPayloadUser{
|
||||||
Name: commit.AuthorName,
|
Name: commit.AuthorName,
|
||||||
Email: commit.AuthorEmail,
|
Email: commit.AuthorEmail,
|
||||||
UserName: authorUsername,
|
UserName: authorUsername,
|
||||||
},
|
},
|
||||||
Committer: &api.PayloadUser{
|
Committer: &apiv1types.WebhookPayloadUser{
|
||||||
Name: commit.CommitterName,
|
Name: commit.CommitterName,
|
||||||
Email: commit.CommitterEmail,
|
Email: commit.CommitterEmail,
|
||||||
UserName: committerUsername,
|
UserName: committerUsername,
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import (
|
|||||||
"xorm.io/xorm"
|
"xorm.io/xorm"
|
||||||
|
|
||||||
"gogs.io/gogs/internal/conf"
|
"gogs.io/gogs/internal/conf"
|
||||||
"gogs.io/gogs/internal/errutil"
|
"gogs.io/gogs/internal/errx"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Attachment represent a attachment of issue/comment/release.
|
// Attachment represent a attachment of issue/comment/release.
|
||||||
@@ -81,7 +81,7 @@ func NewAttachment(name string, buf []byte, file multipart.File) (_ *Attachment,
|
|||||||
return attach, nil
|
return attach, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ errutil.NotFound = (*ErrAttachmentNotExist)(nil)
|
var _ errx.NotFound = (*ErrAttachmentNotExist)(nil)
|
||||||
|
|
||||||
type ErrAttachmentNotExist struct {
|
type ErrAttachmentNotExist struct {
|
||||||
args map[string]any
|
args map[string]any
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
@@ -13,7 +14,6 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/cockroachdb/errors"
|
"github.com/cockroachdb/errors"
|
||||||
jsoniter "github.com/json-iterator/go"
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
"gorm.io/gorm/schema"
|
"gorm.io/gorm/schema"
|
||||||
log "unknwon.dev/clog/v2"
|
log "unknwon.dev/clog/v2"
|
||||||
@@ -21,7 +21,7 @@ import (
|
|||||||
"xorm.io/xorm"
|
"xorm.io/xorm"
|
||||||
|
|
||||||
"gogs.io/gogs/internal/conf"
|
"gogs.io/gogs/internal/conf"
|
||||||
"gogs.io/gogs/internal/osutil"
|
"gogs.io/gogs/internal/osx"
|
||||||
)
|
)
|
||||||
|
|
||||||
// getTableType returns the type name of a table definition without package name,
|
// getTableType returns the type name of a table definition without package name,
|
||||||
@@ -99,7 +99,7 @@ func dumpTable(ctx context.Context, db *gorm.DB, table any, w io.Writer) error {
|
|||||||
e.CreatedAt = e.CreatedAt.UTC()
|
e.CreatedAt = e.CreatedAt.UTC()
|
||||||
}
|
}
|
||||||
|
|
||||||
err = jsoniter.NewEncoder(w).Encode(elem)
|
err = json.NewEncoder(w).Encode(elem)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "encode JSON")
|
return errors.Wrap(err, "encode JSON")
|
||||||
}
|
}
|
||||||
@@ -129,7 +129,7 @@ func dumpLegacyTables(ctx context.Context, dirPath string, verbose bool) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err = x.Context(ctx).Asc("id").Iterate(table, func(idx int, bean any) (err error) {
|
if err = x.Context(ctx).Asc("id").Iterate(table, func(idx int, bean any) (err error) {
|
||||||
return jsoniter.NewEncoder(f).Encode(bean)
|
return json.NewEncoder(f).Encode(bean)
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
_ = f.Close()
|
_ = f.Close()
|
||||||
return errors.Newf("dump table '%s': %v", tableName, err)
|
return errors.Newf("dump table '%s': %v", tableName, err)
|
||||||
@@ -156,7 +156,7 @@ func ImportDatabase(ctx context.Context, db *gorm.DB, dirPath string, verbose bo
|
|||||||
tableName := strings.TrimPrefix(fmt.Sprintf("%T", table), "*database.")
|
tableName := strings.TrimPrefix(fmt.Sprintf("%T", table), "*database.")
|
||||||
err := func() error {
|
err := func() error {
|
||||||
tableFile := filepath.Join(dirPath, tableName+".json")
|
tableFile := filepath.Join(dirPath, tableName+".json")
|
||||||
if !osutil.IsFile(tableFile) {
|
if !osx.IsFile(tableFile) {
|
||||||
log.Info("Skipped table %q", tableName)
|
log.Info("Skipped table %q", tableName)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -207,7 +207,7 @@ func importTable(ctx context.Context, db *gorm.DB, table any, r io.Reader) error
|
|||||||
cleaned := bytes.ReplaceAll(scanner.Bytes(), []byte("\\u0000"), []byte(""))
|
cleaned := bytes.ReplaceAll(scanner.Bytes(), []byte("\\u0000"), []byte(""))
|
||||||
|
|
||||||
elem := reflect.New(reflect.TypeOf(table).Elem()).Interface()
|
elem := reflect.New(reflect.TypeOf(table).Elem()).Interface()
|
||||||
err = jsoniter.Unmarshal(cleaned, elem)
|
err = json.Unmarshal(cleaned, elem)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "unmarshal JSON to struct")
|
return errors.Wrap(err, "unmarshal JSON to struct")
|
||||||
}
|
}
|
||||||
@@ -247,7 +247,7 @@ func importLegacyTables(ctx context.Context, dirPath string, verbose bool) error
|
|||||||
|
|
||||||
tableName := strings.TrimPrefix(fmt.Sprintf("%T", table), "*database.")
|
tableName := strings.TrimPrefix(fmt.Sprintf("%T", table), "*database.")
|
||||||
tableFile := filepath.Join(dirPath, tableName+".json")
|
tableFile := filepath.Join(dirPath, tableName+".json")
|
||||||
if !osutil.IsFile(tableFile) {
|
if !osx.IsFile(tableFile) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -269,7 +269,7 @@ func importLegacyTables(ctx context.Context, dirPath string, verbose bool) error
|
|||||||
_, isInsertProcessor := table.(xorm.BeforeInsertProcessor)
|
_, isInsertProcessor := table.(xorm.BeforeInsertProcessor)
|
||||||
scanner := bufio.NewScanner(f)
|
scanner := bufio.NewScanner(f)
|
||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
if err = jsoniter.Unmarshal(scanner.Bytes(), table); err != nil {
|
if err = json.Unmarshal(scanner.Bytes(), table); err != nil {
|
||||||
return errors.Newf("unmarshal to struct: %v", err)
|
return errors.Newf("unmarshal to struct: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -283,7 +283,7 @@ func importLegacyTables(ctx context.Context, dirPath string, verbose bool) error
|
|||||||
DeadlineUnix int64
|
DeadlineUnix int64
|
||||||
ClosedDateUnix int64
|
ClosedDateUnix int64
|
||||||
}
|
}
|
||||||
if err = jsoniter.Unmarshal(scanner.Bytes(), &meta); err != nil {
|
if err = json.Unmarshal(scanner.Bytes(), &meta); err != nil {
|
||||||
log.Error("Failed to unmarshal to map: %v", err)
|
log.Error("Failed to unmarshal to map: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,10 +15,10 @@ import (
|
|||||||
"gogs.io/gogs/internal/auth"
|
"gogs.io/gogs/internal/auth"
|
||||||
"gogs.io/gogs/internal/auth/github"
|
"gogs.io/gogs/internal/auth/github"
|
||||||
"gogs.io/gogs/internal/auth/pam"
|
"gogs.io/gogs/internal/auth/pam"
|
||||||
"gogs.io/gogs/internal/cryptoutil"
|
"gogs.io/gogs/internal/cryptox"
|
||||||
"gogs.io/gogs/internal/dbtest"
|
"gogs.io/gogs/internal/dbtest"
|
||||||
"gogs.io/gogs/internal/lfsutil"
|
"gogs.io/gogs/internal/lfsx"
|
||||||
"gogs.io/gogs/internal/testutil"
|
"gogs.io/gogs/internal/testx"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestDumpAndImport(t *testing.T) {
|
func TestDumpAndImport(t *testing.T) {
|
||||||
@@ -59,30 +59,30 @@ func setupDBToDump(t *testing.T, db *gorm.DB) {
|
|||||||
&AccessToken{
|
&AccessToken{
|
||||||
UserID: 1,
|
UserID: 1,
|
||||||
Name: "test1",
|
Name: "test1",
|
||||||
Sha1: cryptoutil.SHA1("2910d03d-c0b5-4f71-bad5-c4086e4efae3"),
|
Sha1: cryptox.SHA1("2910d03d-c0b5-4f71-bad5-c4086e4efae3"),
|
||||||
SHA256: cryptoutil.SHA256(cryptoutil.SHA1("2910d03d-c0b5-4f71-bad5-c4086e4efae3")),
|
SHA256: cryptox.SHA256(cryptox.SHA1("2910d03d-c0b5-4f71-bad5-c4086e4efae3")),
|
||||||
CreatedUnix: 1588568886,
|
CreatedUnix: 1588568886,
|
||||||
UpdatedUnix: 1588572486, // 1 hour later
|
UpdatedUnix: 1588572486, // 1 hour later
|
||||||
},
|
},
|
||||||
&AccessToken{
|
&AccessToken{
|
||||||
UserID: 1,
|
UserID: 1,
|
||||||
Name: "test2",
|
Name: "test2",
|
||||||
Sha1: cryptoutil.SHA1("84117e17-7e67-4024-bd04-1c23e6e809d4"),
|
Sha1: cryptox.SHA1("84117e17-7e67-4024-bd04-1c23e6e809d4"),
|
||||||
SHA256: cryptoutil.SHA256(cryptoutil.SHA1("84117e17-7e67-4024-bd04-1c23e6e809d4")),
|
SHA256: cryptox.SHA256(cryptox.SHA1("84117e17-7e67-4024-bd04-1c23e6e809d4")),
|
||||||
CreatedUnix: 1588568886,
|
CreatedUnix: 1588568886,
|
||||||
},
|
},
|
||||||
&AccessToken{
|
&AccessToken{
|
||||||
UserID: 2,
|
UserID: 2,
|
||||||
Name: "test1",
|
Name: "test1",
|
||||||
Sha1: cryptoutil.SHA1("da2775ce-73dd-47ba-b9d2-bbcc346585c4"),
|
Sha1: cryptox.SHA1("da2775ce-73dd-47ba-b9d2-bbcc346585c4"),
|
||||||
SHA256: cryptoutil.SHA256(cryptoutil.SHA1("da2775ce-73dd-47ba-b9d2-bbcc346585c4")),
|
SHA256: cryptox.SHA256(cryptox.SHA1("da2775ce-73dd-47ba-b9d2-bbcc346585c4")),
|
||||||
CreatedUnix: 1588568886,
|
CreatedUnix: 1588568886,
|
||||||
},
|
},
|
||||||
&AccessToken{
|
&AccessToken{
|
||||||
UserID: 2,
|
UserID: 2,
|
||||||
Name: "test2",
|
Name: "test2",
|
||||||
Sha1: cryptoutil.SHA256(cryptoutil.SHA1("1b2dccd1-a262-470f-bb8c-7fc73192e9bb"))[:40],
|
Sha1: cryptox.SHA256(cryptox.SHA1("1b2dccd1-a262-470f-bb8c-7fc73192e9bb"))[:40],
|
||||||
SHA256: cryptoutil.SHA256(cryptoutil.SHA1("1b2dccd1-a262-470f-bb8c-7fc73192e9bb")),
|
SHA256: cryptox.SHA256(cryptox.SHA1("1b2dccd1-a262-470f-bb8c-7fc73192e9bb")),
|
||||||
CreatedUnix: 1588568886,
|
CreatedUnix: 1588568886,
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -156,14 +156,14 @@ func setupDBToDump(t *testing.T, db *gorm.DB) {
|
|||||||
RepoID: 1,
|
RepoID: 1,
|
||||||
OID: "ef797c8118f02dfb649607dd5d3f8c7623048c9c063d532cc95c5ed7a898a64f",
|
OID: "ef797c8118f02dfb649607dd5d3f8c7623048c9c063d532cc95c5ed7a898a64f",
|
||||||
Size: 100,
|
Size: 100,
|
||||||
Storage: lfsutil.StorageLocal,
|
Storage: lfsx.StorageLocal,
|
||||||
CreatedAt: time.Unix(1588568886, 0).UTC(),
|
CreatedAt: time.Unix(1588568886, 0).UTC(),
|
||||||
},
|
},
|
||||||
&LFSObject{
|
&LFSObject{
|
||||||
RepoID: 2,
|
RepoID: 2,
|
||||||
OID: "ef797c8118f02dfb649607dd5d3f8c7623048c9c063d532cc95c5ed7a898a64f",
|
OID: "ef797c8118f02dfb649607dd5d3f8c7623048c9c063d532cc95c5ed7a898a64f",
|
||||||
Size: 100,
|
Size: 100,
|
||||||
Storage: lfsutil.StorageLocal,
|
Storage: lfsx.StorageLocal,
|
||||||
CreatedAt: time.Unix(1588568886, 0).UTC(),
|
CreatedAt: time.Unix(1588568886, 0).UTC(),
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -213,7 +213,7 @@ func dumpTables(t *testing.T, db *gorm.DB) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
golden := filepath.Join("testdata", "backup", tableName+".golden.json")
|
golden := filepath.Join("testdata", "backup", tableName+".golden.json")
|
||||||
testutil.AssertGolden(t, golden, testutil.Update("TestDumpAndImport"), buf.String())
|
testx.AssertGolden(t, golden, testx.Update("TestDumpAndImport"), buf.String())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,10 +11,9 @@ import (
|
|||||||
log "unknwon.dev/clog/v2"
|
log "unknwon.dev/clog/v2"
|
||||||
"xorm.io/xorm"
|
"xorm.io/xorm"
|
||||||
|
|
||||||
api "github.com/gogs/go-gogs-client"
|
"gogs.io/gogs/internal/errx"
|
||||||
|
|
||||||
"gogs.io/gogs/internal/errutil"
|
|
||||||
"gogs.io/gogs/internal/markup"
|
"gogs.io/gogs/internal/markup"
|
||||||
|
apiv1types "gogs.io/gogs/internal/route/api/v1/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CommentType defines whether a comment is just a simple comment, an action (like close) or a reference.
|
// CommentType defines whether a comment is just a simple comment, an action (like close) or a reference.
|
||||||
@@ -136,8 +135,8 @@ func (c *Comment) HTMLURL() string {
|
|||||||
|
|
||||||
// This method assumes following fields have been assigned with valid values:
|
// This method assumes following fields have been assigned with valid values:
|
||||||
// Required - Poster, Issue
|
// Required - Poster, Issue
|
||||||
func (c *Comment) APIFormat() *api.Comment {
|
func (c *Comment) APIFormat() *apiv1types.IssueComment {
|
||||||
return &api.Comment{
|
return &apiv1types.IssueComment{
|
||||||
ID: c.ID,
|
ID: c.ID,
|
||||||
HTMLURL: c.HTMLURL(),
|
HTMLURL: c.HTMLURL(),
|
||||||
Poster: c.Poster.APIFormat(),
|
Poster: c.Poster.APIFormat(),
|
||||||
@@ -347,8 +346,8 @@ func CreateIssueComment(doer *User, repo *Repository, issue *Issue, content stri
|
|||||||
}
|
}
|
||||||
|
|
||||||
comment.Issue = issue
|
comment.Issue = issue
|
||||||
if err = PrepareWebhooks(repo, HookEventTypeIssueComment, &api.IssueCommentPayload{
|
if err = PrepareWebhooks(repo, HookEventTypeIssueComment, &apiv1types.WebhookIssueCommentPayload{
|
||||||
Action: api.HOOK_ISSUE_COMMENT_CREATED,
|
Action: apiv1types.WebhookIssueCommentCreated,
|
||||||
Issue: issue.APIFormat(),
|
Issue: issue.APIFormat(),
|
||||||
Comment: comment.APIFormat(),
|
Comment: comment.APIFormat(),
|
||||||
Repository: repo.APIFormatLegacy(nil),
|
Repository: repo.APIFormatLegacy(nil),
|
||||||
@@ -389,7 +388,7 @@ func CreateRefComment(doer *User, repo *Repository, issue *Issue, content, commi
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ errutil.NotFound = (*ErrCommentNotExist)(nil)
|
var _ errx.NotFound = (*ErrCommentNotExist)(nil)
|
||||||
|
|
||||||
type ErrCommentNotExist struct {
|
type ErrCommentNotExist struct {
|
||||||
args map[string]any
|
args map[string]any
|
||||||
@@ -483,12 +482,12 @@ func UpdateComment(doer *User, c *Comment, oldContent string) (err error) {
|
|||||||
|
|
||||||
if err = c.Issue.LoadAttributes(); err != nil {
|
if err = c.Issue.LoadAttributes(); err != nil {
|
||||||
log.Error("Issue.LoadAttributes [issue_id: %d]: %v", c.IssueID, err)
|
log.Error("Issue.LoadAttributes [issue_id: %d]: %v", c.IssueID, err)
|
||||||
} else if err = PrepareWebhooks(c.Issue.Repo, HookEventTypeIssueComment, &api.IssueCommentPayload{
|
} else if err = PrepareWebhooks(c.Issue.Repo, HookEventTypeIssueComment, &apiv1types.WebhookIssueCommentPayload{
|
||||||
Action: api.HOOK_ISSUE_COMMENT_EDITED,
|
Action: apiv1types.WebhookIssueCommentEdited,
|
||||||
Issue: c.Issue.APIFormat(),
|
Issue: c.Issue.APIFormat(),
|
||||||
Comment: c.APIFormat(),
|
Comment: c.APIFormat(),
|
||||||
Changes: &api.ChangesPayload{
|
Changes: &apiv1types.WebhookChangesPayload{
|
||||||
Body: &api.ChangesFromPayload{
|
Body: &apiv1types.WebhookChangesFromPayload{
|
||||||
From: oldContent,
|
From: oldContent,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -538,8 +537,8 @@ func DeleteCommentByID(doer *User, id int64) error {
|
|||||||
|
|
||||||
if err = comment.Issue.LoadAttributes(); err != nil {
|
if err = comment.Issue.LoadAttributes(); err != nil {
|
||||||
log.Error("Issue.LoadAttributes [issue_id: %d]: %v", comment.IssueID, err)
|
log.Error("Issue.LoadAttributes [issue_id: %d]: %v", comment.IssueID, err)
|
||||||
} else if err = PrepareWebhooks(comment.Issue.Repo, HookEventTypeIssueComment, &api.IssueCommentPayload{
|
} else if err = PrepareWebhooks(comment.Issue.Repo, HookEventTypeIssueComment, &apiv1types.WebhookIssueCommentPayload{
|
||||||
Action: api.HOOK_ISSUE_COMMENT_DELETED,
|
Action: apiv1types.WebhookIssueCommentDeleted,
|
||||||
Issue: comment.Issue.APIFormat(),
|
Issue: comment.Issue.APIFormat(),
|
||||||
Comment: comment.APIFormat(),
|
Comment: comment.APIFormat(),
|
||||||
Repository: comment.Issue.Repo.APIFormatLegacy(nil),
|
Repository: comment.Issue.Repo.APIFormatLegacy(nil),
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import (
|
|||||||
log "unknwon.dev/clog/v2"
|
log "unknwon.dev/clog/v2"
|
||||||
|
|
||||||
"gogs.io/gogs/internal/conf"
|
"gogs.io/gogs/internal/conf"
|
||||||
"gogs.io/gogs/internal/dbutil"
|
"gogs.io/gogs/internal/dbx"
|
||||||
)
|
)
|
||||||
|
|
||||||
func newLogWriter() (logger.Writer, error) {
|
func newLogWriter() (logger.Writer, error) {
|
||||||
@@ -30,7 +30,7 @@ func newLogWriter() (logger.Writer, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, `create "gorm.log"`)
|
return nil, errors.Wrap(err, `create "gorm.log"`)
|
||||||
}
|
}
|
||||||
return &dbutil.Logger{Writer: w}, nil
|
return &dbx.Logger{Writer: w}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tables is the list of struct-to-table mappings.
|
// Tables is the list of struct-to-table mappings.
|
||||||
@@ -59,7 +59,7 @@ func NewConnection(w logger.Writer) (*gorm.DB, error) {
|
|||||||
LogLevel: level,
|
LogLevel: level,
|
||||||
})
|
})
|
||||||
|
|
||||||
db, err := dbutil.OpenDB(
|
db, err := dbx.OpenDB(
|
||||||
conf.Database,
|
conf.Database,
|
||||||
&gorm.Config{
|
&gorm.Config{
|
||||||
SkipDefaultTransaction: true,
|
SkipDefaultTransaction: true,
|
||||||
@@ -91,8 +91,6 @@ func NewConnection(w logger.Writer) (*gorm.DB, error) {
|
|||||||
db = db.Set("gorm:table_options", "ENGINE=InnoDB").Session(&gorm.Session{})
|
db = db.Set("gorm:table_options", "ENGINE=InnoDB").Session(&gorm.Session{})
|
||||||
case "sqlite3":
|
case "sqlite3":
|
||||||
conf.UseSQLite3 = true
|
conf.UseSQLite3 = true
|
||||||
case "mssql":
|
|
||||||
conf.UseMSSQL = true
|
|
||||||
default:
|
default:
|
||||||
panic("unreachable")
|
panic("unreachable")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,11 +11,10 @@ import (
|
|||||||
log "unknwon.dev/clog/v2"
|
log "unknwon.dev/clog/v2"
|
||||||
"xorm.io/xorm"
|
"xorm.io/xorm"
|
||||||
|
|
||||||
api "github.com/gogs/go-gogs-client"
|
|
||||||
|
|
||||||
"gogs.io/gogs/internal/conf"
|
"gogs.io/gogs/internal/conf"
|
||||||
"gogs.io/gogs/internal/errutil"
|
"gogs.io/gogs/internal/errx"
|
||||||
"gogs.io/gogs/internal/markup"
|
"gogs.io/gogs/internal/markup"
|
||||||
|
apiv1types "gogs.io/gogs/internal/route/api/v1/types"
|
||||||
"gogs.io/gogs/internal/tool"
|
"gogs.io/gogs/internal/tool"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -83,7 +82,7 @@ func getUserByID(e Engine, id int64) (*User, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
} else if !has {
|
} else if !has {
|
||||||
return nil, ErrUserNotExist{args: errutil.Args{"userID": id}}
|
return nil, ErrUserNotExist{args: errx.Args{"userID": id}}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(unknwon): Rely on AfterFind hook to sanitize user full name.
|
// TODO(unknwon): Rely on AfterFind hook to sanitize user full name.
|
||||||
@@ -172,23 +171,23 @@ func (issue *Issue) HTMLURL() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// State returns string representation of issue status.
|
// State returns string representation of issue status.
|
||||||
func (issue *Issue) State() api.StateType {
|
func (issue *Issue) State() apiv1types.IssueStateType {
|
||||||
if issue.IsClosed {
|
if issue.IsClosed {
|
||||||
return api.STATE_CLOSED
|
return apiv1types.IssueStateClosed
|
||||||
}
|
}
|
||||||
return api.STATE_OPEN
|
return apiv1types.IssueStateOpen
|
||||||
}
|
}
|
||||||
|
|
||||||
// This method assumes some fields assigned with values:
|
// This method assumes some fields assigned with values:
|
||||||
// Required - Poster, Labels,
|
// Required - Poster, Labels,
|
||||||
// Optional - Milestone, Assignee, PullRequest
|
// Optional - Milestone, Assignee, PullRequest
|
||||||
func (issue *Issue) APIFormat() *api.Issue {
|
func (issue *Issue) APIFormat() *apiv1types.Issue {
|
||||||
apiLabels := make([]*api.Label, len(issue.Labels))
|
apiLabels := make([]*apiv1types.IssueLabel, len(issue.Labels))
|
||||||
for i := range issue.Labels {
|
for i := range issue.Labels {
|
||||||
apiLabels[i] = issue.Labels[i].APIFormat()
|
apiLabels[i] = issue.Labels[i].APIFormat()
|
||||||
}
|
}
|
||||||
|
|
||||||
apiIssue := &api.Issue{
|
apiIssue := &apiv1types.Issue{
|
||||||
ID: issue.ID,
|
ID: issue.ID,
|
||||||
Index: issue.Index,
|
Index: issue.Index,
|
||||||
Poster: issue.Poster.APIFormat(),
|
Poster: issue.Poster.APIFormat(),
|
||||||
@@ -208,7 +207,7 @@ func (issue *Issue) APIFormat() *api.Issue {
|
|||||||
apiIssue.Assignee = issue.Assignee.APIFormat()
|
apiIssue.Assignee = issue.Assignee.APIFormat()
|
||||||
}
|
}
|
||||||
if issue.IsPull {
|
if issue.IsPull {
|
||||||
apiIssue.PullRequest = &api.PullRequestMeta{
|
apiIssue.PullRequest = &apiv1types.PullRequestMeta{
|
||||||
HasMerged: issue.PullRequest.HasMerged,
|
HasMerged: issue.PullRequest.HasMerged,
|
||||||
}
|
}
|
||||||
if issue.PullRequest.HasMerged {
|
if issue.PullRequest.HasMerged {
|
||||||
@@ -246,16 +245,16 @@ func (issue *Issue) sendLabelUpdatedWebhook(doer *User) {
|
|||||||
log.Error("LoadIssue: %v", err)
|
log.Error("LoadIssue: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = PrepareWebhooks(issue.Repo, HookEventTypePullRequest, &api.PullRequestPayload{
|
err = PrepareWebhooks(issue.Repo, HookEventTypePullRequest, &apiv1types.WebhookPullRequestPayload{
|
||||||
Action: api.HOOK_ISSUE_LABEL_UPDATED,
|
Action: apiv1types.WebhookIssueLabelUpdated,
|
||||||
Index: issue.Index,
|
Index: issue.Index,
|
||||||
PullRequest: issue.PullRequest.APIFormat(),
|
PullRequest: issue.PullRequest.APIFormat(),
|
||||||
Repository: issue.Repo.APIFormatLegacy(nil),
|
Repository: issue.Repo.APIFormatLegacy(nil),
|
||||||
Sender: doer.APIFormat(),
|
Sender: doer.APIFormat(),
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
err = PrepareWebhooks(issue.Repo, HookEventTypeIssues, &api.IssuesPayload{
|
err = PrepareWebhooks(issue.Repo, HookEventTypeIssues, &apiv1types.WebhookIssuesPayload{
|
||||||
Action: api.HOOK_ISSUE_LABEL_UPDATED,
|
Action: apiv1types.WebhookIssueLabelUpdated,
|
||||||
Index: issue.Index,
|
Index: issue.Index,
|
||||||
Issue: issue.APIFormat(),
|
Issue: issue.APIFormat(),
|
||||||
Repository: issue.Repo.APIFormatLegacy(nil),
|
Repository: issue.Repo.APIFormatLegacy(nil),
|
||||||
@@ -359,16 +358,16 @@ func (issue *Issue) ClearLabels(doer *User) (err error) {
|
|||||||
log.Error("LoadIssue: %v", err)
|
log.Error("LoadIssue: %v", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = PrepareWebhooks(issue.Repo, HookEventTypePullRequest, &api.PullRequestPayload{
|
err = PrepareWebhooks(issue.Repo, HookEventTypePullRequest, &apiv1types.WebhookPullRequestPayload{
|
||||||
Action: api.HOOK_ISSUE_LABEL_CLEARED,
|
Action: apiv1types.WebhookIssueLabelCleared,
|
||||||
Index: issue.Index,
|
Index: issue.Index,
|
||||||
PullRequest: issue.PullRequest.APIFormat(),
|
PullRequest: issue.PullRequest.APIFormat(),
|
||||||
Repository: issue.Repo.APIFormatLegacy(nil),
|
Repository: issue.Repo.APIFormatLegacy(nil),
|
||||||
Sender: doer.APIFormat(),
|
Sender: doer.APIFormat(),
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
err = PrepareWebhooks(issue.Repo, HookEventTypeIssues, &api.IssuesPayload{
|
err = PrepareWebhooks(issue.Repo, HookEventTypeIssues, &apiv1types.WebhookIssuesPayload{
|
||||||
Action: api.HOOK_ISSUE_LABEL_CLEARED,
|
Action: apiv1types.WebhookIssueLabelCleared,
|
||||||
Index: issue.Index,
|
Index: issue.Index,
|
||||||
Issue: issue.APIFormat(),
|
Issue: issue.APIFormat(),
|
||||||
Repository: issue.Repo.APIFormatLegacy(nil),
|
Repository: issue.Repo.APIFormatLegacy(nil),
|
||||||
@@ -487,29 +486,29 @@ func (issue *Issue) ChangeStatus(doer *User, repo *Repository, isClosed bool) (e
|
|||||||
if issue.IsPull {
|
if issue.IsPull {
|
||||||
// Merge pull request calls issue.changeStatus so we need to handle separately.
|
// Merge pull request calls issue.changeStatus so we need to handle separately.
|
||||||
issue.PullRequest.Issue = issue
|
issue.PullRequest.Issue = issue
|
||||||
apiPullRequest := &api.PullRequestPayload{
|
apiPullRequest := &apiv1types.WebhookPullRequestPayload{
|
||||||
Index: issue.Index,
|
Index: issue.Index,
|
||||||
PullRequest: issue.PullRequest.APIFormat(),
|
PullRequest: issue.PullRequest.APIFormat(),
|
||||||
Repository: repo.APIFormatLegacy(nil),
|
Repository: repo.APIFormatLegacy(nil),
|
||||||
Sender: doer.APIFormat(),
|
Sender: doer.APIFormat(),
|
||||||
}
|
}
|
||||||
if isClosed {
|
if isClosed {
|
||||||
apiPullRequest.Action = api.HOOK_ISSUE_CLOSED
|
apiPullRequest.Action = apiv1types.WebhookIssueClosed
|
||||||
} else {
|
} else {
|
||||||
apiPullRequest.Action = api.HOOK_ISSUE_REOPENED
|
apiPullRequest.Action = apiv1types.WebhookIssueReopened
|
||||||
}
|
}
|
||||||
err = PrepareWebhooks(repo, HookEventTypePullRequest, apiPullRequest)
|
err = PrepareWebhooks(repo, HookEventTypePullRequest, apiPullRequest)
|
||||||
} else {
|
} else {
|
||||||
apiIssues := &api.IssuesPayload{
|
apiIssues := &apiv1types.WebhookIssuesPayload{
|
||||||
Index: issue.Index,
|
Index: issue.Index,
|
||||||
Issue: issue.APIFormat(),
|
Issue: issue.APIFormat(),
|
||||||
Repository: repo.APIFormatLegacy(nil),
|
Repository: repo.APIFormatLegacy(nil),
|
||||||
Sender: doer.APIFormat(),
|
Sender: doer.APIFormat(),
|
||||||
}
|
}
|
||||||
if isClosed {
|
if isClosed {
|
||||||
apiIssues.Action = api.HOOK_ISSUE_CLOSED
|
apiIssues.Action = apiv1types.WebhookIssueClosed
|
||||||
} else {
|
} else {
|
||||||
apiIssues.Action = api.HOOK_ISSUE_REOPENED
|
apiIssues.Action = apiv1types.WebhookIssueReopened
|
||||||
}
|
}
|
||||||
err = PrepareWebhooks(repo, HookEventTypeIssues, apiIssues)
|
err = PrepareWebhooks(repo, HookEventTypeIssues, apiIssues)
|
||||||
}
|
}
|
||||||
@@ -529,12 +528,12 @@ func (issue *Issue) ChangeTitle(doer *User, title string) (err error) {
|
|||||||
|
|
||||||
if issue.IsPull {
|
if issue.IsPull {
|
||||||
issue.PullRequest.Issue = issue
|
issue.PullRequest.Issue = issue
|
||||||
err = PrepareWebhooks(issue.Repo, HookEventTypePullRequest, &api.PullRequestPayload{
|
err = PrepareWebhooks(issue.Repo, HookEventTypePullRequest, &apiv1types.WebhookPullRequestPayload{
|
||||||
Action: api.HOOK_ISSUE_EDITED,
|
Action: apiv1types.WebhookIssueEdited,
|
||||||
Index: issue.Index,
|
Index: issue.Index,
|
||||||
PullRequest: issue.PullRequest.APIFormat(),
|
PullRequest: issue.PullRequest.APIFormat(),
|
||||||
Changes: &api.ChangesPayload{
|
Changes: &apiv1types.WebhookChangesPayload{
|
||||||
Title: &api.ChangesFromPayload{
|
Title: &apiv1types.WebhookChangesFromPayload{
|
||||||
From: oldTitle,
|
From: oldTitle,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -542,12 +541,12 @@ func (issue *Issue) ChangeTitle(doer *User, title string) (err error) {
|
|||||||
Sender: doer.APIFormat(),
|
Sender: doer.APIFormat(),
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
err = PrepareWebhooks(issue.Repo, HookEventTypeIssues, &api.IssuesPayload{
|
err = PrepareWebhooks(issue.Repo, HookEventTypeIssues, &apiv1types.WebhookIssuesPayload{
|
||||||
Action: api.HOOK_ISSUE_EDITED,
|
Action: apiv1types.WebhookIssueEdited,
|
||||||
Index: issue.Index,
|
Index: issue.Index,
|
||||||
Issue: issue.APIFormat(),
|
Issue: issue.APIFormat(),
|
||||||
Changes: &api.ChangesPayload{
|
Changes: &apiv1types.WebhookChangesPayload{
|
||||||
Title: &api.ChangesFromPayload{
|
Title: &apiv1types.WebhookChangesFromPayload{
|
||||||
From: oldTitle,
|
From: oldTitle,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -571,12 +570,12 @@ func (issue *Issue) ChangeContent(doer *User, content string) (err error) {
|
|||||||
|
|
||||||
if issue.IsPull {
|
if issue.IsPull {
|
||||||
issue.PullRequest.Issue = issue
|
issue.PullRequest.Issue = issue
|
||||||
err = PrepareWebhooks(issue.Repo, HookEventTypePullRequest, &api.PullRequestPayload{
|
err = PrepareWebhooks(issue.Repo, HookEventTypePullRequest, &apiv1types.WebhookPullRequestPayload{
|
||||||
Action: api.HOOK_ISSUE_EDITED,
|
Action: apiv1types.WebhookIssueEdited,
|
||||||
Index: issue.Index,
|
Index: issue.Index,
|
||||||
PullRequest: issue.PullRequest.APIFormat(),
|
PullRequest: issue.PullRequest.APIFormat(),
|
||||||
Changes: &api.ChangesPayload{
|
Changes: &apiv1types.WebhookChangesPayload{
|
||||||
Body: &api.ChangesFromPayload{
|
Body: &apiv1types.WebhookChangesFromPayload{
|
||||||
From: oldContent,
|
From: oldContent,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -584,12 +583,12 @@ func (issue *Issue) ChangeContent(doer *User, content string) (err error) {
|
|||||||
Sender: doer.APIFormat(),
|
Sender: doer.APIFormat(),
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
err = PrepareWebhooks(issue.Repo, HookEventTypeIssues, &api.IssuesPayload{
|
err = PrepareWebhooks(issue.Repo, HookEventTypeIssues, &apiv1types.WebhookIssuesPayload{
|
||||||
Action: api.HOOK_ISSUE_EDITED,
|
Action: apiv1types.WebhookIssueEdited,
|
||||||
Index: issue.Index,
|
Index: issue.Index,
|
||||||
Issue: issue.APIFormat(),
|
Issue: issue.APIFormat(),
|
||||||
Changes: &api.ChangesPayload{
|
Changes: &apiv1types.WebhookChangesPayload{
|
||||||
Body: &api.ChangesFromPayload{
|
Body: &apiv1types.WebhookChangesFromPayload{
|
||||||
From: oldContent,
|
From: oldContent,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -620,29 +619,29 @@ func (issue *Issue) ChangeAssignee(doer *User, assigneeID int64) (err error) {
|
|||||||
isRemoveAssignee := err != nil
|
isRemoveAssignee := err != nil
|
||||||
if issue.IsPull {
|
if issue.IsPull {
|
||||||
issue.PullRequest.Issue = issue
|
issue.PullRequest.Issue = issue
|
||||||
apiPullRequest := &api.PullRequestPayload{
|
apiPullRequest := &apiv1types.WebhookPullRequestPayload{
|
||||||
Index: issue.Index,
|
Index: issue.Index,
|
||||||
PullRequest: issue.PullRequest.APIFormat(),
|
PullRequest: issue.PullRequest.APIFormat(),
|
||||||
Repository: issue.Repo.APIFormatLegacy(nil),
|
Repository: issue.Repo.APIFormatLegacy(nil),
|
||||||
Sender: doer.APIFormat(),
|
Sender: doer.APIFormat(),
|
||||||
}
|
}
|
||||||
if isRemoveAssignee {
|
if isRemoveAssignee {
|
||||||
apiPullRequest.Action = api.HOOK_ISSUE_UNASSIGNED
|
apiPullRequest.Action = apiv1types.WebhookIssueUnassigned
|
||||||
} else {
|
} else {
|
||||||
apiPullRequest.Action = api.HOOK_ISSUE_ASSIGNED
|
apiPullRequest.Action = apiv1types.WebhookIssueAssigned
|
||||||
}
|
}
|
||||||
err = PrepareWebhooks(issue.Repo, HookEventTypePullRequest, apiPullRequest)
|
err = PrepareWebhooks(issue.Repo, HookEventTypePullRequest, apiPullRequest)
|
||||||
} else {
|
} else {
|
||||||
apiIssues := &api.IssuesPayload{
|
apiIssues := &apiv1types.WebhookIssuesPayload{
|
||||||
Index: issue.Index,
|
Index: issue.Index,
|
||||||
Issue: issue.APIFormat(),
|
Issue: issue.APIFormat(),
|
||||||
Repository: issue.Repo.APIFormatLegacy(nil),
|
Repository: issue.Repo.APIFormatLegacy(nil),
|
||||||
Sender: doer.APIFormat(),
|
Sender: doer.APIFormat(),
|
||||||
}
|
}
|
||||||
if isRemoveAssignee {
|
if isRemoveAssignee {
|
||||||
apiIssues.Action = api.HOOK_ISSUE_UNASSIGNED
|
apiIssues.Action = apiv1types.WebhookIssueUnassigned
|
||||||
} else {
|
} else {
|
||||||
apiIssues.Action = api.HOOK_ISSUE_ASSIGNED
|
apiIssues.Action = apiv1types.WebhookIssueAssigned
|
||||||
}
|
}
|
||||||
err = PrepareWebhooks(issue.Repo, HookEventTypeIssues, apiIssues)
|
err = PrepareWebhooks(issue.Repo, HookEventTypeIssues, apiIssues)
|
||||||
}
|
}
|
||||||
@@ -789,8 +788,8 @@ func NewIssue(repo *Repository, issue *Issue, labelIDs []int64, uuids []string)
|
|||||||
log.Error("MailParticipants: %v", err)
|
log.Error("MailParticipants: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = PrepareWebhooks(repo, HookEventTypeIssues, &api.IssuesPayload{
|
if err = PrepareWebhooks(repo, HookEventTypeIssues, &apiv1types.WebhookIssuesPayload{
|
||||||
Action: api.HOOK_ISSUE_OPENED,
|
Action: apiv1types.WebhookIssueOpened,
|
||||||
Index: issue.Index,
|
Index: issue.Index,
|
||||||
Issue: issue.APIFormat(),
|
Issue: issue.APIFormat(),
|
||||||
Repository: repo.APIFormatLegacy(nil),
|
Repository: repo.APIFormatLegacy(nil),
|
||||||
@@ -802,7 +801,7 @@ func NewIssue(repo *Repository, issue *Issue, labelIDs []int64, uuids []string)
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ errutil.NotFound = (*ErrIssueNotExist)(nil)
|
var _ errx.NotFound = (*ErrIssueNotExist)(nil)
|
||||||
|
|
||||||
type ErrIssueNotExist struct {
|
type ErrIssueNotExist struct {
|
||||||
args map[string]any
|
args map[string]any
|
||||||
|
|||||||
@@ -9,10 +9,10 @@ import (
|
|||||||
"xorm.io/xorm"
|
"xorm.io/xorm"
|
||||||
|
|
||||||
"github.com/cockroachdb/errors"
|
"github.com/cockroachdb/errors"
|
||||||
api "github.com/gogs/go-gogs-client"
|
|
||||||
|
|
||||||
"gogs.io/gogs/internal/errutil"
|
"gogs.io/gogs/internal/errx"
|
||||||
"gogs.io/gogs/internal/lazyregexp"
|
"gogs.io/gogs/internal/lazyregexp"
|
||||||
|
apiv1types "gogs.io/gogs/internal/route/api/v1/types"
|
||||||
"gogs.io/gogs/internal/tool"
|
"gogs.io/gogs/internal/tool"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -62,8 +62,8 @@ type Label struct {
|
|||||||
IsChecked bool `xorm:"-" json:"-" gorm:"-"`
|
IsChecked bool `xorm:"-" json:"-" gorm:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Label) APIFormat() *api.Label {
|
func (l *Label) APIFormat() *apiv1types.IssueLabel {
|
||||||
return &api.Label{
|
return &apiv1types.IssueLabel{
|
||||||
ID: l.ID,
|
ID: l.ID,
|
||||||
Name: l.Name,
|
Name: l.Name,
|
||||||
Color: strings.TrimLeft(l.Color, "#"),
|
Color: strings.TrimLeft(l.Color, "#"),
|
||||||
@@ -101,7 +101,7 @@ func NewLabels(labels ...*Label) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ errutil.NotFound = (*ErrLabelNotExist)(nil)
|
var _ errx.NotFound = (*ErrLabelNotExist)(nil)
|
||||||
|
|
||||||
type ErrLabelNotExist struct {
|
type ErrLabelNotExist struct {
|
||||||
args map[string]any
|
args map[string]any
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ import (
|
|||||||
"gogs.io/gogs/internal/conf"
|
"gogs.io/gogs/internal/conf"
|
||||||
"gogs.io/gogs/internal/email"
|
"gogs.io/gogs/internal/email"
|
||||||
"gogs.io/gogs/internal/markup"
|
"gogs.io/gogs/internal/markup"
|
||||||
"gogs.io/gogs/internal/strutil"
|
"gogs.io/gogs/internal/strx"
|
||||||
"gogs.io/gogs/internal/userutil"
|
"gogs.io/gogs/internal/userx"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (issue *Issue) MailSubject() string {
|
func (issue *Issue) MailSubject() string {
|
||||||
@@ -36,7 +36,7 @@ func (mu mailerUser) Email() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (mu mailerUser) GenerateEmailActivateCode(email string) string {
|
func (mu mailerUser) GenerateEmailActivateCode(email string) string {
|
||||||
return userutil.GenerateActivateCode(
|
return userx.GenerateActivateCode(
|
||||||
mu.user.ID,
|
mu.user.ID,
|
||||||
email,
|
email,
|
||||||
mu.user.Name,
|
mu.user.Name,
|
||||||
@@ -138,7 +138,7 @@ func mailIssueCommentToParticipants(issue *Issue, doer *User, mentions []string)
|
|||||||
for i := range participants {
|
for i := range participants {
|
||||||
if participants[i].ID == doer.ID {
|
if participants[i].ID == doer.ID {
|
||||||
continue
|
continue
|
||||||
} else if strutil.ContainsFold(names, participants[i].Name) {
|
} else if strx.ContainsFold(names, participants[i].Name) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,18 +146,20 @@ func mailIssueCommentToParticipants(issue *Issue, doer *User, mentions []string)
|
|||||||
names = append(names, participants[i].Name)
|
names = append(names, participants[i].Name)
|
||||||
}
|
}
|
||||||
if issue.Assignee != nil && issue.Assignee.ID != doer.ID {
|
if issue.Assignee != nil && issue.Assignee.ID != doer.ID {
|
||||||
if !strutil.ContainsFold(names, issue.Assignee.Name) {
|
if !strx.ContainsFold(names, issue.Assignee.Name) {
|
||||||
tos = append(tos, issue.Assignee.Email)
|
tos = append(tos, issue.Assignee.Email)
|
||||||
names = append(names, issue.Assignee.Name)
|
names = append(names, issue.Assignee.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
email.SendIssueCommentMail(NewMailerIssue(issue), NewMailerRepo(issue.Repo), NewMailerUser(doer), tos)
|
if err = email.SendIssueCommentMail(NewMailerIssue(issue), NewMailerRepo(issue.Repo), NewMailerUser(doer), tos); err != nil {
|
||||||
|
return errors.Wrap(err, "send issue comment mail")
|
||||||
|
}
|
||||||
|
|
||||||
// Mail mentioned people and exclude watchers.
|
// Mail mentioned people and exclude watchers.
|
||||||
names = append(names, doer.Name)
|
names = append(names, doer.Name)
|
||||||
toUsernames := make([]string, 0, len(mentions)) // list of user names.
|
toUsernames := make([]string, 0, len(mentions)) // list of user names.
|
||||||
for i := range mentions {
|
for i := range mentions {
|
||||||
if strutil.ContainsFold(names, mentions[i]) {
|
if strx.ContainsFold(names, mentions[i]) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -168,7 +170,9 @@ func mailIssueCommentToParticipants(issue *Issue, doer *User, mentions []string)
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "get mailable emails by usernames")
|
return errors.Wrap(err, "get mailable emails by usernames")
|
||||||
}
|
}
|
||||||
email.SendIssueMentionMail(NewMailerIssue(issue), NewMailerRepo(issue.Repo), NewMailerUser(doer), tos)
|
if err = email.SendIssueMentionMail(NewMailerIssue(issue), NewMailerRepo(issue.Repo), NewMailerUser(doer), tos); err != nil {
|
||||||
|
return errors.Wrap(err, "send issue mention mail")
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,17 +8,17 @@ import (
|
|||||||
"github.com/cockroachdb/errors"
|
"github.com/cockroachdb/errors"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
|
|
||||||
"gogs.io/gogs/internal/errutil"
|
"gogs.io/gogs/internal/errx"
|
||||||
"gogs.io/gogs/internal/lfsutil"
|
"gogs.io/gogs/internal/lfsx"
|
||||||
)
|
)
|
||||||
|
|
||||||
// LFSObject is the relation between an LFS object and a repository.
|
// LFSObject is the relation between an LFS object and a repository.
|
||||||
type LFSObject struct {
|
type LFSObject struct {
|
||||||
RepoID int64 `gorm:"primaryKey;auto_increment:false"`
|
RepoID int64 `gorm:"primaryKey;auto_increment:false"`
|
||||||
OID lfsutil.OID `gorm:"primaryKey;column:oid"`
|
OID lfsx.OID `gorm:"primaryKey;column:oid"`
|
||||||
Size int64 `gorm:"not null"`
|
Size int64 `gorm:"not null"`
|
||||||
Storage lfsutil.Storage `gorm:"not null"`
|
Storage lfsx.Storage `gorm:"not null"`
|
||||||
CreatedAt time.Time `gorm:"not null"`
|
CreatedAt time.Time `gorm:"not null"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// LFSStore is the storage layer for LFS objects.
|
// LFSStore is the storage layer for LFS objects.
|
||||||
@@ -31,7 +31,7 @@ func newLFSStore(db *gorm.DB) *LFSStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CreateObject creates an LFS object record in database.
|
// CreateObject creates an LFS object record in database.
|
||||||
func (s *LFSStore) CreateObject(ctx context.Context, repoID int64, oid lfsutil.OID, size int64, storage lfsutil.Storage) error {
|
func (s *LFSStore) CreateObject(ctx context.Context, repoID int64, oid lfsx.OID, size int64, storage lfsx.Storage) error {
|
||||||
object := &LFSObject{
|
object := &LFSObject{
|
||||||
RepoID: repoID,
|
RepoID: repoID,
|
||||||
OID: oid,
|
OID: oid,
|
||||||
@@ -42,7 +42,7 @@ func (s *LFSStore) CreateObject(ctx context.Context, repoID int64, oid lfsutil.O
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ErrLFSObjectNotExist struct {
|
type ErrLFSObjectNotExist struct {
|
||||||
args errutil.Args
|
args errx.Args
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsErrLFSObjectNotExist(err error) bool {
|
func IsErrLFSObjectNotExist(err error) bool {
|
||||||
@@ -59,12 +59,12 @@ func (ErrLFSObjectNotExist) NotFound() bool {
|
|||||||
|
|
||||||
// GetObjectByOID returns the LFS object with given OID. It returns
|
// GetObjectByOID returns the LFS object with given OID. It returns
|
||||||
// ErrLFSObjectNotExist when not found.
|
// ErrLFSObjectNotExist when not found.
|
||||||
func (s *LFSStore) GetObjectByOID(ctx context.Context, repoID int64, oid lfsutil.OID) (*LFSObject, error) {
|
func (s *LFSStore) GetObjectByOID(ctx context.Context, repoID int64, oid lfsx.OID) (*LFSObject, error) {
|
||||||
object := new(LFSObject)
|
object := new(LFSObject)
|
||||||
err := s.db.WithContext(ctx).Where("repo_id = ? AND oid = ?", repoID, oid).First(object).Error
|
err := s.db.WithContext(ctx).Where("repo_id = ? AND oid = ?", repoID, oid).First(object).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
return nil, ErrLFSObjectNotExist{args: errutil.Args{"repoID": repoID, "oid": oid}}
|
return nil, ErrLFSObjectNotExist{args: errx.Args{"repoID": repoID, "oid": oid}}
|
||||||
}
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -73,7 +73,7 @@ func (s *LFSStore) GetObjectByOID(ctx context.Context, repoID int64, oid lfsutil
|
|||||||
|
|
||||||
// GetObjectsByOIDs returns LFS objects found within "oids". The returned list
|
// GetObjectsByOIDs returns LFS objects found within "oids". The returned list
|
||||||
// could have fewer elements if some oids were not found.
|
// could have fewer elements if some oids were not found.
|
||||||
func (s *LFSStore) GetObjectsByOIDs(ctx context.Context, repoID int64, oids ...lfsutil.OID) ([]*LFSObject, error) {
|
func (s *LFSStore) GetObjectsByOIDs(ctx context.Context, repoID int64, oids ...lfsx.OID) ([]*LFSObject, error) {
|
||||||
if len(oids) == 0 {
|
if len(oids) == 0 {
|
||||||
return []*LFSObject{}, nil
|
return []*LFSObject{}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ import (
|
|||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"gogs.io/gogs/internal/errutil"
|
"gogs.io/gogs/internal/errx"
|
||||||
"gogs.io/gogs/internal/lfsutil"
|
"gogs.io/gogs/internal/lfsx"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestLFS(t *testing.T) {
|
func TestLFS(t *testing.T) {
|
||||||
@@ -47,8 +47,8 @@ func TestLFS(t *testing.T) {
|
|||||||
func lfsCreateObject(t *testing.T, ctx context.Context, s *LFSStore) {
|
func lfsCreateObject(t *testing.T, ctx context.Context, s *LFSStore) {
|
||||||
// Create first LFS object
|
// Create first LFS object
|
||||||
repoID := int64(1)
|
repoID := int64(1)
|
||||||
oid := lfsutil.OID("ef797c8118f02dfb649607dd5d3f8c7623048c9c063d532cc95c5ed7a898a64f")
|
oid := lfsx.OID("ef797c8118f02dfb649607dd5d3f8c7623048c9c063d532cc95c5ed7a898a64f")
|
||||||
err := s.CreateObject(ctx, repoID, oid, 12, lfsutil.StorageLocal)
|
err := s.CreateObject(ctx, repoID, oid, 12, lfsx.StorageLocal)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// Get it back and check the CreatedAt field
|
// Get it back and check the CreatedAt field
|
||||||
@@ -57,15 +57,15 @@ func lfsCreateObject(t *testing.T, ctx context.Context, s *LFSStore) {
|
|||||||
assert.Equal(t, s.db.NowFunc().Format(time.RFC3339), object.CreatedAt.UTC().Format(time.RFC3339))
|
assert.Equal(t, s.db.NowFunc().Format(time.RFC3339), object.CreatedAt.UTC().Format(time.RFC3339))
|
||||||
|
|
||||||
// Try to create second LFS object with same oid should fail
|
// Try to create second LFS object with same oid should fail
|
||||||
err = s.CreateObject(ctx, repoID, oid, 12, lfsutil.StorageLocal)
|
err = s.CreateObject(ctx, repoID, oid, 12, lfsx.StorageLocal)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func lfsGetObjectByOID(t *testing.T, ctx context.Context, s *LFSStore) {
|
func lfsGetObjectByOID(t *testing.T, ctx context.Context, s *LFSStore) {
|
||||||
// Create a LFS object
|
// Create a LFS object
|
||||||
repoID := int64(1)
|
repoID := int64(1)
|
||||||
oid := lfsutil.OID("ef797c8118f02dfb649607dd5d3f8c7623048c9c063d532cc95c5ed7a898a64f")
|
oid := lfsx.OID("ef797c8118f02dfb649607dd5d3f8c7623048c9c063d532cc95c5ed7a898a64f")
|
||||||
err := s.CreateObject(ctx, repoID, oid, 12, lfsutil.StorageLocal)
|
err := s.CreateObject(ctx, repoID, oid, 12, lfsx.StorageLocal)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// We should be able to get it back
|
// We should be able to get it back
|
||||||
@@ -74,18 +74,18 @@ func lfsGetObjectByOID(t *testing.T, ctx context.Context, s *LFSStore) {
|
|||||||
|
|
||||||
// Try to get a non-existent object
|
// Try to get a non-existent object
|
||||||
_, err = s.GetObjectByOID(ctx, repoID, "bad_oid")
|
_, err = s.GetObjectByOID(ctx, repoID, "bad_oid")
|
||||||
expErr := ErrLFSObjectNotExist{args: errutil.Args{"repoID": repoID, "oid": lfsutil.OID("bad_oid")}}
|
expErr := ErrLFSObjectNotExist{args: errx.Args{"repoID": repoID, "oid": lfsx.OID("bad_oid")}}
|
||||||
assert.Equal(t, expErr, err)
|
assert.Equal(t, expErr, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func lfsGetObjectsByOIDs(t *testing.T, ctx context.Context, s *LFSStore) {
|
func lfsGetObjectsByOIDs(t *testing.T, ctx context.Context, s *LFSStore) {
|
||||||
// Create two LFS objects
|
// Create two LFS objects
|
||||||
repoID := int64(1)
|
repoID := int64(1)
|
||||||
oid1 := lfsutil.OID("ef797c8118f02dfb649607dd5d3f8c7623048c9c063d532cc95c5ed7a898a64f")
|
oid1 := lfsx.OID("ef797c8118f02dfb649607dd5d3f8c7623048c9c063d532cc95c5ed7a898a64f")
|
||||||
oid2 := lfsutil.OID("ef797c8118f02dfb649607dd5d3f8c7623048c9c063d532cc95c5ed7a898a64g")
|
oid2 := lfsx.OID("ef797c8118f02dfb649607dd5d3f8c7623048c9c063d532cc95c5ed7a898a64g")
|
||||||
err := s.CreateObject(ctx, repoID, oid1, 12, lfsutil.StorageLocal)
|
err := s.CreateObject(ctx, repoID, oid1, 12, lfsx.StorageLocal)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
err = s.CreateObject(ctx, repoID, oid2, 12, lfsutil.StorageLocal)
|
err = s.CreateObject(ctx, repoID, oid2, 12, lfsx.StorageLocal)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// We should be able to get them back and ignore non-existent ones
|
// We should be able to get them back and ignore non-existent ones
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ import (
|
|||||||
"gogs.io/gogs/internal/auth/ldap"
|
"gogs.io/gogs/internal/auth/ldap"
|
||||||
"gogs.io/gogs/internal/auth/pam"
|
"gogs.io/gogs/internal/auth/pam"
|
||||||
"gogs.io/gogs/internal/auth/smtp"
|
"gogs.io/gogs/internal/auth/smtp"
|
||||||
"gogs.io/gogs/internal/errutil"
|
"gogs.io/gogs/internal/errx"
|
||||||
"gogs.io/gogs/internal/osutil"
|
"gogs.io/gogs/internal/osx"
|
||||||
)
|
)
|
||||||
|
|
||||||
// loginSourceFilesStore is the in-memory interface for login source files stored on file system.
|
// loginSourceFilesStore is the in-memory interface for login source files stored on file system.
|
||||||
@@ -41,10 +41,10 @@ type loginSourceFiles struct {
|
|||||||
clock func() time.Time
|
clock func() time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ errutil.NotFound = (*ErrLoginSourceNotExist)(nil)
|
var _ errx.NotFound = (*ErrLoginSourceNotExist)(nil)
|
||||||
|
|
||||||
type ErrLoginSourceNotExist struct {
|
type ErrLoginSourceNotExist struct {
|
||||||
args errutil.Args
|
args errx.Args
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsErrLoginSourceNotExist(err error) bool {
|
func IsErrLoginSourceNotExist(err error) bool {
|
||||||
@@ -69,7 +69,7 @@ func (s *loginSourceFiles) GetByID(id int64) (*LoginSource, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, ErrLoginSourceNotExist{args: errutil.Args{"id": id}}
|
return nil, ErrLoginSourceNotExist{args: errx.Args{"id": id}}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *loginSourceFiles) Len() int {
|
func (s *loginSourceFiles) Len() int {
|
||||||
@@ -109,7 +109,7 @@ func (s *loginSourceFiles) Update(source *LoginSource) {
|
|||||||
|
|
||||||
// loadLoginSourceFiles loads login sources from file system.
|
// loadLoginSourceFiles loads login sources from file system.
|
||||||
func loadLoginSourceFiles(authdPath string, clock func() time.Time) (loginSourceFilesStore, error) {
|
func loadLoginSourceFiles(authdPath string, clock func() time.Time) (loginSourceFilesStore, error) {
|
||||||
if !osutil.IsDir(authdPath) {
|
if !osx.IsDir(authdPath) {
|
||||||
return &loginSourceFiles{clock: clock}, nil
|
return &loginSourceFiles{clock: clock}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import (
|
|||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"gogs.io/gogs/internal/errutil"
|
"gogs.io/gogs/internal/errx"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestLoginSourceFiles_GetByID(t *testing.T) {
|
func TestLoginSourceFiles_GetByID(t *testing.T) {
|
||||||
@@ -19,7 +19,7 @@ func TestLoginSourceFiles_GetByID(t *testing.T) {
|
|||||||
|
|
||||||
t.Run("source does not exist", func(t *testing.T) {
|
t.Run("source does not exist", func(t *testing.T) {
|
||||||
_, err := store.GetByID(1)
|
_, err := store.GetByID(1)
|
||||||
wantErr := ErrLoginSourceNotExist{args: errutil.Args{"id": int64(1)}}
|
wantErr := ErrLoginSourceNotExist{args: errx.Args{"id": int64(1)}}
|
||||||
assert.Equal(t, wantErr, err)
|
assert.Equal(t, wantErr, err)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -2,12 +2,12 @@ package database
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/cockroachdb/errors"
|
"github.com/cockroachdb/errors"
|
||||||
jsoniter "github.com/json-iterator/go"
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
|
|
||||||
"gogs.io/gogs/internal/auth"
|
"gogs.io/gogs/internal/auth"
|
||||||
@@ -15,7 +15,7 @@ import (
|
|||||||
"gogs.io/gogs/internal/auth/ldap"
|
"gogs.io/gogs/internal/auth/ldap"
|
||||||
"gogs.io/gogs/internal/auth/pam"
|
"gogs.io/gogs/internal/auth/pam"
|
||||||
"gogs.io/gogs/internal/auth/smtp"
|
"gogs.io/gogs/internal/auth/smtp"
|
||||||
"gogs.io/gogs/internal/errutil"
|
"gogs.io/gogs/internal/errx"
|
||||||
)
|
)
|
||||||
|
|
||||||
// LoginSource represents an external way for authorizing users.
|
// LoginSource represents an external way for authorizing users.
|
||||||
@@ -41,7 +41,8 @@ func (s *LoginSource) BeforeSave(_ *gorm.DB) (err error) {
|
|||||||
if s.Provider == nil {
|
if s.Provider == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
s.Config, err = jsoniter.MarshalToString(s.Provider.Config())
|
data, err := json.Marshal(s.Provider.Config())
|
||||||
|
s.Config = string(data)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,7 +73,7 @@ func (s *LoginSource) AfterFind(_ *gorm.DB) error {
|
|||||||
switch s.Type {
|
switch s.Type {
|
||||||
case auth.LDAP:
|
case auth.LDAP:
|
||||||
var cfg ldap.Config
|
var cfg ldap.Config
|
||||||
err := jsoniter.UnmarshalFromString(s.Config, &cfg)
|
err := json.Unmarshal([]byte(s.Config), &cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -80,7 +81,7 @@ func (s *LoginSource) AfterFind(_ *gorm.DB) error {
|
|||||||
|
|
||||||
case auth.DLDAP:
|
case auth.DLDAP:
|
||||||
var cfg ldap.Config
|
var cfg ldap.Config
|
||||||
err := jsoniter.UnmarshalFromString(s.Config, &cfg)
|
err := json.Unmarshal([]byte(s.Config), &cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -88,7 +89,7 @@ func (s *LoginSource) AfterFind(_ *gorm.DB) error {
|
|||||||
|
|
||||||
case auth.SMTP:
|
case auth.SMTP:
|
||||||
var cfg smtp.Config
|
var cfg smtp.Config
|
||||||
err := jsoniter.UnmarshalFromString(s.Config, &cfg)
|
err := json.Unmarshal([]byte(s.Config), &cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -96,7 +97,7 @@ func (s *LoginSource) AfterFind(_ *gorm.DB) error {
|
|||||||
|
|
||||||
case auth.PAM:
|
case auth.PAM:
|
||||||
var cfg pam.Config
|
var cfg pam.Config
|
||||||
err := jsoniter.UnmarshalFromString(s.Config, &cfg)
|
err := json.Unmarshal([]byte(s.Config), &cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -104,7 +105,7 @@ func (s *LoginSource) AfterFind(_ *gorm.DB) error {
|
|||||||
|
|
||||||
case auth.GitHub:
|
case auth.GitHub:
|
||||||
var cfg github.Config
|
var cfg github.Config
|
||||||
err := jsoniter.UnmarshalFromString(s.Config, &cfg)
|
err := json.Unmarshal([]byte(s.Config), &cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -112,7 +113,7 @@ func (s *LoginSource) AfterFind(_ *gorm.DB) error {
|
|||||||
|
|
||||||
case auth.Mock:
|
case auth.Mock:
|
||||||
var cfg mockProviderConfig
|
var cfg mockProviderConfig
|
||||||
err := jsoniter.UnmarshalFromString(s.Config, &cfg)
|
err := json.Unmarshal([]byte(s.Config), &cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -188,7 +189,7 @@ type CreateLoginSourceOptions struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ErrLoginSourceAlreadyExist struct {
|
type ErrLoginSourceAlreadyExist struct {
|
||||||
args errutil.Args
|
args errx.Args
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsErrLoginSourceAlreadyExist(err error) bool {
|
func IsErrLoginSourceAlreadyExist(err error) bool {
|
||||||
@@ -204,7 +205,7 @@ func (err ErrLoginSourceAlreadyExist) Error() string {
|
|||||||
func (s *LoginSourcesStore) Create(ctx context.Context, opts CreateLoginSourceOptions) (*LoginSource, error) {
|
func (s *LoginSourcesStore) Create(ctx context.Context, opts CreateLoginSourceOptions) (*LoginSource, error) {
|
||||||
err := s.db.WithContext(ctx).Where("name = ?", opts.Name).First(new(LoginSource)).Error
|
err := s.db.WithContext(ctx).Where("name = ?", opts.Name).First(new(LoginSource)).Error
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return nil, ErrLoginSourceAlreadyExist{args: errutil.Args{"name": opts.Name}}
|
return nil, ErrLoginSourceAlreadyExist{args: errx.Args{"name": opts.Name}}
|
||||||
} else if !errors.Is(err, gorm.ErrRecordNotFound) {
|
} else if !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -215,7 +216,8 @@ func (s *LoginSourcesStore) Create(ctx context.Context, opts CreateLoginSourceOp
|
|||||||
IsActived: opts.Activated,
|
IsActived: opts.Activated,
|
||||||
IsDefault: opts.Default,
|
IsDefault: opts.Default,
|
||||||
}
|
}
|
||||||
source.Config, err = jsoniter.MarshalToString(opts.Config)
|
data, err := json.Marshal(opts.Config)
|
||||||
|
source.Config = string(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -230,7 +232,7 @@ func (s *LoginSourcesStore) Count(ctx context.Context) int64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ErrLoginSourceInUse struct {
|
type ErrLoginSourceInUse struct {
|
||||||
args errutil.Args
|
args errx.Args
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsErrLoginSourceInUse(err error) bool {
|
func IsErrLoginSourceInUse(err error) bool {
|
||||||
@@ -249,7 +251,7 @@ func (s *LoginSourcesStore) DeleteByID(ctx context.Context, id int64) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
} else if count > 0 {
|
} else if count > 0 {
|
||||||
return ErrLoginSourceInUse{args: errutil.Args{"id": id}}
|
return ErrLoginSourceInUse{args: errx.Args{"id": id}}
|
||||||
}
|
}
|
||||||
|
|
||||||
return s.db.WithContext(ctx).Where("id = ?", id).Delete(new(LoginSource)).Error
|
return s.db.WithContext(ctx).Where("id = ?", id).Delete(new(LoginSource)).Error
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import (
|
|||||||
"gogs.io/gogs/internal/auth/ldap"
|
"gogs.io/gogs/internal/auth/ldap"
|
||||||
"gogs.io/gogs/internal/auth/pam"
|
"gogs.io/gogs/internal/auth/pam"
|
||||||
"gogs.io/gogs/internal/auth/smtp"
|
"gogs.io/gogs/internal/auth/smtp"
|
||||||
"gogs.io/gogs/internal/errutil"
|
"gogs.io/gogs/internal/errx"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestLoginSource_BeforeSave(t *testing.T) {
|
func TestLoginSource_BeforeSave(t *testing.T) {
|
||||||
@@ -211,7 +211,7 @@ func loginSourcesCreate(t *testing.T, ctx context.Context, s *LoginSourcesStore)
|
|||||||
|
|
||||||
// Try to create second login source with same name should fail.
|
// Try to create second login source with same name should fail.
|
||||||
_, err = s.Create(ctx, CreateLoginSourceOptions{Name: source.Name})
|
_, err = s.Create(ctx, CreateLoginSourceOptions{Name: source.Name})
|
||||||
wantErr := ErrLoginSourceAlreadyExist{args: errutil.Args{"name": source.Name}}
|
wantErr := ErrLoginSourceAlreadyExist{args: errx.Args{"name": source.Name}}
|
||||||
assert.Equal(t, wantErr, err)
|
assert.Equal(t, wantErr, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -270,13 +270,13 @@ func loginSourcesDeleteByID(t *testing.T, ctx context.Context, s *LoginSourcesSt
|
|||||||
|
|
||||||
// Delete the login source will result in error
|
// Delete the login source will result in error
|
||||||
err = s.DeleteByID(ctx, source.ID)
|
err = s.DeleteByID(ctx, source.ID)
|
||||||
wantErr := ErrLoginSourceInUse{args: errutil.Args{"id": source.ID}}
|
wantErr := ErrLoginSourceInUse{args: errx.Args{"id": source.ID}}
|
||||||
assert.Equal(t, wantErr, err)
|
assert.Equal(t, wantErr, err)
|
||||||
})
|
})
|
||||||
|
|
||||||
mock := NewMockLoginSourceFilesStore()
|
mock := NewMockLoginSourceFilesStore()
|
||||||
mock.GetByIDFunc.SetDefaultHook(func(id int64) (*LoginSource, error) {
|
mock.GetByIDFunc.SetDefaultHook(func(id int64) (*LoginSource, error) {
|
||||||
return nil, ErrLoginSourceNotExist{args: errutil.Args{"id": id}}
|
return nil, ErrLoginSourceNotExist{args: errx.Args{"id": id}}
|
||||||
})
|
})
|
||||||
setMockLoginSourceFilesStore(t, s, mock)
|
setMockLoginSourceFilesStore(t, s, mock)
|
||||||
|
|
||||||
@@ -308,7 +308,7 @@ func loginSourcesDeleteByID(t *testing.T, ctx context.Context, s *LoginSourcesSt
|
|||||||
|
|
||||||
// We should get token not found error
|
// We should get token not found error
|
||||||
_, err = s.GetByID(ctx, source.ID)
|
_, err = s.GetByID(ctx, source.ID)
|
||||||
wantErr := ErrLoginSourceNotExist{args: errutil.Args{"id": source.ID}}
|
wantErr := ErrLoginSourceNotExist{args: errx.Args{"id": source.ID}}
|
||||||
assert.Equal(t, wantErr, err)
|
assert.Equal(t, wantErr, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -316,7 +316,7 @@ func loginSourcesGetByID(t *testing.T, ctx context.Context, s *LoginSourcesStore
|
|||||||
mock := NewMockLoginSourceFilesStore()
|
mock := NewMockLoginSourceFilesStore()
|
||||||
mock.GetByIDFunc.SetDefaultHook(func(id int64) (*LoginSource, error) {
|
mock.GetByIDFunc.SetDefaultHook(func(id int64) (*LoginSource, error) {
|
||||||
if id != 101 {
|
if id != 101 {
|
||||||
return nil, ErrLoginSourceNotExist{args: errutil.Args{"id": id}}
|
return nil, ErrLoginSourceNotExist{args: errx.Args{"id": id}}
|
||||||
}
|
}
|
||||||
return &LoginSource{ID: id}, nil
|
return &LoginSource{ID: id}, nil
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import (
|
|||||||
|
|
||||||
"gogs.io/gogs/internal/conf"
|
"gogs.io/gogs/internal/conf"
|
||||||
"gogs.io/gogs/internal/dbtest"
|
"gogs.io/gogs/internal/dbtest"
|
||||||
"gogs.io/gogs/internal/testutil"
|
"gogs.io/gogs/internal/testx"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
func TestMain(m *testing.M) {
|
||||||
@@ -22,7 +22,7 @@ func TestMain(m *testing.M) {
|
|||||||
if !testing.Verbose() {
|
if !testing.Verbose() {
|
||||||
// Remove the primary logger and register a noop logger.
|
// Remove the primary logger and register a noop logger.
|
||||||
log.Remove(log.DefaultConsoleName)
|
log.Remove(log.DefaultConsoleName)
|
||||||
err := log.New("noop", testutil.InitNoopLogger)
|
err := log.New("noop", testx.InitNoopLogger)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import (
|
|||||||
"gorm.io/gorm/logger"
|
"gorm.io/gorm/logger"
|
||||||
log "unknwon.dev/clog/v2"
|
log "unknwon.dev/clog/v2"
|
||||||
|
|
||||||
"gogs.io/gogs/internal/testutil"
|
"gogs.io/gogs/internal/testx"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
func TestMain(m *testing.M) {
|
||||||
@@ -19,7 +19,7 @@ func TestMain(m *testing.M) {
|
|||||||
if !testing.Verbose() {
|
if !testing.Verbose() {
|
||||||
// Remove the primary logger and register a noop logger.
|
// Remove the primary logger and register a noop logger.
|
||||||
log.Remove(log.DefaultConsoleName)
|
log.Remove(log.DefaultConsoleName)
|
||||||
err := log.New("noop", testutil.InitNoopLogger)
|
err := log.New("noop", testx.InitNoopLogger)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
|
|||||||
@@ -102,11 +102,11 @@ You can migrate your older database using a previous release, then you can upgra
|
|||||||
Please save following instructions to somewhere and start working:
|
Please save following instructions to somewhere and start working:
|
||||||
|
|
||||||
- If you were using below 0.6.0 (e.g. 0.5.x), download last supported archive from following link:
|
- If you were using below 0.6.0 (e.g. 0.5.x), download last supported archive from following link:
|
||||||
https://gogs.io/gogs/releases/tag/v0.7.33
|
https://github.com/gogs/gogs/releases/tag/v0.7.33
|
||||||
- If you were using below 0.7.0 (e.g. 0.6.x), download last supported archive from following link:
|
- If you were using below 0.7.0 (e.g. 0.6.x), download last supported archive from following link:
|
||||||
https://gogs.io/gogs/releases/tag/v0.9.141
|
https://github.com/gogs/gogs/releases/tag/v0.9.141
|
||||||
- If you were using below 0.11.55 (e.g. 0.9.141), download last supported archive from following link:
|
- If you were using below 0.11.55 (e.g. 0.9.141), download last supported archive from following link:
|
||||||
https://gogs.io/gogs/releases/tag/v0.12.0
|
https://github.com/gogs/gogs/releases/tag/v0.12.0
|
||||||
|
|
||||||
Once finished downloading:
|
Once finished downloading:
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"github.com/cockroachdb/errors"
|
"github.com/cockroachdb/errors"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
|
|
||||||
"gogs.io/gogs/internal/cryptoutil"
|
"gogs.io/gogs/internal/cryptox"
|
||||||
)
|
)
|
||||||
|
|
||||||
func migrateAccessTokenToSHA256(db *gorm.DB) error {
|
func migrateAccessTokenToSHA256(db *gorm.DB) error {
|
||||||
@@ -33,7 +33,7 @@ func migrateAccessTokenToSHA256(db *gorm.DB) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, t := range accessTokens {
|
for _, t := range accessTokens {
|
||||||
sha256 := cryptoutil.SHA256(t.Sha1)
|
sha256 := cryptox.SHA256(t.Sha1)
|
||||||
err = tx.Model(&accessToken{}).Where("id = ?", t.ID).Update("sha256", sha256).Error
|
err = tx.Model(&accessToken{}).Where("id = ?", t.ID).Update("sha256", sha256).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "update")
|
return errors.Wrap(err, "update")
|
||||||
|
|||||||
@@ -8,10 +8,10 @@ import (
|
|||||||
"xorm.io/xorm"
|
"xorm.io/xorm"
|
||||||
|
|
||||||
"github.com/cockroachdb/errors"
|
"github.com/cockroachdb/errors"
|
||||||
api "github.com/gogs/go-gogs-client"
|
|
||||||
|
|
||||||
"gogs.io/gogs/internal/conf"
|
"gogs.io/gogs/internal/conf"
|
||||||
"gogs.io/gogs/internal/errutil"
|
"gogs.io/gogs/internal/errx"
|
||||||
|
apiv1types "gogs.io/gogs/internal/route/api/v1/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Milestone represents a milestone of repository.
|
// Milestone represents a milestone of repository.
|
||||||
@@ -72,19 +72,19 @@ func (m *Milestone) AfterSet(colName string, _ xorm.Cell) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// State returns string representation of milestone status.
|
// State returns string representation of milestone status.
|
||||||
func (m *Milestone) State() api.StateType {
|
func (m *Milestone) State() apiv1types.IssueStateType {
|
||||||
if m.IsClosed {
|
if m.IsClosed {
|
||||||
return api.STATE_CLOSED
|
return apiv1types.IssueStateClosed
|
||||||
}
|
}
|
||||||
return api.STATE_OPEN
|
return apiv1types.IssueStateOpen
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Milestone) ChangeStatus(isClosed bool) error {
|
func (m *Milestone) ChangeStatus(isClosed bool) error {
|
||||||
return ChangeMilestoneStatus(m, isClosed)
|
return ChangeMilestoneStatus(m, isClosed)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Milestone) APIFormat() *api.Milestone {
|
func (m *Milestone) APIFormat() *apiv1types.IssueMilestone {
|
||||||
apiMilestone := &api.Milestone{
|
apiMilestone := &apiv1types.IssueMilestone{
|
||||||
ID: m.ID,
|
ID: m.ID,
|
||||||
State: m.State(),
|
State: m.State(),
|
||||||
Title: m.Name,
|
Title: m.Name,
|
||||||
@@ -128,7 +128,7 @@ func NewMilestone(m *Milestone) (err error) {
|
|||||||
return sess.Commit()
|
return sess.Commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ errutil.NotFound = (*ErrMilestoneNotExist)(nil)
|
var _ errx.NotFound = (*ErrMilestoneNotExist)(nil)
|
||||||
|
|
||||||
type ErrMilestoneNotExist struct {
|
type ErrMilestoneNotExist struct {
|
||||||
args map[string]any
|
args map[string]any
|
||||||
@@ -343,11 +343,11 @@ func ChangeMilestoneAssign(doer *User, issue *Issue, oldMilestoneID int64) (err
|
|||||||
return errors.Newf("commit: %v", err)
|
return errors.Newf("commit: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var hookAction api.HookIssueAction
|
var hookAction apiv1types.WebhookIssueAction
|
||||||
if issue.MilestoneID > 0 {
|
if issue.MilestoneID > 0 {
|
||||||
hookAction = api.HOOK_ISSUE_MILESTONED
|
hookAction = apiv1types.WebhookIssueMilestoned
|
||||||
} else {
|
} else {
|
||||||
hookAction = api.HOOK_ISSUE_DEMILESTONED
|
hookAction = apiv1types.WebhookIssueDemilestoned
|
||||||
}
|
}
|
||||||
|
|
||||||
if issue.IsPull {
|
if issue.IsPull {
|
||||||
@@ -356,7 +356,7 @@ func ChangeMilestoneAssign(doer *User, issue *Issue, oldMilestoneID int64) (err
|
|||||||
log.Error("LoadIssue: %v", err)
|
log.Error("LoadIssue: %v", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = PrepareWebhooks(issue.Repo, HookEventTypePullRequest, &api.PullRequestPayload{
|
err = PrepareWebhooks(issue.Repo, HookEventTypePullRequest, &apiv1types.WebhookPullRequestPayload{
|
||||||
Action: hookAction,
|
Action: hookAction,
|
||||||
Index: issue.Index,
|
Index: issue.Index,
|
||||||
PullRequest: issue.PullRequest.APIFormat(),
|
PullRequest: issue.PullRequest.APIFormat(),
|
||||||
@@ -364,7 +364,7 @@ func ChangeMilestoneAssign(doer *User, issue *Issue, oldMilestoneID int64) (err
|
|||||||
Sender: doer.APIFormat(),
|
Sender: doer.APIFormat(),
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
err = PrepareWebhooks(issue.Repo, HookEventTypeIssues, &api.IssuesPayload{
|
err = PrepareWebhooks(issue.Repo, HookEventTypeIssues, &apiv1types.WebhookIssuesPayload{
|
||||||
Action: hookAction,
|
Action: hookAction,
|
||||||
Index: issue.Index,
|
Index: issue.Index,
|
||||||
Issue: issue.APIFormat(),
|
Issue: issue.APIFormat(),
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import (
|
|||||||
|
|
||||||
"gogs.io/gogs/internal/conf"
|
"gogs.io/gogs/internal/conf"
|
||||||
"gogs.io/gogs/internal/database/migrations"
|
"gogs.io/gogs/internal/database/migrations"
|
||||||
"gogs.io/gogs/internal/dbutil"
|
"gogs.io/gogs/internal/dbx"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Engine represents a XORM engine or session.
|
// Engine represents a XORM engine or session.
|
||||||
@@ -89,16 +89,11 @@ func getEngine() (*xorm.Engine, error) {
|
|||||||
|
|
||||||
case "postgres":
|
case "postgres":
|
||||||
conf.UsePostgreSQL = true
|
conf.UsePostgreSQL = true
|
||||||
host, port := dbutil.ParsePostgreSQLHostPort(conf.Database.Host)
|
host, port := dbx.ParsePostgreSQLHostPort(conf.Database.Host)
|
||||||
connStr = fmt.Sprintf("user='%s' password='%s' host='%s' port='%s' dbname='%s' sslmode='%s' search_path='%s'",
|
connStr = fmt.Sprintf("user='%s' password='%s' host='%s' port='%s' dbname='%s' sslmode='%s' search_path='%s'",
|
||||||
conf.Database.User, conf.Database.Password, host, port, conf.Database.Name, conf.Database.SSLMode, conf.Database.Schema)
|
conf.Database.User, conf.Database.Password, host, port, conf.Database.Name, conf.Database.SSLMode, conf.Database.Schema)
|
||||||
driver = "pgx"
|
driver = "pgx"
|
||||||
|
|
||||||
case "mssql":
|
|
||||||
conf.UseMSSQL = true
|
|
||||||
host, port := dbutil.ParseMSSQLHostPort(conf.Database.Host)
|
|
||||||
connStr = fmt.Sprintf("server=%s; port=%s; database=%s; user id=%s; password=%s;", host, port, conf.Database.Name, conf.Database.User, conf.Database.Password)
|
|
||||||
|
|
||||||
case "sqlite3":
|
case "sqlite3":
|
||||||
if err := os.MkdirAll(path.Dir(conf.Database.Path), os.ModePerm); err != nil {
|
if err := os.MkdirAll(path.Dir(conf.Database.Path), os.ModePerm); err != nil {
|
||||||
return nil, errors.Newf("create directories: %v", err)
|
return nil, errors.Newf("create directories: %v", err)
|
||||||
@@ -171,7 +166,7 @@ func SetEngine() (*gorm.DB, error) {
|
|||||||
|
|
||||||
var gormLogger logger.Writer
|
var gormLogger logger.Writer
|
||||||
if conf.HookMode {
|
if conf.HookMode {
|
||||||
gormLogger = &dbutil.Logger{Writer: fileWriter}
|
gormLogger = &dbx.Logger{Writer: fileWriter}
|
||||||
} else {
|
} else {
|
||||||
gormLogger, err = newLogWriter()
|
gormLogger, err = newLogWriter()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -9,9 +9,9 @@ import (
|
|||||||
"xorm.io/builder"
|
"xorm.io/builder"
|
||||||
"xorm.io/xorm"
|
"xorm.io/xorm"
|
||||||
|
|
||||||
"gogs.io/gogs/internal/errutil"
|
"gogs.io/gogs/internal/errx"
|
||||||
"gogs.io/gogs/internal/repoutil"
|
"gogs.io/gogs/internal/repox"
|
||||||
"gogs.io/gogs/internal/userutil"
|
"gogs.io/gogs/internal/userx"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ErrOrgNotExist = errors.New("Organization does not exist")
|
var ErrOrgNotExist = errors.New("Organization does not exist")
|
||||||
@@ -103,17 +103,17 @@ func CreateOrganization(org, owner *User) (err error) {
|
|||||||
|
|
||||||
if Handle.Users().IsUsernameUsed(context.TODO(), org.Name, 0) {
|
if Handle.Users().IsUsernameUsed(context.TODO(), org.Name, 0) {
|
||||||
return ErrUserAlreadyExist{
|
return ErrUserAlreadyExist{
|
||||||
args: errutil.Args{
|
args: errx.Args{
|
||||||
"name": org.Name,
|
"name": org.Name,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
org.LowerName = strings.ToLower(org.Name)
|
org.LowerName = strings.ToLower(org.Name)
|
||||||
if org.Rands, err = userutil.RandomSalt(); err != nil {
|
if org.Rands, err = userx.RandomSalt(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if org.Salt, err = userutil.RandomSalt(); err != nil {
|
if org.Salt, err = userx.RandomSalt(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
org.UseCustomAvatar = true
|
org.UseCustomAvatar = true
|
||||||
@@ -130,7 +130,7 @@ func CreateOrganization(org, owner *User) (err error) {
|
|||||||
if _, err = sess.Insert(org); err != nil {
|
if _, err = sess.Insert(org); err != nil {
|
||||||
return errors.Newf("insert organization: %v", err)
|
return errors.Newf("insert organization: %v", err)
|
||||||
}
|
}
|
||||||
_ = userutil.GenerateRandomAvatar(org.ID, org.Name, org.Email)
|
_ = userx.GenerateRandomAvatar(org.ID, org.Name, org.Email)
|
||||||
|
|
||||||
// Add initial creator to organization and owner team.
|
// Add initial creator to organization and owner team.
|
||||||
if _, err = sess.Insert(&OrgUser{
|
if _, err = sess.Insert(&OrgUser{
|
||||||
@@ -162,7 +162,7 @@ func CreateOrganization(org, owner *User) (err error) {
|
|||||||
return errors.Newf("insert team-user relation: %v", err)
|
return errors.Newf("insert team-user relation: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = os.MkdirAll(repoutil.UserPath(org.Name), os.ModePerm); err != nil {
|
if err = os.MkdirAll(repox.UserPath(org.Name), os.ModePerm); err != nil {
|
||||||
return errors.Newf("create directory: %v", err)
|
return errors.Newf("create directory: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
"github.com/cockroachdb/errors"
|
"github.com/cockroachdb/errors"
|
||||||
"xorm.io/xorm"
|
"xorm.io/xorm"
|
||||||
|
|
||||||
"gogs.io/gogs/internal/errutil"
|
"gogs.io/gogs/internal/errx"
|
||||||
)
|
)
|
||||||
|
|
||||||
const ownerTeamName = "Owners"
|
const ownerTeamName = "Owners"
|
||||||
@@ -30,7 +30,7 @@ type Team struct {
|
|||||||
func (t *Team) AfterSet(colName string, _ xorm.Cell) {
|
func (t *Team) AfterSet(colName string, _ xorm.Cell) {
|
||||||
switch colName {
|
switch colName {
|
||||||
case "num_repos":
|
case "num_repos":
|
||||||
// LEGACY [1.0]: this is backward compatibility bug fix for https://gogs.io/gogs/issues/3671
|
// LEGACY [1.0]: this is backward compatibility bug fix for https://github.com/gogs/gogs/issues/3671
|
||||||
if t.NumRepos < 0 {
|
if t.NumRepos < 0 {
|
||||||
t.NumRepos = 0
|
t.NumRepos = 0
|
||||||
}
|
}
|
||||||
@@ -297,7 +297,7 @@ func NewTeam(t *Team) error {
|
|||||||
return sess.Commit()
|
return sess.Commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ errutil.NotFound = (*ErrTeamNotExist)(nil)
|
var _ errx.NotFound = (*ErrTeamNotExist)(nil)
|
||||||
|
|
||||||
type ErrTeamNotExist struct {
|
type ErrTeamNotExist struct {
|
||||||
args map[string]any
|
args map[string]any
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import (
|
|||||||
"github.com/cockroachdb/errors"
|
"github.com/cockroachdb/errors"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
|
|
||||||
"gogs.io/gogs/internal/dbutil"
|
"gogs.io/gogs/internal/dbx"
|
||||||
)
|
)
|
||||||
|
|
||||||
// OrganizationsStore is the storage layer for organizations.
|
// OrganizationsStore is the storage layer for organizations.
|
||||||
@@ -42,9 +42,9 @@ func (s *OrganizationsStore) List(ctx context.Context, opts ListOrgsOptions) ([]
|
|||||||
ORDER BY org.id ASC
|
ORDER BY org.id ASC
|
||||||
*/
|
*/
|
||||||
tx := s.db.WithContext(ctx).
|
tx := s.db.WithContext(ctx).
|
||||||
Joins(dbutil.Quote("JOIN org_user ON org_user.org_id = %s.id", "user")).
|
Joins(dbx.Quote("JOIN org_user ON org_user.org_id = %s.id", "user")).
|
||||||
Where("org_user.uid = ?", opts.MemberID).
|
Where("org_user.uid = ?", opts.MemberID).
|
||||||
Order(dbutil.Quote("%s.id ASC", "user"))
|
Order(dbx.Quote("%s.id ASC", "user"))
|
||||||
if !opts.IncludePrivateMembers {
|
if !opts.IncludePrivateMembers {
|
||||||
tx = tx.Where("org_user.is_public = ?", true)
|
tx = tx.Where("org_user.is_public = ?", true)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import (
|
|||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"gogs.io/gogs/internal/dbutil"
|
"gogs.io/gogs/internal/dbx"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestOrgs(t *testing.T) {
|
func TestOrgs(t *testing.T) {
|
||||||
@@ -55,7 +55,7 @@ func orgsList(t *testing.T, ctx context.Context, s *OrganizationsStore) {
|
|||||||
org2, err := usersStore.Create(ctx, "org2", "org2@example.com", CreateUserOptions{})
|
org2, err := usersStore.Create(ctx, "org2", "org2@example.com", CreateUserOptions{})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
err = s.db.Exec(
|
err = s.db.Exec(
|
||||||
dbutil.Quote("UPDATE %s SET type = ? WHERE id IN (?, ?)", "user"),
|
dbx.Quote("UPDATE %s SET type = ? WHERE id IN (?, ?)", "user"),
|
||||||
UserTypeOrganization, org1.ID, org2.ID,
|
UserTypeOrganization, org1.ID, org2.ID,
|
||||||
).Error
|
).Error
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@@ -120,7 +120,7 @@ func organizationsSearchByName(t *testing.T, ctx context.Context, s *Organizatio
|
|||||||
org2, err := usersStore.Create(ctx, "org2", "org2@example.com", CreateUserOptions{FullName: "Acme Corp 2"})
|
org2, err := usersStore.Create(ctx, "org2", "org2@example.com", CreateUserOptions{FullName: "Acme Corp 2"})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
err = s.db.Exec(
|
err = s.db.Exec(
|
||||||
dbutil.Quote("UPDATE %s SET type = ? WHERE id IN (?, ?)", "user"),
|
dbx.Quote("UPDATE %s SET type = ? WHERE id IN (?, ?)", "user"),
|
||||||
UserTypeOrganization, org1.ID, org2.ID,
|
UserTypeOrganization, org1.ID, org2.ID,
|
||||||
).Error
|
).Error
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
|
|
||||||
"gogs.io/gogs/internal/conf"
|
"gogs.io/gogs/internal/conf"
|
||||||
"gogs.io/gogs/internal/osutil"
|
"gogs.io/gogs/internal/osx"
|
||||||
)
|
)
|
||||||
|
|
||||||
// PublicKeysStore is the storage layer for public keys.
|
// PublicKeysStore is the storage layer for public keys.
|
||||||
@@ -73,7 +73,7 @@ func (s *PublicKeysStore) RewriteAuthorizedKeys() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "close temporary file")
|
return errors.Wrap(err, "close temporary file")
|
||||||
}
|
}
|
||||||
if osutil.Exist(fpath) {
|
if osx.Exist(fpath) {
|
||||||
err = os.Remove(fpath)
|
err = os.Remove(fpath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "remove")
|
return errors.Wrap(err, "remove")
|
||||||
|
|||||||
@@ -13,12 +13,12 @@ import (
|
|||||||
"xorm.io/xorm"
|
"xorm.io/xorm"
|
||||||
|
|
||||||
"github.com/gogs/git-module"
|
"github.com/gogs/git-module"
|
||||||
api "github.com/gogs/go-gogs-client"
|
|
||||||
|
|
||||||
"gogs.io/gogs/internal/conf"
|
"gogs.io/gogs/internal/conf"
|
||||||
"gogs.io/gogs/internal/errutil"
|
"gogs.io/gogs/internal/errx"
|
||||||
"gogs.io/gogs/internal/osutil"
|
"gogs.io/gogs/internal/osx"
|
||||||
"gogs.io/gogs/internal/process"
|
"gogs.io/gogs/internal/process"
|
||||||
|
apiv1types "gogs.io/gogs/internal/route/api/v1/types"
|
||||||
"gogs.io/gogs/internal/sync"
|
"gogs.io/gogs/internal/sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -127,11 +127,11 @@ func (pr *PullRequest) LoadIssue() (err error) {
|
|||||||
// This method assumes following fields have been assigned with valid values:
|
// This method assumes following fields have been assigned with valid values:
|
||||||
// Required - Issue, BaseRepo
|
// Required - Issue, BaseRepo
|
||||||
// Optional - HeadRepo, Merger
|
// Optional - HeadRepo, Merger
|
||||||
func (pr *PullRequest) APIFormat() *api.PullRequest {
|
func (pr *PullRequest) APIFormat() *apiv1types.PullRequest {
|
||||||
// In case of head repo has been deleted.
|
// In case of head repo has been deleted.
|
||||||
var apiHeadRepo *api.Repository
|
var apiHeadRepo *apiv1types.Repository
|
||||||
if pr.HeadRepo == nil {
|
if pr.HeadRepo == nil {
|
||||||
apiHeadRepo = &api.Repository{
|
apiHeadRepo = &apiv1types.Repository{
|
||||||
Name: "deleted",
|
Name: "deleted",
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -139,7 +139,7 @@ func (pr *PullRequest) APIFormat() *api.PullRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
apiIssue := pr.Issue.APIFormat()
|
apiIssue := pr.Issue.APIFormat()
|
||||||
apiPullRequest := &api.PullRequest{
|
apiPullRequest := &apiv1types.PullRequest{
|
||||||
ID: pr.ID,
|
ID: pr.ID,
|
||||||
Index: pr.Index,
|
Index: pr.Index,
|
||||||
Poster: apiIssue.Poster,
|
Poster: apiIssue.Poster,
|
||||||
@@ -341,8 +341,8 @@ func (pr *PullRequest) Merge(doer *User, baseGitRepo *git.Repository, mergeStyle
|
|||||||
log.Error("LoadAttributes: %v", err)
|
log.Error("LoadAttributes: %v", err)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if err = PrepareWebhooks(pr.Issue.Repo, HookEventTypePullRequest, &api.PullRequestPayload{
|
if err = PrepareWebhooks(pr.Issue.Repo, HookEventTypePullRequest, &apiv1types.WebhookPullRequestPayload{
|
||||||
Action: api.HOOK_ISSUE_CLOSED,
|
Action: apiv1types.WebhookIssueClosed,
|
||||||
Index: pr.Index,
|
Index: pr.Index,
|
||||||
PullRequest: pr.APIFormat(),
|
PullRequest: pr.APIFormat(),
|
||||||
Repository: pr.Issue.Repo.APIFormatLegacy(nil),
|
Repository: pr.Issue.Repo.APIFormatLegacy(nil),
|
||||||
@@ -376,7 +376,7 @@ func (pr *PullRequest) Merge(doer *User, baseGitRepo *git.Repository, mergeStyle
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
p := &api.PushPayload{
|
p := &apiv1types.WebhookPushPayload{
|
||||||
Ref: git.RefsHeads + pr.BaseBranch,
|
Ref: git.RefsHeads + pr.BaseBranch,
|
||||||
Before: pr.MergeBase,
|
Before: pr.MergeBase,
|
||||||
After: mergeCommit.ID.String(),
|
After: mergeCommit.ID.String(),
|
||||||
@@ -409,7 +409,7 @@ func (pr *PullRequest) testPatch() (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Fast fail if patch does not exist, this assumes data is corrupted.
|
// Fast fail if patch does not exist, this assumes data is corrupted.
|
||||||
if !osutil.IsFile(patchPath) {
|
if !osx.IsFile(patchPath) {
|
||||||
log.Trace("PullRequest[%d].testPatch: ignored corrupted data", pr.ID)
|
log.Trace("PullRequest[%d].testPatch: ignored corrupted data", pr.ID)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -500,8 +500,8 @@ func NewPullRequest(repo *Repository, pull *Issue, labelIDs []int64, uuids []str
|
|||||||
|
|
||||||
pr.Issue = pull
|
pr.Issue = pull
|
||||||
pull.PullRequest = pr
|
pull.PullRequest = pr
|
||||||
if err = PrepareWebhooks(repo, HookEventTypePullRequest, &api.PullRequestPayload{
|
if err = PrepareWebhooks(repo, HookEventTypePullRequest, &apiv1types.WebhookPullRequestPayload{
|
||||||
Action: api.HOOK_ISSUE_OPENED,
|
Action: apiv1types.WebhookIssueOpened,
|
||||||
Index: pull.Index,
|
Index: pull.Index,
|
||||||
PullRequest: pr.APIFormat(),
|
PullRequest: pr.APIFormat(),
|
||||||
Repository: repo.APIFormatLegacy(nil),
|
Repository: repo.APIFormatLegacy(nil),
|
||||||
@@ -552,7 +552,7 @@ func GetUnmergedPullRequestsByBaseInfo(repoID int64, branch string) ([]*PullRequ
|
|||||||
Join("INNER", "issue", "issue.id=pull_request.issue_id").Find(&prs)
|
Join("INNER", "issue", "issue.id=pull_request.issue_id").Find(&prs)
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ errutil.NotFound = (*ErrPullRequestNotExist)(nil)
|
var _ errx.NotFound = (*ErrPullRequestNotExist)(nil)
|
||||||
|
|
||||||
type ErrPullRequestNotExist struct {
|
type ErrPullRequestNotExist struct {
|
||||||
args map[string]any
|
args map[string]any
|
||||||
@@ -684,7 +684,7 @@ func (pr *PullRequest) PushToBaseRepo() (err error) {
|
|||||||
|
|
||||||
headRefspec := fmt.Sprintf("refs/pull/%d/head", pr.Index)
|
headRefspec := fmt.Sprintf("refs/pull/%d/head", pr.Index)
|
||||||
headFile := filepath.Join(pr.BaseRepo.RepoPath(), headRefspec)
|
headFile := filepath.Join(pr.BaseRepo.RepoPath(), headRefspec)
|
||||||
if osutil.Exist(headFile) {
|
if osx.Exist(headFile) {
|
||||||
err = os.Remove(headFile)
|
err = os.Remove(headFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Newf("remove head file [repo_id: %d]: %v", pr.BaseRepoID, err)
|
return errors.Newf("remove head file [repo_id: %d]: %v", pr.BaseRepoID, err)
|
||||||
@@ -792,8 +792,8 @@ func AddTestPullRequestTask(doer *User, repoID int64, branch string, isSync bool
|
|||||||
log.Error("LoadAttributes: %v", err)
|
log.Error("LoadAttributes: %v", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if err = PrepareWebhooks(pr.Issue.Repo, HookEventTypePullRequest, &api.PullRequestPayload{
|
if err = PrepareWebhooks(pr.Issue.Repo, HookEventTypePullRequest, &apiv1types.WebhookPullRequestPayload{
|
||||||
Action: api.HOOK_ISSUE_SYNCHRONIZED,
|
Action: apiv1types.WebhookIssueSynchronized,
|
||||||
Index: pr.Issue.Index,
|
Index: pr.Issue.Index,
|
||||||
PullRequest: pr.Issue.PullRequest.APIFormat(),
|
PullRequest: pr.Issue.PullRequest.APIFormat(),
|
||||||
Repository: pr.Issue.Repo.APIFormatLegacy(nil),
|
Repository: pr.Issue.Repo.APIFormatLegacy(nil),
|
||||||
|
|||||||
@@ -11,10 +11,9 @@ import (
|
|||||||
|
|
||||||
"github.com/cockroachdb/errors"
|
"github.com/cockroachdb/errors"
|
||||||
"github.com/gogs/git-module"
|
"github.com/gogs/git-module"
|
||||||
api "github.com/gogs/go-gogs-client"
|
|
||||||
|
|
||||||
"gogs.io/gogs/internal/errutil"
|
"gogs.io/gogs/internal/errx"
|
||||||
"gogs.io/gogs/internal/process"
|
apiv1types "gogs.io/gogs/internal/route/api/v1/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Release represents a release of repository.
|
// Release represents a release of repository.
|
||||||
@@ -90,8 +89,8 @@ func (r *Release) LoadAttributes() error {
|
|||||||
|
|
||||||
// This method assumes some fields assigned with values:
|
// This method assumes some fields assigned with values:
|
||||||
// Required - Publisher
|
// Required - Publisher
|
||||||
func (r *Release) APIFormat() *api.Release {
|
func (r *Release) APIFormat() *apiv1types.RepositoryRelease {
|
||||||
return &api.Release{
|
return &apiv1types.RepositoryRelease{
|
||||||
ID: r.ID,
|
ID: r.ID,
|
||||||
TagName: r.TagName,
|
TagName: r.TagName,
|
||||||
TargetCommitish: r.Target,
|
TargetCommitish: r.Target,
|
||||||
@@ -147,8 +146,8 @@ func createTag(gitRepo *git.Repository, r *Release) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *Release) preparePublishWebhooks() {
|
func (r *Release) preparePublishWebhooks() {
|
||||||
if err := PrepareWebhooks(r.Repo, HookEventTypeRelease, &api.ReleasePayload{
|
if err := PrepareWebhooks(r.Repo, HookEventTypeRelease, &apiv1types.WebhookReleasePayload{
|
||||||
Action: api.HOOK_RELEASE_PUBLISHED,
|
Action: apiv1types.WebhookReleasePublished,
|
||||||
Release: r.APIFormat(),
|
Release: r.APIFormat(),
|
||||||
Repository: r.Repo.APIFormatLegacy(nil),
|
Repository: r.Repo.APIFormatLegacy(nil),
|
||||||
Sender: r.Publisher.APIFormat(),
|
Sender: r.Publisher.APIFormat(),
|
||||||
@@ -203,7 +202,7 @@ func NewRelease(gitRepo *git.Repository, r *Release, uuids []string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ errutil.NotFound = (*ErrReleaseNotExist)(nil)
|
var _ errx.NotFound = (*ErrReleaseNotExist)(nil)
|
||||||
|
|
||||||
type ErrReleaseNotExist struct {
|
type ErrReleaseNotExist struct {
|
||||||
args map[string]any
|
args map[string]any
|
||||||
@@ -359,11 +358,13 @@ func DeleteReleaseOfRepoByID(repoID, id int64) error {
|
|||||||
return errors.Newf("GetRepositoryByID: %v", err)
|
return errors.Newf("GetRepositoryByID: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, stderr, err := process.ExecDir(-1, repo.RepoPath(),
|
gitRepo, err := git.Open(repo.RepoPath())
|
||||||
fmt.Sprintf("DeleteReleaseByID (git tag -d): %d", rel.ID),
|
if err != nil {
|
||||||
"git", "tag", "-d", rel.TagName)
|
return errors.Newf("open repository: %v", err)
|
||||||
if err != nil && !strings.Contains(stderr, "not found") {
|
}
|
||||||
return errors.Newf("git tag -d: %v - %s", err, stderr)
|
err = gitRepo.DeleteTag(rel.TagName)
|
||||||
|
if err != nil && !strings.Contains(err.Error(), "not found") {
|
||||||
|
return errors.Newf("delete tag: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err = x.Id(rel.ID).Delete(new(Release)); err != nil {
|
if _, err = x.Id(rel.ID).Delete(new(Release)); err != nil {
|
||||||
|
|||||||
@@ -26,19 +26,19 @@ import (
|
|||||||
"xorm.io/xorm"
|
"xorm.io/xorm"
|
||||||
|
|
||||||
"github.com/gogs/git-module"
|
"github.com/gogs/git-module"
|
||||||
api "github.com/gogs/go-gogs-client"
|
|
||||||
|
|
||||||
embedConf "gogs.io/gogs/conf"
|
embedConf "gogs.io/gogs/conf"
|
||||||
"gogs.io/gogs/internal/avatar"
|
"gogs.io/gogs/internal/avatar"
|
||||||
"gogs.io/gogs/internal/conf"
|
"gogs.io/gogs/internal/conf"
|
||||||
"gogs.io/gogs/internal/dbutil"
|
"gogs.io/gogs/internal/dbx"
|
||||||
"gogs.io/gogs/internal/errutil"
|
"gogs.io/gogs/internal/errx"
|
||||||
"gogs.io/gogs/internal/markup"
|
"gogs.io/gogs/internal/markup"
|
||||||
"gogs.io/gogs/internal/osutil"
|
"gogs.io/gogs/internal/osx"
|
||||||
"gogs.io/gogs/internal/process"
|
"gogs.io/gogs/internal/process"
|
||||||
"gogs.io/gogs/internal/repoutil"
|
"gogs.io/gogs/internal/repox"
|
||||||
"gogs.io/gogs/internal/semverutil"
|
apiv1types "gogs.io/gogs/internal/route/api/v1/types"
|
||||||
"gogs.io/gogs/internal/strutil"
|
"gogs.io/gogs/internal/semverx"
|
||||||
|
"gogs.io/gogs/internal/strx"
|
||||||
"gogs.io/gogs/internal/sync"
|
"gogs.io/gogs/internal/sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -80,7 +80,7 @@ func LoadRepoConfig() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
customPath := filepath.Join(conf.CustomDir(), "conf", t)
|
customPath := filepath.Join(conf.CustomDir(), "conf", t)
|
||||||
if osutil.IsDir(customPath) {
|
if osx.IsDir(customPath) {
|
||||||
entries, err := os.ReadDir(customPath)
|
entries, err := os.ReadDir(customPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("Failed to get custom %s files: %v", t, err)
|
log.Fatal("Failed to get custom %s files: %v", t, err)
|
||||||
@@ -88,7 +88,7 @@ func LoadRepoConfig() {
|
|||||||
|
|
||||||
for _, entry := range entries {
|
for _, entry := range entries {
|
||||||
f := entry.Name()
|
f := entry.Name()
|
||||||
if !strutil.ContainsFold(files, f) {
|
if !strx.ContainsFold(files, f) {
|
||||||
files = append(files, f)
|
files = append(files, f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -136,7 +136,7 @@ func NewRepoContext() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
log.Trace("Git version: %s", conf.Git.Version)
|
log.Trace("Git version: %s", conf.Git.Version)
|
||||||
if semverutil.Compare(conf.Git.Version, "<", "1.8.3") {
|
if semverx.Compare(conf.Git.Version, "<", "1.8.3") {
|
||||||
log.Fatal("Gogs requires Git version greater or equal to 1.8.3")
|
log.Fatal("Gogs requires Git version greater or equal to 1.8.3")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,6 +162,7 @@ func NewRepoContext() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
RemoveAllWithNotice("Clean up repository temporary data", filepath.Join(conf.Server.AppDataPath, "tmp"))
|
RemoveAllWithNotice("Clean up repository temporary data", filepath.Join(conf.Server.AppDataPath, "tmp"))
|
||||||
|
RemoveAllWithNotice("Clean up LFS temporary data", conf.LFS.ObjectsTempPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Repository contains information of a repository.
|
// Repository contains information of a repository.
|
||||||
@@ -306,7 +307,7 @@ func (r *Repository) FullName() string {
|
|||||||
return r.MustOwner().Name + "/" + r.Name
|
return r.MustOwner().Name + "/" + r.Name
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: Use repoutil.HTMLURL instead.
|
// Deprecated: Use repox.HTMLURL instead.
|
||||||
func (r *Repository) HTMLURL() string {
|
func (r *Repository) HTMLURL() string {
|
||||||
return conf.Server.ExternalURL + r.FullName()
|
return conf.Server.ExternalURL + r.FullName()
|
||||||
}
|
}
|
||||||
@@ -321,7 +322,7 @@ func (r *Repository) CustomAvatarPath() string {
|
|||||||
// Since Gravatar support not needed here - just check for image path.
|
// Since Gravatar support not needed here - just check for image path.
|
||||||
func (r *Repository) RelAvatarLink() string {
|
func (r *Repository) RelAvatarLink() string {
|
||||||
defaultImgURL := ""
|
defaultImgURL := ""
|
||||||
if !osutil.Exist(r.CustomAvatarPath()) {
|
if !osx.Exist(r.CustomAvatarPath()) {
|
||||||
return defaultImgURL
|
return defaultImgURL
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("%s/%s/%d", conf.Server.Subpath, RepoAvatarURLPrefix, r.ID)
|
return fmt.Sprintf("%s/%s/%d", conf.Server.Subpath, RepoAvatarURLPrefix, r.ID)
|
||||||
@@ -376,9 +377,9 @@ func (r *Repository) DeleteAvatar() error {
|
|||||||
// Arguments that are allowed to be nil: permission
|
// Arguments that are allowed to be nil: permission
|
||||||
//
|
//
|
||||||
// Deprecated: Use APIFormat instead.
|
// Deprecated: Use APIFormat instead.
|
||||||
func (r *Repository) APIFormatLegacy(permission *api.Permission, user ...*User) *api.Repository {
|
func (r *Repository) APIFormatLegacy(permission *apiv1types.RepositoryPermission, user ...*User) *apiv1types.Repository {
|
||||||
cloneLink := r.CloneLink()
|
cloneLink := r.CloneLink()
|
||||||
apiRepo := &api.Repository{
|
apiRepo := &apiv1types.Repository{
|
||||||
ID: r.ID,
|
ID: r.ID,
|
||||||
Owner: r.Owner.APIFormat(),
|
Owner: r.Owner.APIFormat(),
|
||||||
Name: r.Name,
|
Name: r.Name,
|
||||||
@@ -405,7 +406,7 @@ func (r *Repository) APIFormatLegacy(permission *api.Permission, user ...*User)
|
|||||||
// AvatarUrl: r.AvatarLink(),
|
// AvatarUrl: r.AvatarLink(),
|
||||||
}
|
}
|
||||||
if r.IsFork {
|
if r.IsFork {
|
||||||
p := &api.Permission{Pull: true}
|
p := &apiv1types.RepositoryPermission{Pull: true}
|
||||||
if len(user) != 0 {
|
if len(user) != 0 {
|
||||||
accessMode := Handle.Permissions().AccessMode(
|
accessMode := Handle.Permissions().AccessMode(
|
||||||
context.TODO(),
|
context.TODO(),
|
||||||
@@ -555,7 +556,7 @@ func (r *Repository) GetAssigneeByID(userID int64) (*User, error) {
|
|||||||
Private: r.IsPrivate,
|
Private: r.IsPrivate,
|
||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
return nil, ErrUserNotExist{args: errutil.Args{"userID": userID}}
|
return nil, ErrUserNotExist{args: errx.Args{"userID": userID}}
|
||||||
}
|
}
|
||||||
return Handle.Users().GetByID(ctx, userID)
|
return Handle.Users().GetByID(ctx, userID)
|
||||||
}
|
}
|
||||||
@@ -584,7 +585,7 @@ func (r *Repository) repoPath(e Engine) string {
|
|||||||
return RepoPath(r.mustOwner(e).Name, r.Name)
|
return RepoPath(r.mustOwner(e).Name, r.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: Use repoutil.RepositoryPath instead.
|
// Deprecated: Use repox.RepositoryPath instead.
|
||||||
func (r *Repository) RepoPath() string {
|
func (r *Repository) RepoPath() string {
|
||||||
return r.repoPath(x)
|
return r.repoPath(x)
|
||||||
}
|
}
|
||||||
@@ -601,7 +602,7 @@ func (r *Repository) Link() string {
|
|||||||
return conf.Server.Subpath + "/" + r.FullName()
|
return conf.Server.Subpath + "/" + r.FullName()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: Use repoutil.ComparePath instead.
|
// Deprecated: Use repox.ComparePath instead.
|
||||||
func (r *Repository) ComposeCompareURL(oldCommitID, newCommitID string) string {
|
func (r *Repository) ComposeCompareURL(oldCommitID, newCommitID string) string {
|
||||||
return fmt.Sprintf("%s/%s/compare/%s...%s", r.MustOwner().Name, r.Name, oldCommitID, newCommitID)
|
return fmt.Sprintf("%s/%s/compare/%s...%s", r.MustOwner().Name, r.Name, oldCommitID, newCommitID)
|
||||||
}
|
}
|
||||||
@@ -660,7 +661,7 @@ func (r *Repository) LocalCopyPath() string {
|
|||||||
// assume subsequent operations are against target branch when caller has confidence
|
// assume subsequent operations are against target branch when caller has confidence
|
||||||
// about no race condition.
|
// about no race condition.
|
||||||
func UpdateLocalCopyBranch(repoPath, localPath, branch string, isWiki bool) (err error) {
|
func UpdateLocalCopyBranch(repoPath, localPath, branch string, isWiki bool) (err error) {
|
||||||
if !osutil.Exist(localPath) {
|
if !osx.Exist(localPath) {
|
||||||
// Checkout to a specific branch fails when wiki is an empty repository.
|
// Checkout to a specific branch fails when wiki is an empty repository.
|
||||||
if isWiki {
|
if isWiki {
|
||||||
branch = ""
|
branch = ""
|
||||||
@@ -735,7 +736,7 @@ func isRepositoryExist(e Engine, u *User, repoName string) (bool, error) {
|
|||||||
OwnerID: u.ID,
|
OwnerID: u.ID,
|
||||||
LowerName: strings.ToLower(repoName),
|
LowerName: strings.ToLower(repoName),
|
||||||
})
|
})
|
||||||
return has && osutil.IsDir(RepoPath(u.Name, repoName)), err
|
return has && osx.IsDir(RepoPath(u.Name, repoName)), err
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsRepositoryExist returns true if the repository with given name under user has already existed.
|
// IsRepositoryExist returns true if the repository with given name under user has already existed.
|
||||||
@@ -743,28 +744,28 @@ func IsRepositoryExist(u *User, repoName string) (bool, error) {
|
|||||||
return isRepositoryExist(x, u, repoName)
|
return isRepositoryExist(x, u, repoName)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: Use repoutil.NewCloneLink instead.
|
// Deprecated: Use repox.NewCloneLink instead.
|
||||||
func (r *Repository) cloneLink(isWiki bool) *repoutil.CloneLink {
|
func (r *Repository) cloneLink(isWiki bool) *repox.CloneLink {
|
||||||
repoName := r.Name
|
repoName := r.Name
|
||||||
if isWiki {
|
if isWiki {
|
||||||
repoName += ".wiki"
|
repoName += ".wiki"
|
||||||
}
|
}
|
||||||
|
|
||||||
r.Owner = r.MustOwner()
|
r.Owner = r.MustOwner()
|
||||||
cl := new(repoutil.CloneLink)
|
cl := new(repox.CloneLink)
|
||||||
if conf.SSH.Port != 22 {
|
if conf.SSH.Port != 22 {
|
||||||
cl.SSH = fmt.Sprintf("ssh://%s@%s:%d/%s/%s.git", conf.App.RunUser, conf.SSH.Domain, conf.SSH.Port, r.Owner.Name, repoName)
|
cl.SSH = fmt.Sprintf("ssh://%s@%s:%d/%s/%s.git", conf.App.RunUser, conf.SSH.Domain, conf.SSH.Port, r.Owner.Name, repoName)
|
||||||
} else {
|
} else {
|
||||||
cl.SSH = fmt.Sprintf("%s@%s:%s/%s.git", conf.App.RunUser, conf.SSH.Domain, r.Owner.Name, repoName)
|
cl.SSH = fmt.Sprintf("%s@%s:%s/%s.git", conf.App.RunUser, conf.SSH.Domain, r.Owner.Name, repoName)
|
||||||
}
|
}
|
||||||
cl.HTTPS = repoutil.HTTPSCloneURL(r.Owner.Name, repoName)
|
cl.HTTPS = repox.HTTPSCloneURL(r.Owner.Name, repoName)
|
||||||
return cl
|
return cl
|
||||||
}
|
}
|
||||||
|
|
||||||
// CloneLink returns clone URLs of repository.
|
// CloneLink returns clone URLs of repository.
|
||||||
//
|
//
|
||||||
// Deprecated: Use repoutil.NewCloneLink instead.
|
// Deprecated: Use repox.NewCloneLink instead.
|
||||||
func (r *Repository) CloneLink() (cl *repoutil.CloneLink) {
|
func (r *Repository) CloneLink() (cl *repox.CloneLink) {
|
||||||
return r.cloneLink(false)
|
return r.cloneLink(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -989,7 +990,7 @@ func getRepoInitFile(tp, name string) ([]byte, error) {
|
|||||||
|
|
||||||
// Use custom file when available.
|
// Use custom file when available.
|
||||||
customPath := filepath.Join(conf.CustomDir(), "conf", relPath)
|
customPath := filepath.Join(conf.CustomDir(), "conf", relPath)
|
||||||
if osutil.IsFile(customPath) {
|
if osx.IsFile(customPath) {
|
||||||
return os.ReadFile(customPath)
|
return os.ReadFile(customPath)
|
||||||
}
|
}
|
||||||
return embedConf.Files.ReadFile(relPath)
|
return embedConf.Files.ReadFile(relPath)
|
||||||
@@ -1147,14 +1148,14 @@ func createRepository(e *xorm.Session, doer, owner *User, repo *Repository) (err
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Newf("IsRepositoryExist: %v", err)
|
return errors.Newf("IsRepositoryExist: %v", err)
|
||||||
} else if has {
|
} else if has {
|
||||||
return ErrRepoAlreadyExist{args: errutil.Args{"ownerID": owner.ID, "name": repo.Name}}
|
return ErrRepoAlreadyExist{args: errx.Args{"ownerID": owner.ID, "name": repo.Name}}
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err = e.Insert(repo); err != nil {
|
if _, err = e.Insert(repo); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = e.Exec(dbutil.Quote("UPDATE %s SET num_repos = num_repos + 1 WHERE id = ?", "user"), owner.ID)
|
_, err = e.Exec(dbx.Quote("UPDATE %s SET num_repos = num_repos + 1 WHERE id = ?", "user"), owner.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "increase owned repository count")
|
return errors.Wrap(err, "increase owned repository count")
|
||||||
}
|
}
|
||||||
@@ -1221,7 +1222,7 @@ func (err ErrReachLimitOfRepo) Error() string {
|
|||||||
// CreateRepository creates a repository for given user or organization.
|
// CreateRepository creates a repository for given user or organization.
|
||||||
func CreateRepository(doer, owner *User, opts CreateRepoOptionsLegacy) (_ *Repository, err error) {
|
func CreateRepository(doer, owner *User, opts CreateRepoOptionsLegacy) (_ *Repository, err error) {
|
||||||
repoPath := RepoPath(owner.Name, opts.Name)
|
repoPath := RepoPath(owner.Name, opts.Name)
|
||||||
if osutil.Exist(repoPath) {
|
if osx.Exist(repoPath) {
|
||||||
return nil, errors.Errorf("repository directory already exists: %s", repoPath)
|
return nil, errors.Errorf("repository directory already exists: %s", repoPath)
|
||||||
}
|
}
|
||||||
if !owner.canCreateRepo() {
|
if !owner.canCreateRepo() {
|
||||||
@@ -1360,9 +1361,9 @@ func FilterRepositoryWithIssues(repoIDs []int64) ([]int64, error) {
|
|||||||
|
|
||||||
// RepoPath returns repository path by given user and repository name.
|
// RepoPath returns repository path by given user and repository name.
|
||||||
//
|
//
|
||||||
// Deprecated: Use repoutil.RepositoryPath instead.
|
// Deprecated: Use repox.RepositoryPath instead.
|
||||||
func RepoPath(userName, repoName string) string {
|
func RepoPath(userName, repoName string) string {
|
||||||
return filepath.Join(repoutil.UserPath(userName), strings.ToLower(repoName)+".git")
|
return filepath.Join(repox.UserPath(userName), strings.ToLower(repoName)+".git")
|
||||||
}
|
}
|
||||||
|
|
||||||
// TransferOwnership transfers all corresponding setting from old user to new one.
|
// TransferOwnership transfers all corresponding setting from old user to new one.
|
||||||
@@ -1377,7 +1378,7 @@ func TransferOwnership(doer *User, newOwnerName string, repo *Repository) error
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Newf("IsRepositoryExist: %v", err)
|
return errors.Newf("IsRepositoryExist: %v", err)
|
||||||
} else if has {
|
} else if has {
|
||||||
return ErrRepoAlreadyExist{args: errutil.Args{"ownerName": newOwnerName, "name": repo.Name}}
|
return ErrRepoAlreadyExist{args: errx.Args{"ownerName": newOwnerName, "name": repo.Name}}
|
||||||
}
|
}
|
||||||
|
|
||||||
sess := x.NewSession()
|
sess := x.NewSession()
|
||||||
@@ -1489,7 +1490,7 @@ func TransferOwnership(doer *User, newOwnerName string, repo *Repository) error
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Rename remote repository to new path and delete local copy.
|
// Rename remote repository to new path and delete local copy.
|
||||||
if err = os.MkdirAll(repoutil.UserPath(newOwner.Name), os.ModePerm); err != nil {
|
if err = os.MkdirAll(repox.UserPath(newOwner.Name), os.ModePerm); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err = os.Rename(RepoPath(owner.Name, repo.Name), RepoPath(newOwner.Name, repo.Name)); err != nil {
|
if err = os.Rename(RepoPath(owner.Name, repo.Name), RepoPath(newOwner.Name, repo.Name)); err != nil {
|
||||||
@@ -1500,7 +1501,7 @@ func TransferOwnership(doer *User, newOwnerName string, repo *Repository) error
|
|||||||
|
|
||||||
// Rename remote wiki repository to new path and delete local copy.
|
// Rename remote wiki repository to new path and delete local copy.
|
||||||
wikiPath := WikiPath(owner.Name, repo.Name)
|
wikiPath := WikiPath(owner.Name, repo.Name)
|
||||||
if osutil.Exist(wikiPath) {
|
if osx.Exist(wikiPath) {
|
||||||
RemoveAllWithNotice("Delete repository wiki local copy", repo.LocalWikiPath())
|
RemoveAllWithNotice("Delete repository wiki local copy", repo.LocalWikiPath())
|
||||||
if err = os.Rename(wikiPath, WikiPath(newOwner.Name, repo.Name)); err != nil {
|
if err = os.Rename(wikiPath, WikiPath(newOwner.Name, repo.Name)); err != nil {
|
||||||
return errors.Newf("rename repository wiki: %v", err)
|
return errors.Newf("rename repository wiki: %v", err)
|
||||||
@@ -1513,7 +1514,7 @@ func TransferOwnership(doer *User, newOwnerName string, repo *Repository) error
|
|||||||
func deleteRepoLocalCopy(repoID int64) {
|
func deleteRepoLocalCopy(repoID int64) {
|
||||||
repoWorkingPool.CheckIn(strconv.FormatInt(repoID, 10))
|
repoWorkingPool.CheckIn(strconv.FormatInt(repoID, 10))
|
||||||
defer repoWorkingPool.CheckOut(strconv.FormatInt(repoID, 10))
|
defer repoWorkingPool.CheckOut(strconv.FormatInt(repoID, 10))
|
||||||
RemoveAllWithNotice(fmt.Sprintf("Delete repository %d local copy", repoID), repoutil.RepositoryLocalPath(repoID))
|
RemoveAllWithNotice(fmt.Sprintf("Delete repository %d local copy", repoID), repox.RepositoryLocalPath(repoID))
|
||||||
}
|
}
|
||||||
|
|
||||||
// ChangeRepositoryName changes all corresponding setting from old repository name to new one.
|
// ChangeRepositoryName changes all corresponding setting from old repository name to new one.
|
||||||
@@ -1528,7 +1529,7 @@ func ChangeRepositoryName(u *User, oldRepoName, newRepoName string) (err error)
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Newf("IsRepositoryExist: %v", err)
|
return errors.Newf("IsRepositoryExist: %v", err)
|
||||||
} else if has {
|
} else if has {
|
||||||
return ErrRepoAlreadyExist{args: errutil.Args{"ownerID": u.ID, "name": newRepoName}}
|
return ErrRepoAlreadyExist{args: errx.Args{"ownerID": u.ID, "name": newRepoName}}
|
||||||
}
|
}
|
||||||
|
|
||||||
repo, err := GetRepositoryByName(u.ID, oldRepoName)
|
repo, err := GetRepositoryByName(u.ID, oldRepoName)
|
||||||
@@ -1542,7 +1543,7 @@ func ChangeRepositoryName(u *User, oldRepoName, newRepoName string) (err error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
wikiPath := repo.WikiPath()
|
wikiPath := repo.WikiPath()
|
||||||
if osutil.Exist(wikiPath) {
|
if osx.Exist(wikiPath) {
|
||||||
if err = os.Rename(wikiPath, WikiPath(u.Name, newRepoName)); err != nil {
|
if err = os.Rename(wikiPath, WikiPath(u.Name, newRepoName)); err != nil {
|
||||||
return errors.Newf("rename repository wiki: %v", err)
|
return errors.Newf("rename repository wiki: %v", err)
|
||||||
}
|
}
|
||||||
@@ -1600,11 +1601,11 @@ func updateRepository(e Engine, repo *Repository, visibilityChanged bool) (err e
|
|||||||
|
|
||||||
// Create/Remove git-daemon-export-ok for git-daemon
|
// Create/Remove git-daemon-export-ok for git-daemon
|
||||||
daemonExportFile := path.Join(repo.RepoPath(), "git-daemon-export-ok")
|
daemonExportFile := path.Join(repo.RepoPath(), "git-daemon-export-ok")
|
||||||
if repo.IsPrivate && osutil.Exist(daemonExportFile) {
|
if repo.IsPrivate && osx.Exist(daemonExportFile) {
|
||||||
if err = os.Remove(daemonExportFile); err != nil {
|
if err = os.Remove(daemonExportFile); err != nil {
|
||||||
log.Error("Failed to remove %s: %v", daemonExportFile, err)
|
log.Error("Failed to remove %s: %v", daemonExportFile, err)
|
||||||
}
|
}
|
||||||
} else if !repo.IsPrivate && !osutil.Exist(daemonExportFile) {
|
} else if !repo.IsPrivate && !osx.Exist(daemonExportFile) {
|
||||||
if f, err := os.Create(daemonExportFile); err != nil {
|
if f, err := os.Create(daemonExportFile); err != nil {
|
||||||
log.Error("Failed to create %s: %v", daemonExportFile, err)
|
log.Error("Failed to create %s: %v", daemonExportFile, err)
|
||||||
} else {
|
} else {
|
||||||
@@ -1936,7 +1937,7 @@ func DeleteOldRepositoryArchives() {
|
|||||||
basePath := filepath.Join(repo.RepoPath(), "archives")
|
basePath := filepath.Join(repo.RepoPath(), "archives")
|
||||||
for _, format := range formats {
|
for _, format := range formats {
|
||||||
dirPath := filepath.Join(basePath, format)
|
dirPath := filepath.Join(basePath, format)
|
||||||
if !osutil.IsDir(dirPath) {
|
if !osx.IsDir(dirPath) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1999,7 +2000,7 @@ func gatherMissingRepoRecords() ([]*Repository, error) {
|
|||||||
if err := x.Where("id > 0").Iterate(new(Repository),
|
if err := x.Where("id > 0").Iterate(new(Repository),
|
||||||
func(idx int, bean any) error {
|
func(idx int, bean any) error {
|
||||||
repo := bean.(*Repository)
|
repo := bean.(*Repository)
|
||||||
if !osutil.IsDir(repo.RepoPath()) {
|
if !osx.IsDir(repo.RepoPath()) {
|
||||||
repos = append(repos, repo)
|
repos = append(repos, repo)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@@ -2415,7 +2416,7 @@ func GetWatchers(repoID int64) ([]*Watch, error) {
|
|||||||
func (r *Repository) GetWatchers(page int) ([]*User, error) {
|
func (r *Repository) GetWatchers(page int) ([]*User, error) {
|
||||||
users := make([]*User, 0, ItemsPerPage)
|
users := make([]*User, 0, ItemsPerPage)
|
||||||
sess := x.Limit(ItemsPerPage, (page-1)*ItemsPerPage).Where("watch.repo_id=?", r.ID)
|
sess := x.Limit(ItemsPerPage, (page-1)*ItemsPerPage).Where("watch.repo_id=?", r.ID)
|
||||||
if conf.UsePostgreSQL || conf.UseMSSQL {
|
if conf.UsePostgreSQL {
|
||||||
sess = sess.Join("LEFT", "watch", `"user".id=watch.user_id`)
|
sess = sess.Join("LEFT", "watch", `"user".id=watch.user_id`)
|
||||||
} else {
|
} else {
|
||||||
sess = sess.Join("LEFT", "watch", "user.id=watch.user_id")
|
sess = sess.Join("LEFT", "watch", "user.id=watch.user_id")
|
||||||
@@ -2515,7 +2516,7 @@ func IsStaring(userID, repoID int64) bool {
|
|||||||
func (r *Repository) GetStargazers(page int) ([]*User, error) {
|
func (r *Repository) GetStargazers(page int) ([]*User, error) {
|
||||||
users := make([]*User, 0, ItemsPerPage)
|
users := make([]*User, 0, ItemsPerPage)
|
||||||
sess := x.Limit(ItemsPerPage, (page-1)*ItemsPerPage).Where("star.repo_id=?", r.ID)
|
sess := x.Limit(ItemsPerPage, (page-1)*ItemsPerPage).Where("star.repo_id=?", r.ID)
|
||||||
if conf.UsePostgreSQL || conf.UseMSSQL {
|
if conf.UsePostgreSQL {
|
||||||
sess = sess.Join("LEFT", "star", `"user".id=star.uid`)
|
sess = sess.Join("LEFT", "star", `"user".id=star.uid`)
|
||||||
} else {
|
} else {
|
||||||
sess = sess.Join("LEFT", "star", "user.id=star.uid")
|
sess = sess.Join("LEFT", "star", "user.id=star.uid")
|
||||||
@@ -2608,7 +2609,7 @@ func ForkRepository(doer, owner *User, baseRepo *Repository, name, desc string)
|
|||||||
if err = repo.UpdateSize(); err != nil {
|
if err = repo.UpdateSize(); err != nil {
|
||||||
log.Error("UpdateSize [repo_id: %d]: %v", repo.ID, err)
|
log.Error("UpdateSize [repo_id: %d]: %v", repo.ID, err)
|
||||||
}
|
}
|
||||||
if err = PrepareWebhooks(baseRepo, HookEventTypeFork, &api.ForkPayload{
|
if err = PrepareWebhooks(baseRepo, HookEventTypeFork, &apiv1types.WebhookForkPayload{
|
||||||
Forkee: repo.APIFormatLegacy(nil),
|
Forkee: repo.APIFormatLegacy(nil),
|
||||||
Repo: baseRepo.APIFormatLegacy(nil),
|
Repo: baseRepo.APIFormatLegacy(nil),
|
||||||
Sender: doer.APIFormat(),
|
Sender: doer.APIFormat(),
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import (
|
|||||||
"github.com/cockroachdb/errors"
|
"github.com/cockroachdb/errors"
|
||||||
"github.com/gogs/git-module"
|
"github.com/gogs/git-module"
|
||||||
|
|
||||||
"gogs.io/gogs/internal/errutil"
|
"gogs.io/gogs/internal/errx"
|
||||||
"gogs.io/gogs/internal/tool"
|
"gogs.io/gogs/internal/tool"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -42,7 +42,7 @@ func GetBranchesByPath(path string) ([]*Branch, error) {
|
|||||||
return branches, nil
|
return branches, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ errutil.NotFound = (*ErrBranchNotExist)(nil)
|
var _ errx.NotFound = (*ErrBranchNotExist)(nil)
|
||||||
|
|
||||||
type ErrBranchNotExist struct {
|
type ErrBranchNotExist struct {
|
||||||
args map[string]any
|
args map[string]any
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
package database
|
package database
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/cockroachdb/errors"
|
||||||
log "unknwon.dev/clog/v2"
|
log "unknwon.dev/clog/v2"
|
||||||
|
|
||||||
"github.com/cockroachdb/errors"
|
apiv1types "gogs.io/gogs/internal/route/api/v1/types"
|
||||||
api "github.com/gogs/go-gogs-client"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Collaboration represent the relation between an individual and a repository.
|
// Collaboration represent the relation between an individual and a repository.
|
||||||
@@ -87,10 +87,10 @@ type Collaborator struct {
|
|||||||
Collaboration *Collaboration
|
Collaboration *Collaboration
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Collaborator) APIFormat() *api.Collaborator {
|
func (c *Collaborator) APIFormat() *apiv1types.RepositoryCollaborator {
|
||||||
return &api.Collaborator{
|
return &apiv1types.RepositoryCollaborator{
|
||||||
User: c.User.APIFormat(),
|
User: c.User.APIFormat(),
|
||||||
Permissions: api.Permission{
|
Permissions: apiv1types.RepositoryPermission{
|
||||||
Admin: c.Collaboration.Mode >= AccessModeAdmin,
|
Admin: c.Collaboration.Mode >= AccessModeAdmin,
|
||||||
Push: c.Collaboration.Mode >= AccessModeWrite,
|
Push: c.Collaboration.Mode >= AccessModeWrite,
|
||||||
Pull: c.Collaboration.Mode >= AccessModeRead,
|
Pull: c.Collaboration.Mode >= AccessModeRead,
|
||||||
|
|||||||
@@ -18,11 +18,11 @@ import (
|
|||||||
"github.com/gogs/git-module"
|
"github.com/gogs/git-module"
|
||||||
|
|
||||||
"gogs.io/gogs/internal/conf"
|
"gogs.io/gogs/internal/conf"
|
||||||
"gogs.io/gogs/internal/cryptoutil"
|
"gogs.io/gogs/internal/cryptox"
|
||||||
"gogs.io/gogs/internal/gitutil"
|
"gogs.io/gogs/internal/gitx"
|
||||||
"gogs.io/gogs/internal/ioutil"
|
"gogs.io/gogs/internal/iox"
|
||||||
"gogs.io/gogs/internal/osutil"
|
"gogs.io/gogs/internal/osx"
|
||||||
"gogs.io/gogs/internal/pathutil"
|
"gogs.io/gogs/internal/pathx"
|
||||||
"gogs.io/gogs/internal/process"
|
"gogs.io/gogs/internal/process"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -68,7 +68,7 @@ func ComposeHookEnvs(opts ComposeHookEnvsOptions) []string {
|
|||||||
EnvAuthUserName + "=" + opts.AuthUser.Name,
|
EnvAuthUserName + "=" + opts.AuthUser.Name,
|
||||||
EnvAuthUserEmail + "=" + opts.AuthUser.Email,
|
EnvAuthUserEmail + "=" + opts.AuthUser.Email,
|
||||||
EnvRepoOwnerName + "=" + opts.OwnerName,
|
EnvRepoOwnerName + "=" + opts.OwnerName,
|
||||||
EnvRepoOwnerSaltMd5 + "=" + cryptoutil.MD5(opts.OwnerSalt),
|
EnvRepoOwnerSaltMd5 + "=" + cryptox.MD5(opts.OwnerSalt),
|
||||||
EnvRepoID + "=" + strconv.FormatInt(opts.RepoID, 10),
|
EnvRepoID + "=" + strconv.FormatInt(opts.RepoID, 10),
|
||||||
EnvRepoName + "=" + opts.RepoName,
|
EnvRepoName + "=" + opts.RepoName,
|
||||||
EnvRepoCustomHooksPath + "=" + filepath.Join(opts.RepoPath, "custom_hooks"),
|
EnvRepoCustomHooksPath + "=" + filepath.Join(opts.RepoPath, "custom_hooks"),
|
||||||
@@ -86,7 +86,7 @@ func ComposeHookEnvs(opts ComposeHookEnvsOptions) []string {
|
|||||||
// discardLocalRepoBranchChanges discards local commits/changes of
|
// discardLocalRepoBranchChanges discards local commits/changes of
|
||||||
// given branch to make sure it is even to remote branch.
|
// given branch to make sure it is even to remote branch.
|
||||||
func discardLocalRepoBranchChanges(localPath, branch string) error {
|
func discardLocalRepoBranchChanges(localPath, branch string) error {
|
||||||
if !osutil.Exist(localPath) {
|
if !osx.Exist(localPath) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,7 +123,7 @@ func hasSymlinkInPath(base, relPath string) bool {
|
|||||||
parts := strings.Split(filepath.ToSlash(relPath), "/")
|
parts := strings.Split(filepath.ToSlash(relPath), "/")
|
||||||
for i := range parts {
|
for i := range parts {
|
||||||
filePath := path.Join(append([]string{base}, parts[:i+1]...)...)
|
filePath := path.Join(append([]string{base}, parts[:i+1]...)...)
|
||||||
if osutil.IsSymlink(filePath) {
|
if osx.IsSymlink(filePath) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -189,7 +189,7 @@ func (r *Repository) UpdateRepoFile(doer *User, opts UpdateRepoFileOptions) erro
|
|||||||
newFilePath := path.Join(localPath, opts.NewTreeName)
|
newFilePath := path.Join(localPath, opts.NewTreeName)
|
||||||
|
|
||||||
// Prompt the user if the meant-to-be new file already exists.
|
// Prompt the user if the meant-to-be new file already exists.
|
||||||
if osutil.Exist(newFilePath) && opts.IsNewFile {
|
if osx.Exist(newFilePath) && opts.IsNewFile {
|
||||||
return ErrRepoFileAlreadyExist{newFilePath}
|
return ErrRepoFileAlreadyExist{newFilePath}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -197,7 +197,7 @@ func (r *Repository) UpdateRepoFile(doer *User, opts UpdateRepoFileOptions) erro
|
|||||||
return errors.Wrapf(err, "create parent directories of %q", newFilePath)
|
return errors.Wrapf(err, "create parent directories of %q", newFilePath)
|
||||||
}
|
}
|
||||||
|
|
||||||
if osutil.IsFile(oldFilePath) && opts.OldTreeName != opts.NewTreeName {
|
if osx.IsFile(oldFilePath) && opts.OldTreeName != opts.NewTreeName {
|
||||||
if err := git.Move(localPath, opts.OldTreeName, opts.NewTreeName); err != nil {
|
if err := git.Move(localPath, opts.OldTreeName, opts.NewTreeName); err != nil {
|
||||||
return errors.Wrapf(err, "git mv %q %q", opts.OldTreeName, opts.NewTreeName)
|
return errors.Wrapf(err, "git mv %q %q", opts.OldTreeName, opts.NewTreeName)
|
||||||
}
|
}
|
||||||
@@ -244,7 +244,7 @@ func (r *Repository) UpdateRepoFile(doer *User, opts UpdateRepoFileOptions) erro
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetDiffPreview produces and returns diff result of a file which is not yet committed.
|
// GetDiffPreview produces and returns diff result of a file which is not yet committed.
|
||||||
func (r *Repository) GetDiffPreview(branch, treePath, content string) (*gitutil.Diff, error) {
|
func (r *Repository) GetDiffPreview(branch, treePath, content string) (*gitx.Diff, error) {
|
||||||
// 🚨 SECURITY: Prevent uploading files into the ".git" directory.
|
// 🚨 SECURITY: Prevent uploading files into the ".git" directory.
|
||||||
if isRepositoryGitPath(treePath) {
|
if isRepositoryGitPath(treePath) {
|
||||||
return nil, errors.Errorf("bad tree path %q", treePath)
|
return nil, errors.Errorf("bad tree path %q", treePath)
|
||||||
@@ -291,7 +291,7 @@ func (r *Repository) GetDiffPreview(branch, treePath, content string) (*gitutil.
|
|||||||
pid := process.Add(fmt.Sprintf("GetDiffPreview [repo_path: %s]", r.RepoPath()), cmd)
|
pid := process.Add(fmt.Sprintf("GetDiffPreview [repo_path: %s]", r.RepoPath()), cmd)
|
||||||
defer process.Remove(pid)
|
defer process.Remove(pid)
|
||||||
|
|
||||||
diff, err := gitutil.ParseDiff(stdout, conf.Git.MaxDiffFiles, conf.Git.MaxDiffLines, conf.Git.MaxDiffLineChars)
|
diff, err := gitx.ParseDiff(stdout, conf.Git.MaxDiffFiles, conf.Git.MaxDiffLines, conf.Git.MaxDiffLineChars)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Newf("parse diff: %v", err)
|
return nil, errors.Newf("parse diff: %v", err)
|
||||||
}
|
}
|
||||||
@@ -416,7 +416,7 @@ func (upload *Upload) LocalPath() string {
|
|||||||
// NewUpload creates a new upload object.
|
// NewUpload creates a new upload object.
|
||||||
func NewUpload(name string, buf []byte, file multipart.File) (_ *Upload, err error) {
|
func NewUpload(name string, buf []byte, file multipart.File) (_ *Upload, err error) {
|
||||||
// 🚨 SECURITY: Prevent path traversal.
|
// 🚨 SECURITY: Prevent path traversal.
|
||||||
name = pathutil.Clean(name)
|
name = pathx.Clean(name)
|
||||||
if name == "" {
|
if name == "" {
|
||||||
return nil, errors.New("empty file name")
|
return nil, errors.New("empty file name")
|
||||||
}
|
}
|
||||||
@@ -492,7 +492,7 @@ func DeleteUploads(uploads ...*Upload) (err error) {
|
|||||||
|
|
||||||
for _, upload := range uploads {
|
for _, upload := range uploads {
|
||||||
localPath := upload.LocalPath()
|
localPath := upload.LocalPath()
|
||||||
if !osutil.IsFile(localPath) {
|
if !osx.IsFile(localPath) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -536,7 +536,7 @@ type UploadRepoFileOptions struct {
|
|||||||
// isRepositoryGitPath returns true if given path is or resides inside ".git"
|
// isRepositoryGitPath returns true if given path is or resides inside ".git"
|
||||||
// path of the repository.
|
// path of the repository.
|
||||||
//
|
//
|
||||||
// TODO(unknwon): Move to repoutil during refactoring for this file.
|
// TODO(unknwon): Move to repox during refactoring for this file.
|
||||||
func isRepositoryGitPath(path string) bool {
|
func isRepositoryGitPath(path string) bool {
|
||||||
path = strings.ToLower(path)
|
path = strings.ToLower(path)
|
||||||
return strings.HasSuffix(path, ".git") ||
|
return strings.HasSuffix(path, ".git") ||
|
||||||
@@ -587,12 +587,12 @@ func (r *Repository) UploadRepoFiles(doer *User, opts UploadRepoFileOptions) err
|
|||||||
// Copy uploaded files into repository
|
// Copy uploaded files into repository
|
||||||
for _, upload := range uploads {
|
for _, upload := range uploads {
|
||||||
tmpPath := upload.LocalPath()
|
tmpPath := upload.LocalPath()
|
||||||
if !osutil.IsFile(tmpPath) {
|
if !osx.IsFile(tmpPath) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// 🚨 SECURITY: Prevent path traversal.
|
// 🚨 SECURITY: Prevent path traversal.
|
||||||
upload.Name = pathutil.Clean(upload.Name)
|
upload.Name = pathx.Clean(upload.Name)
|
||||||
|
|
||||||
// 🚨 SECURITY: Prevent uploading files into the ".git" directory.
|
// 🚨 SECURITY: Prevent uploading files into the ".git" directory.
|
||||||
if isRepositoryGitPath(upload.Name) {
|
if isRepositoryGitPath(upload.Name) {
|
||||||
@@ -603,11 +603,11 @@ func (r *Repository) UploadRepoFiles(doer *User, opts UploadRepoFileOptions) err
|
|||||||
|
|
||||||
// 🚨 SECURITY: Prevent updating files in surprising place, check if the target
|
// 🚨 SECURITY: Prevent updating files in surprising place, check if the target
|
||||||
// is a symlink.
|
// is a symlink.
|
||||||
if osutil.IsSymlink(targetPath) {
|
if osx.IsSymlink(targetPath) {
|
||||||
return errors.Newf("cannot overwrite symbolic link: %s", upload.Name)
|
return errors.Newf("cannot overwrite symbolic link: %s", upload.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = ioutil.CopyFile(tmpPath, targetPath); err != nil {
|
if err = iox.CopyFile(tmpPath, targetPath); err != nil {
|
||||||
return errors.Newf("copy: %v", err)
|
return errors.Newf("copy: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import (
|
|||||||
|
|
||||||
"gogs.io/gogs/internal/conf"
|
"gogs.io/gogs/internal/conf"
|
||||||
"gogs.io/gogs/internal/markup"
|
"gogs.io/gogs/internal/markup"
|
||||||
"gogs.io/gogs/internal/osutil"
|
"gogs.io/gogs/internal/osx"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestRepository_ComposeMetas(t *testing.T) {
|
func TestRepository_ComposeMetas(t *testing.T) {
|
||||||
@@ -81,5 +81,5 @@ func Test_CreateRepository_PreventDeletion(t *testing.T) {
|
|||||||
_, err = CreateRepository(owner, owner, opts)
|
_, err = CreateRepository(owner, owner, opts)
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
assert.Contains(t, err.Error(), "repository directory already exists")
|
assert.Contains(t, err.Error(), "repository directory already exists")
|
||||||
assert.True(t, osutil.Exist(canary))
|
assert.True(t, osx.Exist(canary))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,11 +7,11 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/cockroachdb/errors"
|
"github.com/cockroachdb/errors"
|
||||||
api "github.com/gogs/go-gogs-client"
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
|
|
||||||
"gogs.io/gogs/internal/errutil"
|
"gogs.io/gogs/internal/errx"
|
||||||
"gogs.io/gogs/internal/repoutil"
|
"gogs.io/gogs/internal/repox"
|
||||||
|
apiv1types "gogs.io/gogs/internal/route/api/v1/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
// BeforeCreate implements the GORM create hook.
|
// BeforeCreate implements the GORM create hook.
|
||||||
@@ -36,19 +36,19 @@ func (r *Repository) AfterFind(_ *gorm.DB) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type RepositoryAPIFormatOptions struct {
|
type RepositoryAPIFormatOptions struct {
|
||||||
Permission *api.Permission
|
Permission *apiv1types.RepositoryPermission
|
||||||
Parent *api.Repository
|
Parent *apiv1types.Repository
|
||||||
}
|
}
|
||||||
|
|
||||||
// APIFormat returns the API format of a repository.
|
// APIFormat returns the API format of a repository.
|
||||||
func (r *Repository) APIFormat(owner *User, opts ...RepositoryAPIFormatOptions) *api.Repository {
|
func (r *Repository) APIFormat(owner *User, opts ...RepositoryAPIFormatOptions) *apiv1types.Repository {
|
||||||
var opt RepositoryAPIFormatOptions
|
var opt RepositoryAPIFormatOptions
|
||||||
if len(opts) > 0 {
|
if len(opts) > 0 {
|
||||||
opt = opts[0]
|
opt = opts[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
cloneLink := repoutil.NewCloneLink(owner.Name, r.Name, false)
|
cloneLink := repox.NewCloneLink(owner.Name, r.Name, false)
|
||||||
return &api.Repository{
|
return &apiv1types.Repository{
|
||||||
ID: r.ID,
|
ID: r.ID,
|
||||||
Owner: owner.APIFormat(),
|
Owner: owner.APIFormat(),
|
||||||
Name: r.Name,
|
Name: r.Name,
|
||||||
@@ -60,7 +60,7 @@ func (r *Repository) APIFormat(owner *User, opts ...RepositoryAPIFormatOptions)
|
|||||||
Empty: r.IsBare,
|
Empty: r.IsBare,
|
||||||
Mirror: r.IsMirror,
|
Mirror: r.IsMirror,
|
||||||
Size: r.Size,
|
Size: r.Size,
|
||||||
HTMLURL: repoutil.HTMLURL(owner.Name, r.Name),
|
HTMLURL: repox.HTMLURL(owner.Name, r.Name),
|
||||||
SSHURL: cloneLink.SSH,
|
SSHURL: cloneLink.SSH,
|
||||||
CloneURL: cloneLink.HTTPS,
|
CloneURL: cloneLink.HTTPS,
|
||||||
Website: r.Website,
|
Website: r.Website,
|
||||||
@@ -85,7 +85,7 @@ func newReposStore(db *gorm.DB) *RepositoriesStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ErrRepoAlreadyExist struct {
|
type ErrRepoAlreadyExist struct {
|
||||||
args errutil.Args
|
args errx.Args
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsErrRepoAlreadyExist(err error) bool {
|
func IsErrRepoAlreadyExist(err error) bool {
|
||||||
@@ -123,7 +123,7 @@ func (s *RepositoriesStore) Create(ctx context.Context, ownerID int64, opts Crea
|
|||||||
_, err = s.GetByName(ctx, ownerID, opts.Name)
|
_, err = s.GetByName(ctx, ownerID, opts.Name)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return nil, ErrRepoAlreadyExist{
|
return nil, ErrRepoAlreadyExist{
|
||||||
args: errutil.Args{
|
args: errx.Args{
|
||||||
"ownerID": ownerID,
|
"ownerID": ownerID,
|
||||||
"name": opts.Name,
|
"name": opts.Name,
|
||||||
},
|
},
|
||||||
@@ -221,10 +221,10 @@ func (s *RepositoriesStore) GetByCollaboratorIDWithAccessMode(ctx context.Contex
|
|||||||
return repos, nil
|
return repos, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ errutil.NotFound = (*ErrRepoNotExist)(nil)
|
var _ errx.NotFound = (*ErrRepoNotExist)(nil)
|
||||||
|
|
||||||
type ErrRepoNotExist struct {
|
type ErrRepoNotExist struct {
|
||||||
args errutil.Args
|
args errx.Args
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsErrRepoNotExist(err error) bool {
|
func IsErrRepoNotExist(err error) bool {
|
||||||
@@ -247,7 +247,7 @@ func (s *RepositoriesStore) GetByID(ctx context.Context, id int64) (*Repository,
|
|||||||
err := s.db.WithContext(ctx).Where("id = ?", id).First(repo).Error
|
err := s.db.WithContext(ctx).Where("id = ?", id).First(repo).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
return nil, ErrRepoNotExist{errutil.Args{"repoID": id}}
|
return nil, ErrRepoNotExist{errx.Args{"repoID": id}}
|
||||||
}
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -265,7 +265,7 @@ func (s *RepositoriesStore) GetByName(ctx context.Context, ownerID int64, name s
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
if err == gorm.ErrRecordNotFound {
|
if err == gorm.ErrRecordNotFound {
|
||||||
return nil, ErrRepoNotExist{
|
return nil, ErrRepoNotExist{
|
||||||
args: errutil.Args{
|
args: errx.Args{
|
||||||
"ownerID": ownerID,
|
"ownerID": ownerID,
|
||||||
"name": name,
|
"name": name,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import (
|
|||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
|
|
||||||
"gogs.io/gogs/internal/errutil"
|
"gogs.io/gogs/internal/errx"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestRepository_BeforeCreate(t *testing.T) {
|
func TestRepository_BeforeCreate(t *testing.T) {
|
||||||
@@ -121,7 +121,7 @@ func reposCreate(t *testing.T, ctx context.Context, s *RepositoriesStore) {
|
|||||||
Name: "my.git",
|
Name: "my.git",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
wantErr := ErrNameNotAllowed{args: errutil.Args{"reason": "reserved", "pattern": "*.git"}}
|
wantErr := ErrNameNotAllowed{args: errx.Args{"reason": "reserved", "pattern": "*.git"}}
|
||||||
assert.Equal(t, wantErr, err)
|
assert.Equal(t, wantErr, err)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -138,7 +138,7 @@ func reposCreate(t *testing.T, ctx context.Context, s *RepositoriesStore) {
|
|||||||
Name: "repo1",
|
Name: "repo1",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
wantErr := ErrRepoAlreadyExist{args: errutil.Args{"ownerID": int64(2), "name": "repo1"}}
|
wantErr := ErrRepoAlreadyExist{args: errx.Args{"ownerID": int64(2), "name": "repo1"}}
|
||||||
assert.Equal(t, wantErr, err)
|
assert.Equal(t, wantErr, err)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -218,7 +218,7 @@ func reposGetByID(t *testing.T, ctx context.Context, s *RepositoriesStore) {
|
|||||||
assert.Equal(t, repo1.Name, got.Name)
|
assert.Equal(t, repo1.Name, got.Name)
|
||||||
|
|
||||||
_, err = s.GetByID(ctx, 404)
|
_, err = s.GetByID(ctx, 404)
|
||||||
wantErr := ErrRepoNotExist{args: errutil.Args{"repoID": int64(404)}}
|
wantErr := ErrRepoNotExist{args: errx.Args{"repoID": int64(404)}}
|
||||||
assert.Equal(t, wantErr, err)
|
assert.Equal(t, wantErr, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -234,7 +234,7 @@ func reposGetByName(t *testing.T, ctx context.Context, s *RepositoriesStore) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
_, err = s.GetByName(ctx, 1, "bad_name")
|
_, err = s.GetByName(ctx, 1, "bad_name")
|
||||||
wantErr := ErrRepoNotExist{args: errutil.Args{"ownerID": int64(1), "name": "bad_name"}}
|
wantErr := ErrRepoNotExist{args: errx.Args{"ownerID": int64(1), "name": "bad_name"}}
|
||||||
assert.Equal(t, wantErr, err)
|
assert.Equal(t, wantErr, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ import (
|
|||||||
"xorm.io/xorm"
|
"xorm.io/xorm"
|
||||||
|
|
||||||
"gogs.io/gogs/internal/conf"
|
"gogs.io/gogs/internal/conf"
|
||||||
"gogs.io/gogs/internal/errutil"
|
"gogs.io/gogs/internal/errx"
|
||||||
"gogs.io/gogs/internal/osutil"
|
"gogs.io/gogs/internal/osx"
|
||||||
"gogs.io/gogs/internal/process"
|
"gogs.io/gogs/internal/process"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -542,7 +542,7 @@ func RewriteAuthorizedKeys() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if osutil.Exist(fpath) {
|
if osx.Exist(fpath) {
|
||||||
if err = os.Remove(fpath); err != nil {
|
if err = os.Remove(fpath); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -685,7 +685,7 @@ func AddDeployKey(repoID int64, name, content string) (*DeployKey, error) {
|
|||||||
return key, sess.Commit()
|
return key, sess.Commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ errutil.NotFound = (*ErrDeployKeyNotExist)(nil)
|
var _ errx.NotFound = (*ErrDeployKeyNotExist)(nil)
|
||||||
|
|
||||||
type ErrDeployKeyNotExist struct {
|
type ErrDeployKeyNotExist struct {
|
||||||
args map[string]any
|
args map[string]any
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import (
|
|||||||
"github.com/pquerna/otp/totp"
|
"github.com/pquerna/otp/totp"
|
||||||
|
|
||||||
"gogs.io/gogs/internal/conf"
|
"gogs.io/gogs/internal/conf"
|
||||||
"gogs.io/gogs/internal/cryptoutil"
|
"gogs.io/gogs/internal/cryptox"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TwoFactor is a 2FA token of a user.
|
// TwoFactor is a 2FA token of a user.
|
||||||
@@ -28,7 +28,7 @@ func (t *TwoFactor) ValidateTOTP(passcode string) (bool, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return false, errors.Newf("DecodeString: %v", err)
|
return false, errors.Newf("DecodeString: %v", err)
|
||||||
}
|
}
|
||||||
decryptSecret, err := cryptoutil.AESGCMDecrypt(cryptoutil.MD5Bytes(conf.Security.SecretKey), secret)
|
decryptSecret, err := cryptox.AESGCMDecrypt(cryptox.MD5Bytes(conf.Security.SecretKey), secret)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, errors.Newf("AESGCMDecrypt: %v", err)
|
return false, errors.Newf("AESGCMDecrypt: %v", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,9 +11,9 @@ import (
|
|||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
log "unknwon.dev/clog/v2"
|
log "unknwon.dev/clog/v2"
|
||||||
|
|
||||||
"gogs.io/gogs/internal/cryptoutil"
|
"gogs.io/gogs/internal/cryptox"
|
||||||
"gogs.io/gogs/internal/errutil"
|
"gogs.io/gogs/internal/errx"
|
||||||
"gogs.io/gogs/internal/strutil"
|
"gogs.io/gogs/internal/strx"
|
||||||
)
|
)
|
||||||
|
|
||||||
// BeforeCreate implements the GORM create hook.
|
// BeforeCreate implements the GORM create hook.
|
||||||
@@ -44,7 +44,7 @@ func newTwoFactorsStore(db *gorm.DB) *TwoFactorsStore {
|
|||||||
// configured in site-level and change of the "key" will break all existing 2FA
|
// configured in site-level and change of the "key" will break all existing 2FA
|
||||||
// tokens.
|
// tokens.
|
||||||
func (s *TwoFactorsStore) Create(ctx context.Context, userID int64, key, secret string) error {
|
func (s *TwoFactorsStore) Create(ctx context.Context, userID int64, key, secret string) error {
|
||||||
encrypted, err := cryptoutil.AESGCMEncrypt(cryptoutil.MD5Bytes(key), []byte(secret))
|
encrypted, err := cryptox.AESGCMEncrypt(cryptox.MD5Bytes(key), []byte(secret))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "encrypt secret")
|
return errors.Wrap(err, "encrypt secret")
|
||||||
}
|
}
|
||||||
@@ -68,10 +68,10 @@ func (s *TwoFactorsStore) Create(ctx context.Context, userID int64, key, secret
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ errutil.NotFound = (*ErrTwoFactorNotFound)(nil)
|
var _ errx.NotFound = (*ErrTwoFactorNotFound)(nil)
|
||||||
|
|
||||||
type ErrTwoFactorNotFound struct {
|
type ErrTwoFactorNotFound struct {
|
||||||
args errutil.Args
|
args errx.Args
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsErrTwoFactorNotFound(err error) bool {
|
func IsErrTwoFactorNotFound(err error) bool {
|
||||||
@@ -93,7 +93,7 @@ func (s *TwoFactorsStore) GetByUserID(ctx context.Context, userID int64) (*TwoFa
|
|||||||
err := s.db.WithContext(ctx).Where("user_id = ?", userID).First(tf).Error
|
err := s.db.WithContext(ctx).Where("user_id = ?", userID).First(tf).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
return nil, ErrTwoFactorNotFound{args: errutil.Args{"userID": userID}}
|
return nil, ErrTwoFactorNotFound{args: errx.Args{"userID": userID}}
|
||||||
}
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -136,7 +136,7 @@ func (s *TwoFactorsStore) UseRecoveryCode(ctx context.Context, userID int64, cod
|
|||||||
func generateRecoveryCodes(userID int64, n int) ([]*TwoFactorRecoveryCode, error) {
|
func generateRecoveryCodes(userID int64, n int) ([]*TwoFactorRecoveryCode, error) {
|
||||||
recoveryCodes := make([]*TwoFactorRecoveryCode, n)
|
recoveryCodes := make([]*TwoFactorRecoveryCode, n)
|
||||||
for i := range n {
|
for i := range n {
|
||||||
code, err := strutil.RandomChars(10)
|
code, err := strx.RandomChars(10)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "generate random characters")
|
return nil, errors.Wrap(err, "generate random characters")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import (
|
|||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
|
|
||||||
"gogs.io/gogs/internal/errutil"
|
"gogs.io/gogs/internal/errx"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestTwoFactor_BeforeCreate(t *testing.T) {
|
func TestTwoFactor_BeforeCreate(t *testing.T) {
|
||||||
@@ -117,7 +117,7 @@ func twoFactorsGetByUserID(t *testing.T, ctx context.Context, s *TwoFactorsStore
|
|||||||
|
|
||||||
// Try to get a non-existent 2FA token
|
// Try to get a non-existent 2FA token
|
||||||
_, err = s.GetByUserID(ctx, 2)
|
_, err = s.GetByUserID(ctx, 2)
|
||||||
wantErr := ErrTwoFactorNotFound{args: errutil.Args{"userID": int64(2)}}
|
wantErr := ErrTwoFactorNotFound{args: errx.Args{"userID": int64(2)}}
|
||||||
assert.Equal(t, wantErr, err)
|
assert.Equal(t, wantErr, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,21 +11,21 @@ import (
|
|||||||
|
|
||||||
"github.com/cockroachdb/errors"
|
"github.com/cockroachdb/errors"
|
||||||
"github.com/go-macaron/binding"
|
"github.com/go-macaron/binding"
|
||||||
api "github.com/gogs/go-gogs-client"
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
log "unknwon.dev/clog/v2"
|
log "unknwon.dev/clog/v2"
|
||||||
|
|
||||||
"gogs.io/gogs/internal/auth"
|
"gogs.io/gogs/internal/auth"
|
||||||
"gogs.io/gogs/internal/conf"
|
"gogs.io/gogs/internal/conf"
|
||||||
"gogs.io/gogs/internal/cryptoutil"
|
"gogs.io/gogs/internal/cryptox"
|
||||||
"gogs.io/gogs/internal/dbutil"
|
"gogs.io/gogs/internal/dbx"
|
||||||
"gogs.io/gogs/internal/errutil"
|
"gogs.io/gogs/internal/errx"
|
||||||
"gogs.io/gogs/internal/markup"
|
"gogs.io/gogs/internal/markup"
|
||||||
"gogs.io/gogs/internal/osutil"
|
"gogs.io/gogs/internal/osx"
|
||||||
"gogs.io/gogs/internal/repoutil"
|
"gogs.io/gogs/internal/repox"
|
||||||
"gogs.io/gogs/internal/strutil"
|
apiv1types "gogs.io/gogs/internal/route/api/v1/types"
|
||||||
|
"gogs.io/gogs/internal/strx"
|
||||||
"gogs.io/gogs/internal/tool"
|
"gogs.io/gogs/internal/tool"
|
||||||
"gogs.io/gogs/internal/userutil"
|
"gogs.io/gogs/internal/userx"
|
||||||
)
|
)
|
||||||
|
|
||||||
// UsersStore is the storage layer for users.
|
// UsersStore is the storage layer for users.
|
||||||
@@ -38,7 +38,7 @@ func newUsersStore(db *gorm.DB) *UsersStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ErrLoginSourceMismatch struct {
|
type ErrLoginSourceMismatch struct {
|
||||||
args errutil.Args
|
args errx.Args
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsErrLoginSourceMismatch returns true if the underlying error has the type
|
// IsErrLoginSourceMismatch returns true if the underlying error has the type
|
||||||
@@ -86,12 +86,12 @@ func (s *UsersStore) Authenticate(ctx context.Context, login, password string, l
|
|||||||
// Note: This check is unnecessary but to reduce user confusion at login page
|
// Note: This check is unnecessary but to reduce user confusion at login page
|
||||||
// and make it more consistent from user's perspective.
|
// and make it more consistent from user's perspective.
|
||||||
if loginSourceID >= 0 && user.LoginSource != loginSourceID {
|
if loginSourceID >= 0 && user.LoginSource != loginSourceID {
|
||||||
return nil, ErrLoginSourceMismatch{args: errutil.Args{"expect": loginSourceID, "actual": user.LoginSource}}
|
return nil, ErrLoginSourceMismatch{args: errx.Args{"expect": loginSourceID, "actual": user.LoginSource}}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate password hash fetched from database for local accounts.
|
// Validate password hash fetched from database for local accounts.
|
||||||
if user.IsLocal() {
|
if user.IsLocal() {
|
||||||
if userutil.ValidatePassword(user.Password, user.Salt, password) {
|
if userx.ValidatePassword(user.Password, user.Salt, password) {
|
||||||
return user, nil
|
return user, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,7 +158,7 @@ func (s *UsersStore) ChangeUsername(ctx context.Context, userID int64, newUserna
|
|||||||
|
|
||||||
if s.IsUsernameUsed(ctx, newUsername, userID) {
|
if s.IsUsernameUsed(ctx, newUsername, userID) {
|
||||||
return ErrUserAlreadyExist{
|
return ErrUserAlreadyExist{
|
||||||
args: errutil.Args{
|
args: errx.Args{
|
||||||
"name": newUsername,
|
"name": newUsername,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -212,16 +212,16 @@ func (s *UsersStore) ChangeUsername(ctx context.Context, userID int64, newUserna
|
|||||||
}
|
}
|
||||||
|
|
||||||
deleteRepoLocalCopy(repo.ID)
|
deleteRepoLocalCopy(repo.ID)
|
||||||
RemoveAllWithNotice(fmt.Sprintf("Delete repository %d wiki local copy", repo.ID), repoutil.RepositoryLocalWikiPath(repo.ID))
|
RemoveAllWithNotice(fmt.Sprintf("Delete repository %d wiki local copy", repo.ID), repox.RepositoryLocalWikiPath(repo.ID))
|
||||||
}
|
}
|
||||||
if err = rows.Err(); err != nil {
|
if err = rows.Err(); err != nil {
|
||||||
return errors.Wrap(err, "check rows.Err")
|
return errors.Wrap(err, "check rows.Err")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rename user directory if exists
|
// Rename user directory if exists
|
||||||
userPath := repoutil.UserPath(user.Name)
|
userPath := repox.UserPath(user.Name)
|
||||||
if osutil.Exist(userPath) {
|
if osx.Exist(userPath) {
|
||||||
newUserPath := repoutil.UserPath(newUsername)
|
newUserPath := repox.UserPath(newUsername)
|
||||||
err = os.Rename(userPath, newUserPath)
|
err = os.Rename(userPath, newUserPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "rename user directory")
|
return errors.Wrap(err, "rename user directory")
|
||||||
@@ -250,7 +250,7 @@ type CreateUserOptions struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ErrUserAlreadyExist struct {
|
type ErrUserAlreadyExist struct {
|
||||||
args errutil.Args
|
args errx.Args
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsErrUserAlreadyExist returns true if the underlying error has the type
|
// IsErrUserAlreadyExist returns true if the underlying error has the type
|
||||||
@@ -264,7 +264,7 @@ func (err ErrUserAlreadyExist) Error() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ErrEmailAlreadyUsed struct {
|
type ErrEmailAlreadyUsed struct {
|
||||||
args errutil.Args
|
args errx.Args
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsErrEmailAlreadyUsed returns true if the underlying error has the type
|
// IsErrEmailAlreadyUsed returns true if the underlying error has the type
|
||||||
@@ -297,7 +297,7 @@ func (s *UsersStore) Create(ctx context.Context, username, email string, opts Cr
|
|||||||
|
|
||||||
if s.IsUsernameUsed(ctx, username, 0) {
|
if s.IsUsernameUsed(ctx, username, 0) {
|
||||||
return nil, ErrUserAlreadyExist{
|
return nil, ErrUserAlreadyExist{
|
||||||
args: errutil.Args{
|
args: errx.Args{
|
||||||
"name": username,
|
"name": username,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -307,7 +307,7 @@ func (s *UsersStore) Create(ctx context.Context, username, email string, opts Cr
|
|||||||
_, err = s.GetByEmail(ctx, email)
|
_, err = s.GetByEmail(ctx, email)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return nil, ErrEmailAlreadyUsed{
|
return nil, ErrEmailAlreadyUsed{
|
||||||
args: errutil.Args{
|
args: errx.Args{
|
||||||
"email": email,
|
"email": email,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -328,19 +328,19 @@ func (s *UsersStore) Create(ctx context.Context, username, email string, opts Cr
|
|||||||
MaxRepoCreation: -1,
|
MaxRepoCreation: -1,
|
||||||
IsActive: opts.Activated,
|
IsActive: opts.Activated,
|
||||||
IsAdmin: opts.Admin,
|
IsAdmin: opts.Admin,
|
||||||
Avatar: cryptoutil.MD5(email), // Gravatar URL uses the MD5 hash of the email, see https://en.gravatar.com/site/implement/hash/
|
Avatar: cryptox.MD5(email), // Gravatar URL uses the MD5 hash of the email, see https://en.gravatar.com/site/implement/hash/
|
||||||
AvatarEmail: email,
|
AvatarEmail: email,
|
||||||
}
|
}
|
||||||
|
|
||||||
user.Rands, err = userutil.RandomSalt()
|
user.Rands, err = userx.RandomSalt()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
user.Salt, err = userutil.RandomSalt()
|
user.Salt, err = userx.RandomSalt()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
user.Password = userutil.EncodePassword(user.Password, user.Salt)
|
user.Password = userx.EncodePassword(user.Password, user.Salt)
|
||||||
|
|
||||||
return user, s.db.WithContext(ctx).Create(user).Error
|
return user, s.db.WithContext(ctx).Create(user).Error
|
||||||
}
|
}
|
||||||
@@ -348,7 +348,7 @@ func (s *UsersStore) Create(ctx context.Context, username, email string, opts Cr
|
|||||||
// DeleteCustomAvatar deletes the current user custom avatar and falls back to
|
// DeleteCustomAvatar deletes the current user custom avatar and falls back to
|
||||||
// use look up avatar by email.
|
// use look up avatar by email.
|
||||||
func (s *UsersStore) DeleteCustomAvatar(ctx context.Context, userID int64) error {
|
func (s *UsersStore) DeleteCustomAvatar(ctx context.Context, userID int64) error {
|
||||||
_ = os.Remove(userutil.CustomAvatarPath(userID))
|
_ = os.Remove(userx.CustomAvatarPath(userID))
|
||||||
return s.db.WithContext(ctx).
|
return s.db.WithContext(ctx).
|
||||||
Model(&User{}).
|
Model(&User{}).
|
||||||
Where("id = ?", userID).
|
Where("id = ?", userID).
|
||||||
@@ -360,7 +360,7 @@ func (s *UsersStore) DeleteCustomAvatar(ctx context.Context, userID int64) error
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ErrUserOwnRepos struct {
|
type ErrUserOwnRepos struct {
|
||||||
args errutil.Args
|
args errx.Args
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsErrUserOwnRepos returns true if the underlying error has the type
|
// IsErrUserOwnRepos returns true if the underlying error has the type
|
||||||
@@ -374,7 +374,7 @@ func (err ErrUserOwnRepos) Error() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ErrUserHasOrgs struct {
|
type ErrUserHasOrgs struct {
|
||||||
args errutil.Args
|
args errx.Args
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsErrUserHasOrgs returns true if the underlying error has the type
|
// IsErrUserHasOrgs returns true if the underlying error has the type
|
||||||
@@ -408,14 +408,14 @@ func (s *UsersStore) DeleteByID(ctx context.Context, userID int64, skipRewriteAu
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "count repositories")
|
return errors.Wrap(err, "count repositories")
|
||||||
} else if count > 0 {
|
} else if count > 0 {
|
||||||
return ErrUserOwnRepos{args: errutil.Args{"userID": userID}}
|
return ErrUserOwnRepos{args: errx.Args{"userID": userID}}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = s.db.WithContext(ctx).Model(&OrgUser{}).Where("uid = ?", userID).Count(&count).Error
|
err = s.db.WithContext(ctx).Model(&OrgUser{}).Where("uid = ?", userID).Count(&count).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "count organization membership")
|
return errors.Wrap(err, "count organization membership")
|
||||||
} else if count > 0 {
|
} else if count > 0 {
|
||||||
return ErrUserHasOrgs{args: errutil.Args{"userID": userID}}
|
return ErrUserHasOrgs{args: errx.Args{"userID": userID}}
|
||||||
}
|
}
|
||||||
|
|
||||||
needsRewriteAuthorizedKeys := false
|
needsRewriteAuthorizedKeys := false
|
||||||
@@ -542,8 +542,8 @@ func (s *UsersStore) DeleteByID(ctx context.Context, userID int64, skipRewriteAu
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = os.RemoveAll(repoutil.UserPath(user.Name))
|
_ = os.RemoveAll(repox.UserPath(user.Name))
|
||||||
_ = os.Remove(userutil.CustomAvatarPath(userID))
|
_ = os.Remove(userx.CustomAvatarPath(userID))
|
||||||
|
|
||||||
if needsRewriteAuthorizedKeys {
|
if needsRewriteAuthorizedKeys {
|
||||||
err = newPublicKeysStore(s.db).RewriteAuthorizedKeys()
|
err = newPublicKeysStore(s.db).RewriteAuthorizedKeys()
|
||||||
@@ -667,10 +667,10 @@ func (s *UsersStore) IsFollowing(ctx context.Context, userID, followID int64) bo
|
|||||||
return s.db.WithContext(ctx).Where("user_id = ? AND follow_id = ?", userID, followID).First(&Follow{}).Error == nil
|
return s.db.WithContext(ctx).Where("user_id = ? AND follow_id = ?", userID, followID).First(&Follow{}).Error == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ errutil.NotFound = (*ErrUserNotExist)(nil)
|
var _ errx.NotFound = (*ErrUserNotExist)(nil)
|
||||||
|
|
||||||
type ErrUserNotExist struct {
|
type ErrUserNotExist struct {
|
||||||
args errutil.Args
|
args errx.Args
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsErrUserNotExist returns true if the underlying error has the type
|
// IsErrUserNotExist returns true if the underlying error has the type
|
||||||
@@ -692,7 +692,7 @@ func (ErrUserNotExist) NotFound() bool {
|
|||||||
// records with unverified emails and returns ErrUserNotExist when not found.
|
// records with unverified emails and returns ErrUserNotExist when not found.
|
||||||
func (s *UsersStore) GetByEmail(ctx context.Context, email string) (*User, error) {
|
func (s *UsersStore) GetByEmail(ctx context.Context, email string) (*User, error) {
|
||||||
if email == "" {
|
if email == "" {
|
||||||
return nil, ErrUserNotExist{args: errutil.Args{"email": email}}
|
return nil, ErrUserNotExist{args: errx.Args{"email": email}}
|
||||||
}
|
}
|
||||||
email = strings.ToLower(email)
|
email = strings.ToLower(email)
|
||||||
|
|
||||||
@@ -710,17 +710,17 @@ func (s *UsersStore) GetByEmail(ctx context.Context, email string) (*User, error
|
|||||||
*/
|
*/
|
||||||
user := new(User)
|
user := new(User)
|
||||||
err := s.db.WithContext(ctx).
|
err := s.db.WithContext(ctx).
|
||||||
Joins(dbutil.Quote("LEFT JOIN email_address ON email_address.uid = %s.id", "user"), true).
|
Joins(dbx.Quote("LEFT JOIN email_address ON email_address.uid = %s.id", "user"), true).
|
||||||
Where(dbutil.Quote("%s.type = ?", "user"), UserTypeIndividual).
|
Where(dbx.Quote("%s.type = ?", "user"), UserTypeIndividual).
|
||||||
Where(s.db.
|
Where(s.db.
|
||||||
Where(dbutil.Quote("%[1]s.email = ? AND %[1]s.is_active = ?", "user"), email, true).
|
Where(dbx.Quote("%[1]s.email = ? AND %[1]s.is_active = ?", "user"), email, true).
|
||||||
Or("email_address.email = ? AND email_address.is_activated = ?", email, true),
|
Or("email_address.email = ? AND email_address.is_activated = ?", email, true),
|
||||||
).
|
).
|
||||||
First(&user).
|
First(&user).
|
||||||
Error
|
Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
return nil, ErrUserNotExist{args: errutil.Args{"email": email}}
|
return nil, ErrUserNotExist{args: errx.Args{"email": email}}
|
||||||
}
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -734,7 +734,7 @@ func (s *UsersStore) GetByID(ctx context.Context, id int64) (*User, error) {
|
|||||||
err := s.db.WithContext(ctx).Where("id = ?", id).First(user).Error
|
err := s.db.WithContext(ctx).Where("id = ?", id).First(user).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
return nil, ErrUserNotExist{args: errutil.Args{"userID": id}}
|
return nil, ErrUserNotExist{args: errx.Args{"userID": id}}
|
||||||
}
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -748,7 +748,7 @@ func (s *UsersStore) GetByUsername(ctx context.Context, username string) (*User,
|
|||||||
err := s.db.WithContext(ctx).Where("lower_name = ?", strings.ToLower(username)).First(user).Error
|
err := s.db.WithContext(ctx).Where("lower_name = ?", strings.ToLower(username)).First(user).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
return nil, ErrUserNotExist{args: errutil.Args{"name": username}}
|
return nil, ErrUserNotExist{args: errx.Args{"name": username}}
|
||||||
}
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -760,13 +760,13 @@ func (s *UsersStore) GetByUsername(ctx context.Context, username string) (*User,
|
|||||||
func (s *UsersStore) GetByKeyID(ctx context.Context, keyID int64) (*User, error) {
|
func (s *UsersStore) GetByKeyID(ctx context.Context, keyID int64) (*User, error) {
|
||||||
user := new(User)
|
user := new(User)
|
||||||
err := s.db.WithContext(ctx).
|
err := s.db.WithContext(ctx).
|
||||||
Joins(dbutil.Quote("JOIN public_key ON public_key.owner_id = %s.id", "user")).
|
Joins(dbx.Quote("JOIN public_key ON public_key.owner_id = %s.id", "user")).
|
||||||
Where("public_key.id = ?", keyID).
|
Where("public_key.id = ?", keyID).
|
||||||
First(user).
|
First(user).
|
||||||
Error
|
Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
return nil, ErrUserNotExist{args: errutil.Args{"keyID": keyID}}
|
return nil, ErrUserNotExist{args: errx.Args{"keyID": keyID}}
|
||||||
}
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -826,7 +826,7 @@ func (s *UsersStore) ListFollowers(ctx context.Context, userID int64, page, page
|
|||||||
*/
|
*/
|
||||||
users := make([]*User, 0, pageSize)
|
users := make([]*User, 0, pageSize)
|
||||||
return users, s.db.WithContext(ctx).
|
return users, s.db.WithContext(ctx).
|
||||||
Joins(dbutil.Quote("LEFT JOIN follow ON follow.user_id = %s.id", "user")).
|
Joins(dbx.Quote("LEFT JOIN follow ON follow.user_id = %s.id", "user")).
|
||||||
Where("follow.follow_id = ?", userID).
|
Where("follow.follow_id = ?", userID).
|
||||||
Limit(pageSize).Offset((page - 1) * pageSize).
|
Limit(pageSize).Offset((page - 1) * pageSize).
|
||||||
Order("follow.id DESC").
|
Order("follow.id DESC").
|
||||||
@@ -849,7 +849,7 @@ func (s *UsersStore) ListFollowings(ctx context.Context, userID int64, page, pag
|
|||||||
*/
|
*/
|
||||||
users := make([]*User, 0, pageSize)
|
users := make([]*User, 0, pageSize)
|
||||||
return users, s.db.WithContext(ctx).
|
return users, s.db.WithContext(ctx).
|
||||||
Joins(dbutil.Quote("LEFT JOIN follow ON follow.follow_id = %s.id", "user")).
|
Joins(dbx.Quote("LEFT JOIN follow ON follow.follow_id = %s.id", "user")).
|
||||||
Where("follow.user_id = ?", userID).
|
Where("follow.user_id = ?", userID).
|
||||||
Limit(pageSize).Offset((page - 1) * pageSize).
|
Limit(pageSize).Offset((page - 1) * pageSize).
|
||||||
Order("follow.id DESC").
|
Order("follow.id DESC").
|
||||||
@@ -926,16 +926,16 @@ func (s *UsersStore) Update(ctx context.Context, userID int64, opts UpdateUserOp
|
|||||||
}
|
}
|
||||||
|
|
||||||
if opts.Password != nil {
|
if opts.Password != nil {
|
||||||
salt, err := userutil.RandomSalt()
|
salt, err := userx.RandomSalt()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "generate salt")
|
return errors.Wrap(err, "generate salt")
|
||||||
}
|
}
|
||||||
updates["salt"] = salt
|
updates["salt"] = salt
|
||||||
updates["passwd"] = userutil.EncodePassword(*opts.Password, salt)
|
updates["passwd"] = userx.EncodePassword(*opts.Password, salt)
|
||||||
opts.GenerateNewRands = true
|
opts.GenerateNewRands = true
|
||||||
}
|
}
|
||||||
if opts.GenerateNewRands {
|
if opts.GenerateNewRands {
|
||||||
rands, err := userutil.RandomSalt()
|
rands, err := userx.RandomSalt()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "generate rands")
|
return errors.Wrap(err, "generate rands")
|
||||||
}
|
}
|
||||||
@@ -943,25 +943,25 @@ func (s *UsersStore) Update(ctx context.Context, userID int64, opts UpdateUserOp
|
|||||||
}
|
}
|
||||||
|
|
||||||
if opts.FullName != nil {
|
if opts.FullName != nil {
|
||||||
updates["full_name"] = strutil.Truncate(*opts.FullName, 255)
|
updates["full_name"] = strx.Truncate(*opts.FullName, 255)
|
||||||
}
|
}
|
||||||
if opts.Email != nil {
|
if opts.Email != nil {
|
||||||
_, err := s.GetByEmail(ctx, *opts.Email)
|
_, err := s.GetByEmail(ctx, *opts.Email)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return ErrEmailAlreadyUsed{args: errutil.Args{"email": *opts.Email}}
|
return ErrEmailAlreadyUsed{args: errx.Args{"email": *opts.Email}}
|
||||||
} else if !IsErrUserNotExist(err) {
|
} else if !IsErrUserNotExist(err) {
|
||||||
return errors.Wrap(err, "check email")
|
return errors.Wrap(err, "check email")
|
||||||
}
|
}
|
||||||
updates["email"] = *opts.Email
|
updates["email"] = *opts.Email
|
||||||
}
|
}
|
||||||
if opts.Website != nil {
|
if opts.Website != nil {
|
||||||
updates["website"] = strutil.Truncate(*opts.Website, 255)
|
updates["website"] = strx.Truncate(*opts.Website, 255)
|
||||||
}
|
}
|
||||||
if opts.Location != nil {
|
if opts.Location != nil {
|
||||||
updates["location"] = strutil.Truncate(*opts.Location, 255)
|
updates["location"] = strx.Truncate(*opts.Location, 255)
|
||||||
}
|
}
|
||||||
if opts.Description != nil {
|
if opts.Description != nil {
|
||||||
updates["description"] = strutil.Truncate(*opts.Description, 255)
|
updates["description"] = strx.Truncate(*opts.Description, 255)
|
||||||
}
|
}
|
||||||
|
|
||||||
if opts.MaxRepoCreation != nil {
|
if opts.MaxRepoCreation != nil {
|
||||||
@@ -991,10 +991,10 @@ func (s *UsersStore) Update(ctx context.Context, userID int64, opts UpdateUserOp
|
|||||||
}
|
}
|
||||||
|
|
||||||
if opts.Avatar != nil {
|
if opts.Avatar != nil {
|
||||||
updates["avatar"] = strutil.Truncate(*opts.Avatar, 2048)
|
updates["avatar"] = strx.Truncate(*opts.Avatar, 2048)
|
||||||
}
|
}
|
||||||
if opts.AvatarEmail != nil {
|
if opts.AvatarEmail != nil {
|
||||||
updates["avatar_email"] = strutil.Truncate(*opts.AvatarEmail, 255)
|
updates["avatar_email"] = strx.Truncate(*opts.AvatarEmail, 255)
|
||||||
}
|
}
|
||||||
|
|
||||||
return s.db.WithContext(ctx).Model(&User{}).Where("id = ?", userID).Updates(updates).Error
|
return s.db.WithContext(ctx).Model(&User{}).Where("id = ?", userID).Updates(updates).Error
|
||||||
@@ -1002,7 +1002,7 @@ func (s *UsersStore) Update(ctx context.Context, userID int64, opts UpdateUserOp
|
|||||||
|
|
||||||
// UseCustomAvatar uses the given avatar as the user custom avatar.
|
// UseCustomAvatar uses the given avatar as the user custom avatar.
|
||||||
func (s *UsersStore) UseCustomAvatar(ctx context.Context, userID int64, avatar []byte) error {
|
func (s *UsersStore) UseCustomAvatar(ctx context.Context, userID int64, avatar []byte) error {
|
||||||
err := userutil.SaveAvatar(userID, avatar)
|
err := userx.SaveAvatar(userID, avatar)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "save avatar")
|
return errors.Wrap(err, "save avatar")
|
||||||
}
|
}
|
||||||
@@ -1024,7 +1024,7 @@ func (s *UsersStore) AddEmail(ctx context.Context, userID int64, email string, i
|
|||||||
_, err := s.GetByEmail(ctx, email)
|
_, err := s.GetByEmail(ctx, email)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return ErrEmailAlreadyUsed{
|
return ErrEmailAlreadyUsed{
|
||||||
args: errutil.Args{
|
args: errx.Args{
|
||||||
"email": email,
|
"email": email,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -1041,10 +1041,10 @@ func (s *UsersStore) AddEmail(ctx context.Context, userID int64, email string, i
|
|||||||
).Error
|
).Error
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ errutil.NotFound = (*ErrEmailNotExist)(nil)
|
var _ errx.NotFound = (*ErrEmailNotExist)(nil)
|
||||||
|
|
||||||
type ErrEmailNotExist struct {
|
type ErrEmailNotExist struct {
|
||||||
args errutil.Args
|
args errx.Args
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsErrEmailAddressNotExist returns true if the underlying error has the type
|
// IsErrEmailAddressNotExist returns true if the underlying error has the type
|
||||||
@@ -1077,7 +1077,7 @@ func (s *UsersStore) GetEmail(ctx context.Context, userID int64, email string, n
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
return nil, ErrEmailNotExist{
|
return nil, ErrEmailNotExist{
|
||||||
args: errutil.Args{
|
args: errx.Args{
|
||||||
"email": email,
|
"email": email,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -1140,7 +1140,7 @@ func (s *UsersStore) MarkEmailActivated(ctx context.Context, userID int64, email
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ErrEmailNotVerified struct {
|
type ErrEmailNotVerified struct {
|
||||||
args errutil.Args
|
args errx.Args
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsErrEmailNotVerified returns true if the underlying error has the type
|
// IsErrEmailNotVerified returns true if the underlying error has the type
|
||||||
@@ -1162,13 +1162,13 @@ func (s *UsersStore) MarkEmailPrimary(ctx context.Context, userID int64, email s
|
|||||||
err := s.db.WithContext(ctx).Where("uid = ? AND email = ?", userID, email).First(&emailAddress).Error
|
err := s.db.WithContext(ctx).Where("uid = ? AND email = ?", userID, email).First(&emailAddress).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
return ErrEmailNotExist{args: errutil.Args{"email": email}}
|
return ErrEmailNotExist{args: errx.Args{"email": email}}
|
||||||
}
|
}
|
||||||
return errors.Wrap(err, "get email address")
|
return errors.Wrap(err, "get email address")
|
||||||
}
|
}
|
||||||
|
|
||||||
if !emailAddress.IsActivated {
|
if !emailAddress.IsActivated {
|
||||||
return ErrEmailNotVerified{args: errutil.Args{"email": email}}
|
return ErrEmailNotVerified{args: errx.Args{"email": email}}
|
||||||
}
|
}
|
||||||
|
|
||||||
user, err := s.GetByID(ctx, userID)
|
user, err := s.GetByID(ctx, userID)
|
||||||
@@ -1297,14 +1297,14 @@ func (u *User) IsOrganization() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// APIFormat returns the API format of a user.
|
// APIFormat returns the API format of a user.
|
||||||
func (u *User) APIFormat() *api.User {
|
func (u *User) APIFormat() *apiv1types.User {
|
||||||
return &api.User{
|
return &apiv1types.User{
|
||||||
ID: u.ID,
|
ID: u.ID,
|
||||||
UserName: u.Name,
|
UserName: u.Name,
|
||||||
Login: u.Name,
|
Login: u.Name,
|
||||||
FullName: u.FullName,
|
FullName: u.FullName,
|
||||||
Email: u.Email,
|
Email: u.Email,
|
||||||
AvatarUrl: u.AvatarURL(),
|
AvatarURL: u.AvatarURL(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1349,7 +1349,7 @@ func (u *User) DisplayName() string {
|
|||||||
// HomeURLPath returns the URL path to the user or organization home page.
|
// HomeURLPath returns the URL path to the user or organization home page.
|
||||||
//
|
//
|
||||||
// TODO(unknwon): This is also used in templates, which should be fixed by
|
// TODO(unknwon): This is also used in templates, which should be fixed by
|
||||||
// having a dedicated type `template.User` and move this to the "userutil"
|
// having a dedicated type `template.User` and move this to the "userx"
|
||||||
// package.
|
// package.
|
||||||
func (u *User) HomeURLPath() string {
|
func (u *User) HomeURLPath() string {
|
||||||
return conf.Server.Subpath + "/" + u.Name
|
return conf.Server.Subpath + "/" + u.Name
|
||||||
@@ -1358,7 +1358,7 @@ func (u *User) HomeURLPath() string {
|
|||||||
// HTMLURL returns the full URL to the user or organization home page.
|
// HTMLURL returns the full URL to the user or organization home page.
|
||||||
//
|
//
|
||||||
// TODO(unknwon): This is also used in templates, which should be fixed by
|
// TODO(unknwon): This is also used in templates, which should be fixed by
|
||||||
// having a dedicated type `template.User` and move this to the "userutil"
|
// having a dedicated type `template.User` and move this to the "userx"
|
||||||
// package.
|
// package.
|
||||||
func (u *User) HTMLURL() string {
|
func (u *User) HTMLURL() string {
|
||||||
return conf.Server.ExternalURL + u.Name
|
return conf.Server.ExternalURL + u.Name
|
||||||
@@ -1368,7 +1368,7 @@ func (u *User) HTMLURL() string {
|
|||||||
// user enables Gravatar-like service, then an external URL will be returned.
|
// user enables Gravatar-like service, then an external URL will be returned.
|
||||||
//
|
//
|
||||||
// TODO(unknwon): This is also used in templates, which should be fixed by
|
// TODO(unknwon): This is also used in templates, which should be fixed by
|
||||||
// having a dedicated type `template.User` and move this to the "userutil"
|
// having a dedicated type `template.User` and move this to the "userx"
|
||||||
// package.
|
// package.
|
||||||
func (u *User) AvatarURLPath() string {
|
func (u *User) AvatarURLPath() string {
|
||||||
defaultURLPath := conf.UserDefaultAvatarURLPath()
|
defaultURLPath := conf.UserDefaultAvatarURLPath()
|
||||||
@@ -1376,7 +1376,7 @@ func (u *User) AvatarURLPath() string {
|
|||||||
return defaultURLPath
|
return defaultURLPath
|
||||||
}
|
}
|
||||||
|
|
||||||
hasCustomAvatar := osutil.IsFile(userutil.CustomAvatarPath(u.ID))
|
hasCustomAvatar := osx.IsFile(userx.CustomAvatarPath(u.ID))
|
||||||
switch {
|
switch {
|
||||||
case u.UseCustomAvatar:
|
case u.UseCustomAvatar:
|
||||||
if !hasCustomAvatar {
|
if !hasCustomAvatar {
|
||||||
@@ -1385,7 +1385,7 @@ func (u *User) AvatarURLPath() string {
|
|||||||
return fmt.Sprintf("%s/%s/%d", conf.Server.Subpath, conf.UsersAvatarPathPrefix, u.ID)
|
return fmt.Sprintf("%s/%s/%d", conf.Server.Subpath, conf.UsersAvatarPathPrefix, u.ID)
|
||||||
case conf.Picture.DisableGravatar:
|
case conf.Picture.DisableGravatar:
|
||||||
if !hasCustomAvatar {
|
if !hasCustomAvatar {
|
||||||
if err := userutil.GenerateRandomAvatar(u.ID, u.Name, u.Email); err != nil {
|
if err := userx.GenerateRandomAvatar(u.ID, u.Name, u.Email); err != nil {
|
||||||
log.Error("Failed to generate random avatar [user_id: %d]: %v", u.ID, err)
|
log.Error("Failed to generate random avatar [user_id: %d]: %v", u.ID, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1398,7 +1398,7 @@ func (u *User) AvatarURLPath() string {
|
|||||||
// user enables Gravatar-like service, then an external URL will be returned.
|
// user enables Gravatar-like service, then an external URL will be returned.
|
||||||
//
|
//
|
||||||
// TODO(unknwon): This is also used in templates, which should be fixed by
|
// TODO(unknwon): This is also used in templates, which should be fixed by
|
||||||
// having a dedicated type `template.User` and move this to the "userutil"
|
// having a dedicated type `template.User` and move this to the "userx"
|
||||||
// package.
|
// package.
|
||||||
func (u *User) AvatarURL() string {
|
func (u *User) AvatarURL() string {
|
||||||
link := u.AvatarURLPath()
|
link := u.AvatarURLPath()
|
||||||
@@ -1448,7 +1448,7 @@ func (u *User) GetOrganizationCount() (int64, error) {
|
|||||||
// TODO(unknwon): This is also used in templates, which should be fixed by
|
// TODO(unknwon): This is also used in templates, which should be fixed by
|
||||||
// having a dedicated type `template.User`.
|
// having a dedicated type `template.User`.
|
||||||
func (u *User) ShortName(length int) string {
|
func (u *User) ShortName(length int) string {
|
||||||
return strutil.Ellipsis(u.Name, length)
|
return strx.Ellipsis(u.Name, length)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewGhostUser creates and returns a fake user for people who has deleted their
|
// NewGhostUser creates and returns a fake user for people who has deleted their
|
||||||
@@ -1498,7 +1498,7 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type ErrNameNotAllowed struct {
|
type ErrNameNotAllowed struct {
|
||||||
args errutil.Args
|
args errx.Args
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsErrNameNotAllowed returns true if the underlying error has the type
|
// IsErrNameNotAllowed returns true if the underlying error has the type
|
||||||
@@ -1533,7 +1533,7 @@ func isNameAllowed(names map[string]struct{}, patterns []string, name string) er
|
|||||||
name = strings.TrimSpace(strings.ToLower(name))
|
name = strings.TrimSpace(strings.ToLower(name))
|
||||||
if utf8.RuneCountInString(name) == 0 {
|
if utf8.RuneCountInString(name) == 0 {
|
||||||
return ErrNameNotAllowed{
|
return ErrNameNotAllowed{
|
||||||
args: errutil.Args{
|
args: errx.Args{
|
||||||
"reason": "empty name",
|
"reason": "empty name",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -1541,7 +1541,7 @@ func isNameAllowed(names map[string]struct{}, patterns []string, name string) er
|
|||||||
|
|
||||||
if _, ok := names[name]; ok {
|
if _, ok := names[name]; ok {
|
||||||
return ErrNameNotAllowed{
|
return ErrNameNotAllowed{
|
||||||
args: errutil.Args{
|
args: errx.Args{
|
||||||
"reason": "reserved",
|
"reason": "reserved",
|
||||||
"name": name,
|
"name": name,
|
||||||
},
|
},
|
||||||
@@ -1552,7 +1552,7 @@ func isNameAllowed(names map[string]struct{}, patterns []string, name string) er
|
|||||||
if pattern[0] == '*' && strings.HasSuffix(name, pattern[1:]) ||
|
if pattern[0] == '*' && strings.HasSuffix(name, pattern[1:]) ||
|
||||||
(pattern[len(pattern)-1] == '*' && strings.HasPrefix(name, pattern[:len(pattern)-1])) {
|
(pattern[len(pattern)-1] == '*' && strings.HasPrefix(name, pattern[:len(pattern)-1])) {
|
||||||
return ErrNameNotAllowed{
|
return ErrNameNotAllowed{
|
||||||
args: errutil.Args{
|
args: errx.Args{
|
||||||
"reason": "reserved",
|
"reason": "reserved",
|
||||||
"pattern": pattern,
|
"pattern": pattern,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -15,11 +15,11 @@ import (
|
|||||||
|
|
||||||
"gogs.io/gogs/internal/auth"
|
"gogs.io/gogs/internal/auth"
|
||||||
"gogs.io/gogs/internal/conf"
|
"gogs.io/gogs/internal/conf"
|
||||||
"gogs.io/gogs/internal/dbutil"
|
"gogs.io/gogs/internal/dbx"
|
||||||
"gogs.io/gogs/internal/errutil"
|
"gogs.io/gogs/internal/errx"
|
||||||
"gogs.io/gogs/internal/osutil"
|
"gogs.io/gogs/internal/osx"
|
||||||
"gogs.io/gogs/internal/repoutil"
|
"gogs.io/gogs/internal/repox"
|
||||||
"gogs.io/gogs/internal/userutil"
|
"gogs.io/gogs/internal/userx"
|
||||||
"gogs.io/gogs/public"
|
"gogs.io/gogs/public"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -240,7 +240,7 @@ func usersChangeUsername(t *testing.T, ctx context.Context, s *UsersStore) {
|
|||||||
t.Run("name not allowed", func(t *testing.T) {
|
t.Run("name not allowed", func(t *testing.T) {
|
||||||
err := s.ChangeUsername(ctx, alice.ID, "-")
|
err := s.ChangeUsername(ctx, alice.ID, "-")
|
||||||
wantErr := ErrNameNotAllowed{
|
wantErr := ErrNameNotAllowed{
|
||||||
args: errutil.Args{
|
args: errx.Args{
|
||||||
"reason": "reserved",
|
"reason": "reserved",
|
||||||
"name": "-",
|
"name": "-",
|
||||||
},
|
},
|
||||||
@@ -261,7 +261,7 @@ func usersChangeUsername(t *testing.T, ctx context.Context, s *UsersStore) {
|
|||||||
|
|
||||||
err = s.ChangeUsername(ctx, alice.ID, bob.Name)
|
err = s.ChangeUsername(ctx, alice.ID, bob.Name)
|
||||||
wantErr := ErrUserAlreadyExist{
|
wantErr := ErrUserAlreadyExist{
|
||||||
args: errutil.Args{
|
args: errx.Args{
|
||||||
"name": bob.Name,
|
"name": bob.Name,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -306,11 +306,11 @@ func usersChangeUsername(t *testing.T, ctx context.Context, s *UsersStore) {
|
|||||||
err = s.db.Model(&User{}).Where("id = ?", alice.ID).Update("updated_unix", 0).Error
|
err = s.db.Model(&User{}).Where("id = ?", alice.ID).Update("updated_unix", 0).Error
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
err = os.MkdirAll(repoutil.UserPath(alice.Name), os.ModePerm)
|
err = os.MkdirAll(repox.UserPath(alice.Name), os.ModePerm)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
err = os.MkdirAll(repoutil.RepositoryLocalPath(repo.ID), os.ModePerm)
|
err = os.MkdirAll(repox.RepositoryLocalPath(repo.ID), os.ModePerm)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
err = os.MkdirAll(repoutil.RepositoryLocalWikiPath(repo.ID), os.ModePerm)
|
err = os.MkdirAll(repox.RepositoryLocalWikiPath(repo.ID), os.ModePerm)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// Make sure mock data is set up correctly
|
// Make sure mock data is set up correctly
|
||||||
@@ -325,9 +325,9 @@ func usersChangeUsername(t *testing.T, ctx context.Context, s *UsersStore) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, int64(0), updatedUnix)
|
assert.Equal(t, int64(0), updatedUnix)
|
||||||
|
|
||||||
assert.True(t, osutil.Exist(repoutil.UserPath(alice.Name)))
|
assert.True(t, osx.Exist(repox.UserPath(alice.Name)))
|
||||||
assert.True(t, osutil.Exist(repoutil.RepositoryLocalPath(repo.ID)))
|
assert.True(t, osx.Exist(repox.RepositoryLocalPath(repo.ID)))
|
||||||
assert.True(t, osutil.Exist(repoutil.RepositoryLocalWikiPath(repo.ID)))
|
assert.True(t, osx.Exist(repox.RepositoryLocalWikiPath(repo.ID)))
|
||||||
|
|
||||||
const newUsername = "alice-new"
|
const newUsername = "alice-new"
|
||||||
err = s.ChangeUsername(ctx, alice.ID, newUsername)
|
err = s.ChangeUsername(ctx, alice.ID, newUsername)
|
||||||
@@ -338,10 +338,10 @@ func usersChangeUsername(t *testing.T, ctx context.Context, s *UsersStore) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, headUserName, newUsername)
|
assert.Equal(t, headUserName, newUsername)
|
||||||
|
|
||||||
assert.True(t, osutil.Exist(repoutil.UserPath(newUsername)))
|
assert.True(t, osx.Exist(repox.UserPath(newUsername)))
|
||||||
assert.False(t, osutil.Exist(repoutil.UserPath(alice.Name)))
|
assert.False(t, osx.Exist(repox.UserPath(alice.Name)))
|
||||||
assert.False(t, osutil.Exist(repoutil.RepositoryLocalPath(repo.ID)))
|
assert.False(t, osx.Exist(repox.RepositoryLocalPath(repo.ID)))
|
||||||
assert.False(t, osutil.Exist(repoutil.RepositoryLocalWikiPath(repo.ID)))
|
assert.False(t, osx.Exist(repox.RepositoryLocalWikiPath(repo.ID)))
|
||||||
|
|
||||||
alice, err = s.GetByID(ctx, alice.ID)
|
alice, err = s.GetByID(ctx, alice.ID)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@@ -371,7 +371,7 @@ func usersCount(t *testing.T, ctx context.Context, s *UsersStore) {
|
|||||||
org1, err := s.Create(ctx, "org1", "org1@example.com", CreateUserOptions{})
|
org1, err := s.Create(ctx, "org1", "org1@example.com", CreateUserOptions{})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
err = s.db.Exec(
|
err = s.db.Exec(
|
||||||
dbutil.Quote("UPDATE %s SET type = ? WHERE id = ?", "user"),
|
dbx.Quote("UPDATE %s SET type = ? WHERE id = ?", "user"),
|
||||||
UserTypeOrganization, org1.ID,
|
UserTypeOrganization, org1.ID,
|
||||||
).Error
|
).Error
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@@ -393,7 +393,7 @@ func usersCreate(t *testing.T, ctx context.Context, s *UsersStore) {
|
|||||||
t.Run("name not allowed", func(t *testing.T) {
|
t.Run("name not allowed", func(t *testing.T) {
|
||||||
_, err := s.Create(ctx, "-", "", CreateUserOptions{})
|
_, err := s.Create(ctx, "-", "", CreateUserOptions{})
|
||||||
wantErr := ErrNameNotAllowed{
|
wantErr := ErrNameNotAllowed{
|
||||||
args: errutil.Args{
|
args: errx.Args{
|
||||||
"reason": "reserved",
|
"reason": "reserved",
|
||||||
"name": "-",
|
"name": "-",
|
||||||
},
|
},
|
||||||
@@ -404,7 +404,7 @@ func usersCreate(t *testing.T, ctx context.Context, s *UsersStore) {
|
|||||||
t.Run("name already exists", func(t *testing.T) {
|
t.Run("name already exists", func(t *testing.T) {
|
||||||
_, err := s.Create(ctx, alice.Name, "", CreateUserOptions{})
|
_, err := s.Create(ctx, alice.Name, "", CreateUserOptions{})
|
||||||
wantErr := ErrUserAlreadyExist{
|
wantErr := ErrUserAlreadyExist{
|
||||||
args: errutil.Args{
|
args: errx.Args{
|
||||||
"name": alice.Name,
|
"name": alice.Name,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -414,7 +414,7 @@ func usersCreate(t *testing.T, ctx context.Context, s *UsersStore) {
|
|||||||
t.Run("email already exists", func(t *testing.T) {
|
t.Run("email already exists", func(t *testing.T) {
|
||||||
_, err := s.Create(ctx, "bob", alice.Email, CreateUserOptions{})
|
_, err := s.Create(ctx, "bob", alice.Email, CreateUserOptions{})
|
||||||
wantErr := ErrEmailAlreadyUsed{
|
wantErr := ErrEmailAlreadyUsed{
|
||||||
args: errutil.Args{
|
args: errx.Args{
|
||||||
"email": alice.Email,
|
"email": alice.Email,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -434,7 +434,7 @@ func usersDeleteCustomAvatar(t *testing.T, ctx context.Context, s *UsersStore) {
|
|||||||
avatar, err := public.Files.ReadFile("img/avatar_default.png")
|
avatar, err := public.Files.ReadFile("img/avatar_default.png")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
avatarPath := userutil.CustomAvatarPath(alice.ID)
|
avatarPath := userx.CustomAvatarPath(alice.ID)
|
||||||
_ = os.Remove(avatarPath)
|
_ = os.Remove(avatarPath)
|
||||||
defer func() { _ = os.Remove(avatarPath) }()
|
defer func() { _ = os.Remove(avatarPath) }()
|
||||||
|
|
||||||
@@ -442,7 +442,7 @@ func usersDeleteCustomAvatar(t *testing.T, ctx context.Context, s *UsersStore) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// Make sure avatar is saved and the user flag is updated.
|
// Make sure avatar is saved and the user flag is updated.
|
||||||
got := osutil.IsFile(avatarPath)
|
got := osx.IsFile(avatarPath)
|
||||||
assert.True(t, got)
|
assert.True(t, got)
|
||||||
|
|
||||||
alice, err = s.GetByID(ctx, alice.ID)
|
alice, err = s.GetByID(ctx, alice.ID)
|
||||||
@@ -453,7 +453,7 @@ func usersDeleteCustomAvatar(t *testing.T, ctx context.Context, s *UsersStore) {
|
|||||||
err = s.DeleteCustomAvatar(ctx, alice.ID)
|
err = s.DeleteCustomAvatar(ctx, alice.ID)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
got = osutil.IsFile(avatarPath)
|
got = osx.IsFile(avatarPath)
|
||||||
assert.False(t, got)
|
assert.False(t, got)
|
||||||
|
|
||||||
alice, err = s.GetByID(ctx, alice.ID)
|
alice, err = s.GetByID(ctx, alice.ID)
|
||||||
@@ -472,7 +472,7 @@ func usersDeleteByID(t *testing.T, ctx context.Context, s *UsersStore) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
err = s.DeleteByID(ctx, alice.ID, false)
|
err = s.DeleteByID(ctx, alice.ID, false)
|
||||||
wantErr := ErrUserOwnRepos{errutil.Args{"userID": alice.ID}}
|
wantErr := ErrUserOwnRepos{errx.Args{"userID": alice.ID}}
|
||||||
assert.Equal(t, wantErr, err)
|
assert.Equal(t, wantErr, err)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -484,7 +484,7 @@ func usersDeleteByID(t *testing.T, ctx context.Context, s *UsersStore) {
|
|||||||
org1, err := s.Create(ctx, "org1", "org1@example.com", CreateUserOptions{})
|
org1, err := s.Create(ctx, "org1", "org1@example.com", CreateUserOptions{})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
err = s.db.Exec(
|
err = s.db.Exec(
|
||||||
dbutil.Quote("UPDATE %s SET type = ? WHERE id IN (?)", "user"),
|
dbx.Quote("UPDATE %s SET type = ? WHERE id IN (?)", "user"),
|
||||||
UserTypeOrganization, org1.ID,
|
UserTypeOrganization, org1.ID,
|
||||||
).Error
|
).Error
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@@ -494,7 +494,7 @@ func usersDeleteByID(t *testing.T, ctx context.Context, s *UsersStore) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
err = s.DeleteByID(ctx, bob.ID, false)
|
err = s.DeleteByID(ctx, bob.ID, false)
|
||||||
wantErr := ErrUserHasOrgs{errutil.Args{"userID": bob.ID}}
|
wantErr := ErrUserHasOrgs{errx.Args{"userID": bob.ID}}
|
||||||
assert.Equal(t, wantErr, err)
|
assert.Equal(t, wantErr, err)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -561,7 +561,7 @@ func usersDeleteByID(t *testing.T, ctx context.Context, s *UsersStore) {
|
|||||||
// Mock user directory
|
// Mock user directory
|
||||||
tempRepositoryRoot := filepath.Join(os.TempDir(), "usersDeleteByID-tempRepositoryRoot")
|
tempRepositoryRoot := filepath.Join(os.TempDir(), "usersDeleteByID-tempRepositoryRoot")
|
||||||
conf.SetMockRepository(t, conf.RepositoryOpts{Root: tempRepositoryRoot})
|
conf.SetMockRepository(t, conf.RepositoryOpts{Root: tempRepositoryRoot})
|
||||||
tempUserPath := repoutil.UserPath(testUser.Name)
|
tempUserPath := repox.UserPath(testUser.Name)
|
||||||
err = os.MkdirAll(tempUserPath, os.ModePerm)
|
err = os.MkdirAll(tempUserPath, os.ModePerm)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
@@ -570,7 +570,7 @@ func usersDeleteByID(t *testing.T, ctx context.Context, s *UsersStore) {
|
|||||||
conf.SetMockPicture(t, conf.PictureOpts{AvatarUploadPath: tempPictureAvatarUploadPath})
|
conf.SetMockPicture(t, conf.PictureOpts{AvatarUploadPath: tempPictureAvatarUploadPath})
|
||||||
err = os.MkdirAll(tempPictureAvatarUploadPath, os.ModePerm)
|
err = os.MkdirAll(tempPictureAvatarUploadPath, os.ModePerm)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
tempCustomAvatarPath := userutil.CustomAvatarPath(testUser.ID)
|
tempCustomAvatarPath := userx.CustomAvatarPath(testUser.ID)
|
||||||
err = os.WriteFile(tempCustomAvatarPath, []byte("test"), 0o600)
|
err = os.WriteFile(tempCustomAvatarPath, []byte("test"), 0o600)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
@@ -616,8 +616,8 @@ func usersDeleteByID(t *testing.T, ctx context.Context, s *UsersStore) {
|
|||||||
assert.NotZero(t, count, "table for %T", table)
|
assert.NotZero(t, count, "table for %T", table)
|
||||||
}
|
}
|
||||||
|
|
||||||
assert.True(t, osutil.Exist(tempUserPath))
|
assert.True(t, osx.Exist(tempUserPath))
|
||||||
assert.True(t, osutil.Exist(tempCustomAvatarPath))
|
assert.True(t, osx.Exist(tempCustomAvatarPath))
|
||||||
|
|
||||||
// Pull the trigger
|
// Pull the trigger
|
||||||
err = s.DeleteByID(ctx, testUser.ID, false)
|
err = s.DeleteByID(ctx, testUser.ID, false)
|
||||||
@@ -663,11 +663,11 @@ func usersDeleteByID(t *testing.T, ctx context.Context, s *UsersStore) {
|
|||||||
assert.Equal(t, int64(0), count, "table for %T", table)
|
assert.Equal(t, int64(0), count, "table for %T", table)
|
||||||
}
|
}
|
||||||
|
|
||||||
assert.False(t, osutil.Exist(tempUserPath))
|
assert.False(t, osx.Exist(tempUserPath))
|
||||||
assert.False(t, osutil.Exist(tempCustomAvatarPath))
|
assert.False(t, osx.Exist(tempCustomAvatarPath))
|
||||||
|
|
||||||
_, err = s.GetByID(ctx, testUser.ID)
|
_, err = s.GetByID(ctx, testUser.ID)
|
||||||
wantErr := ErrUserNotExist{errutil.Args{"userID": testUser.ID}}
|
wantErr := ErrUserNotExist{errx.Args{"userID": testUser.ID}}
|
||||||
assert.Equal(t, wantErr, err)
|
assert.Equal(t, wantErr, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -686,7 +686,7 @@ func usersDeleteInactivated(t *testing.T, ctx context.Context, s *UsersStore) {
|
|||||||
org1, err := s.Create(ctx, "org1", "org1@example.com", CreateUserOptions{})
|
org1, err := s.Create(ctx, "org1", "org1@example.com", CreateUserOptions{})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
err = s.db.Exec(
|
err = s.db.Exec(
|
||||||
dbutil.Quote("UPDATE %s SET type = ? WHERE id IN (?)", "user"),
|
dbx.Quote("UPDATE %s SET type = ? WHERE id IN (?)", "user"),
|
||||||
UserTypeOrganization, org1.ID,
|
UserTypeOrganization, org1.ID,
|
||||||
).Error
|
).Error
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@@ -709,7 +709,7 @@ func usersDeleteInactivated(t *testing.T, ctx context.Context, s *UsersStore) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
_, err = s.GetByID(ctx, david.ID)
|
_, err = s.GetByID(ctx, david.ID)
|
||||||
wantErr := ErrUserNotExist{errutil.Args{"userID": david.ID}}
|
wantErr := ErrUserNotExist{errx.Args{"userID": david.ID}}
|
||||||
assert.Equal(t, wantErr, err)
|
assert.Equal(t, wantErr, err)
|
||||||
|
|
||||||
users, err := s.List(ctx, 1, 10)
|
users, err := s.List(ctx, 1, 10)
|
||||||
@@ -720,7 +720,7 @@ func usersDeleteInactivated(t *testing.T, ctx context.Context, s *UsersStore) {
|
|||||||
func usersGetByEmail(t *testing.T, ctx context.Context, s *UsersStore) {
|
func usersGetByEmail(t *testing.T, ctx context.Context, s *UsersStore) {
|
||||||
t.Run("empty email", func(t *testing.T) {
|
t.Run("empty email", func(t *testing.T) {
|
||||||
_, err := s.GetByEmail(ctx, "")
|
_, err := s.GetByEmail(ctx, "")
|
||||||
wantErr := ErrUserNotExist{args: errutil.Args{"email": ""}}
|
wantErr := ErrUserNotExist{args: errx.Args{"email": ""}}
|
||||||
assert.Equal(t, wantErr, err)
|
assert.Equal(t, wantErr, err)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -733,7 +733,7 @@ func usersGetByEmail(t *testing.T, ctx context.Context, s *UsersStore) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
_, err = s.GetByEmail(ctx, org.Email)
|
_, err = s.GetByEmail(ctx, org.Email)
|
||||||
wantErr := ErrUserNotExist{args: errutil.Args{"email": org.Email}}
|
wantErr := ErrUserNotExist{args: errx.Args{"email": org.Email}}
|
||||||
assert.Equal(t, wantErr, err)
|
assert.Equal(t, wantErr, err)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -742,7 +742,7 @@ func usersGetByEmail(t *testing.T, ctx context.Context, s *UsersStore) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
_, err = s.GetByEmail(ctx, alice.Email)
|
_, err = s.GetByEmail(ctx, alice.Email)
|
||||||
wantErr := ErrUserNotExist{args: errutil.Args{"email": alice.Email}}
|
wantErr := ErrUserNotExist{args: errx.Args{"email": alice.Email}}
|
||||||
assert.Equal(t, wantErr, err)
|
assert.Equal(t, wantErr, err)
|
||||||
|
|
||||||
// Mark user as activated
|
// Mark user as activated
|
||||||
@@ -765,7 +765,7 @@ func usersGetByEmail(t *testing.T, ctx context.Context, s *UsersStore) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
_, err = s.GetByEmail(ctx, email2)
|
_, err = s.GetByEmail(ctx, email2)
|
||||||
wantErr := ErrUserNotExist{args: errutil.Args{"email": email2}}
|
wantErr := ErrUserNotExist{args: errx.Args{"email": email2}}
|
||||||
assert.Equal(t, wantErr, err)
|
assert.Equal(t, wantErr, err)
|
||||||
|
|
||||||
// TODO: Use UserEmails.Verify to replace SQL hack when the method is available.
|
// TODO: Use UserEmails.Verify to replace SQL hack when the method is available.
|
||||||
@@ -787,7 +787,7 @@ func usersGetByID(t *testing.T, ctx context.Context, s *UsersStore) {
|
|||||||
assert.Equal(t, alice.Name, user.Name)
|
assert.Equal(t, alice.Name, user.Name)
|
||||||
|
|
||||||
_, err = s.GetByID(ctx, 404)
|
_, err = s.GetByID(ctx, 404)
|
||||||
wantErr := ErrUserNotExist{args: errutil.Args{"userID": int64(404)}}
|
wantErr := ErrUserNotExist{args: errx.Args{"userID": int64(404)}}
|
||||||
assert.Equal(t, wantErr, err)
|
assert.Equal(t, wantErr, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -800,7 +800,7 @@ func usersGetByUsername(t *testing.T, ctx context.Context, s *UsersStore) {
|
|||||||
assert.Equal(t, alice.Name, user.Name)
|
assert.Equal(t, alice.Name, user.Name)
|
||||||
|
|
||||||
_, err = s.GetByUsername(ctx, "bad_username")
|
_, err = s.GetByUsername(ctx, "bad_username")
|
||||||
wantErr := ErrUserNotExist{args: errutil.Args{"name": "bad_username"}}
|
wantErr := ErrUserNotExist{args: errx.Args{"name": "bad_username"}}
|
||||||
assert.Equal(t, wantErr, err)
|
assert.Equal(t, wantErr, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -825,7 +825,7 @@ func usersGetByKeyID(t *testing.T, ctx context.Context, s *UsersStore) {
|
|||||||
assert.Equal(t, alice.Name, user.Name)
|
assert.Equal(t, alice.Name, user.Name)
|
||||||
|
|
||||||
_, err = s.GetByKeyID(ctx, publicKey.ID+1)
|
_, err = s.GetByKeyID(ctx, publicKey.ID+1)
|
||||||
wantErr := ErrUserNotExist{args: errutil.Args{"keyID": publicKey.ID + 1}}
|
wantErr := ErrUserNotExist{args: errx.Args{"keyID": publicKey.ID + 1}}
|
||||||
assert.Equal(t, wantErr, err)
|
assert.Equal(t, wantErr, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -904,7 +904,7 @@ func usersList(t *testing.T, ctx context.Context, s *UsersStore) {
|
|||||||
org1, err := s.Create(ctx, "org1", "org1@example.com", CreateUserOptions{})
|
org1, err := s.Create(ctx, "org1", "org1@example.com", CreateUserOptions{})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
err = s.db.Exec(
|
err = s.db.Exec(
|
||||||
dbutil.Quote("UPDATE %s SET type = ? WHERE id = ?", "user"),
|
dbx.Quote("UPDATE %s SET type = ? WHERE id = ?", "user"),
|
||||||
UserTypeOrganization, org1.ID,
|
UserTypeOrganization, org1.ID,
|
||||||
).Error
|
).Error
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@@ -1046,7 +1046,7 @@ func usersUpdate(t *testing.T, ctx context.Context, s *UsersStore) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
t.Run("update password", func(t *testing.T) {
|
t.Run("update password", func(t *testing.T) {
|
||||||
got := userutil.ValidatePassword(alice.Password, alice.Salt, oldPassword)
|
got := userx.ValidatePassword(alice.Password, alice.Salt, oldPassword)
|
||||||
require.True(t, got)
|
require.True(t, got)
|
||||||
|
|
||||||
newPassword := "NewPassword"
|
newPassword := "NewPassword"
|
||||||
@@ -1055,10 +1055,10 @@ func usersUpdate(t *testing.T, ctx context.Context, s *UsersStore) {
|
|||||||
alice, err = s.GetByID(ctx, alice.ID)
|
alice, err = s.GetByID(ctx, alice.ID)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
got = userutil.ValidatePassword(alice.Password, alice.Salt, oldPassword)
|
got = userx.ValidatePassword(alice.Password, alice.Salt, oldPassword)
|
||||||
assert.False(t, got, "Old password should stop working")
|
assert.False(t, got, "Old password should stop working")
|
||||||
|
|
||||||
got = userutil.ValidatePassword(alice.Password, alice.Salt, newPassword)
|
got = userx.ValidatePassword(alice.Password, alice.Salt, newPassword)
|
||||||
assert.True(t, got, "New password should work")
|
assert.True(t, got, "New password should work")
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -1074,7 +1074,7 @@ func usersUpdate(t *testing.T, ctx context.Context, s *UsersStore) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
got := s.Update(ctx, alice.ID, UpdateUserOptions{Email: &bob.Email})
|
got := s.Update(ctx, alice.ID, UpdateUserOptions{Email: &bob.Email})
|
||||||
want := ErrEmailAlreadyUsed{args: errutil.Args{"email": bob.Email}}
|
want := ErrEmailAlreadyUsed{args: errx.Args{"email": bob.Email}}
|
||||||
assert.Equal(t, want, got)
|
assert.Equal(t, want, got)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -1146,7 +1146,7 @@ func usersUseCustomAvatar(t *testing.T, ctx context.Context, s *UsersStore) {
|
|||||||
avatar, err := public.Files.ReadFile("img/avatar_default.png")
|
avatar, err := public.Files.ReadFile("img/avatar_default.png")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
avatarPath := userutil.CustomAvatarPath(alice.ID)
|
avatarPath := userx.CustomAvatarPath(alice.ID)
|
||||||
_ = os.Remove(avatarPath)
|
_ = os.Remove(avatarPath)
|
||||||
defer func() { _ = os.Remove(avatarPath) }()
|
defer func() { _ = os.Remove(avatarPath) }()
|
||||||
|
|
||||||
@@ -1154,7 +1154,7 @@ func usersUseCustomAvatar(t *testing.T, ctx context.Context, s *UsersStore) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// Make sure avatar is saved and the user flag is updated.
|
// Make sure avatar is saved and the user flag is updated.
|
||||||
got := osutil.IsFile(avatarPath)
|
got := osx.IsFile(avatarPath)
|
||||||
assert.True(t, got)
|
assert.True(t, got)
|
||||||
|
|
||||||
alice, err = s.GetByID(ctx, alice.ID)
|
alice, err = s.GetByID(ctx, alice.ID)
|
||||||
@@ -1189,7 +1189,7 @@ func usersAddEmail(t *testing.T, ctx context.Context, s *UsersStore) {
|
|||||||
bob, err := s.Create(ctx, "bob", "verified@example.com", CreateUserOptions{Activated: true})
|
bob, err := s.Create(ctx, "bob", "verified@example.com", CreateUserOptions{Activated: true})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
got := s.AddEmail(ctx, bob.ID+1, "verified@example.com", true)
|
got := s.AddEmail(ctx, bob.ID+1, "verified@example.com", true)
|
||||||
want := ErrEmailAlreadyUsed{args: errutil.Args{"email": "verified@example.com"}}
|
want := ErrEmailAlreadyUsed{args: errx.Args{"email": "verified@example.com"}}
|
||||||
require.Equal(t, want, got)
|
require.Equal(t, want, got)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -1199,7 +1199,7 @@ func usersGetEmail(t *testing.T, ctx context.Context, s *UsersStore) {
|
|||||||
const testEmail = "alice@example.com"
|
const testEmail = "alice@example.com"
|
||||||
_, err := s.GetEmail(ctx, testUserID, testEmail, false)
|
_, err := s.GetEmail(ctx, testUserID, testEmail, false)
|
||||||
wantErr := ErrEmailNotExist{
|
wantErr := ErrEmailNotExist{
|
||||||
args: errutil.Args{
|
args: errx.Args{
|
||||||
"email": testEmail,
|
"email": testEmail,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -1288,7 +1288,7 @@ func usersMarkEmailPrimary(t *testing.T, ctx context.Context, s *UsersStore) {
|
|||||||
|
|
||||||
// Should fail because email not verified
|
// Should fail because email not verified
|
||||||
gotError := s.MarkEmailPrimary(ctx, alice.ID, "alice2@example.com")
|
gotError := s.MarkEmailPrimary(ctx, alice.ID, "alice2@example.com")
|
||||||
wantError := ErrEmailNotVerified{args: errutil.Args{"email": "alice2@example.com"}}
|
wantError := ErrEmailNotVerified{args: errx.Args{"email": "alice2@example.com"}}
|
||||||
assert.Equal(t, wantError, gotError)
|
assert.Equal(t, wantError, gotError)
|
||||||
|
|
||||||
// Mark email as verified and should succeed
|
// Mark email as verified and should succeed
|
||||||
@@ -1318,7 +1318,7 @@ func usersDeleteEmail(t *testing.T, ctx context.Context, s *UsersStore) {
|
|||||||
err = s.DeleteEmail(ctx, alice.ID, "alice2@example.com")
|
err = s.DeleteEmail(ctx, alice.ID, "alice2@example.com")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
_, got := s.GetEmail(ctx, alice.ID, "alice2@example.com", false)
|
_, got := s.GetEmail(ctx, alice.ID, "alice2@example.com", false)
|
||||||
want := ErrEmailNotExist{args: errutil.Args{"email": "alice2@example.com"}}
|
want := ErrEmailNotExist{args: errx.Args{"email": "alice2@example.com"}}
|
||||||
require.Equal(t, want, got)
|
require.Equal(t, want, got)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/url"
|
"net/url"
|
||||||
@@ -13,18 +14,16 @@ import (
|
|||||||
|
|
||||||
"github.com/cockroachdb/errors"
|
"github.com/cockroachdb/errors"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
jsoniter "github.com/json-iterator/go"
|
|
||||||
log "unknwon.dev/clog/v2"
|
log "unknwon.dev/clog/v2"
|
||||||
"xorm.io/xorm"
|
"xorm.io/xorm"
|
||||||
|
|
||||||
api "github.com/gogs/go-gogs-client"
|
|
||||||
|
|
||||||
"gogs.io/gogs/internal/conf"
|
"gogs.io/gogs/internal/conf"
|
||||||
"gogs.io/gogs/internal/errutil"
|
"gogs.io/gogs/internal/errx"
|
||||||
"gogs.io/gogs/internal/httplib"
|
"gogs.io/gogs/internal/httplib"
|
||||||
"gogs.io/gogs/internal/netutil"
|
"gogs.io/gogs/internal/netx"
|
||||||
|
apiv1types "gogs.io/gogs/internal/route/api/v1/types"
|
||||||
"gogs.io/gogs/internal/sync"
|
"gogs.io/gogs/internal/sync"
|
||||||
"gogs.io/gogs/internal/testutil"
|
"gogs.io/gogs/internal/testx"
|
||||||
)
|
)
|
||||||
|
|
||||||
var HookQueue = sync.NewUniqueQueue(1000)
|
var HookQueue = sync.NewUniqueQueue(1000)
|
||||||
@@ -126,7 +125,7 @@ func (w *Webhook) AfterSet(colName string, _ xorm.Cell) {
|
|||||||
switch colName {
|
switch colName {
|
||||||
case "events":
|
case "events":
|
||||||
w.HookEvent = &HookEvent{}
|
w.HookEvent = &HookEvent{}
|
||||||
if err = jsoniter.Unmarshal([]byte(w.Events), w.HookEvent); err != nil {
|
if err = json.Unmarshal([]byte(w.Events), w.HookEvent); err != nil {
|
||||||
log.Error("Unmarshal [%d]: %v", w.ID, err)
|
log.Error("Unmarshal [%d]: %v", w.ID, err)
|
||||||
}
|
}
|
||||||
case "created_unix":
|
case "created_unix":
|
||||||
@@ -138,7 +137,7 @@ func (w *Webhook) AfterSet(colName string, _ xorm.Cell) {
|
|||||||
|
|
||||||
func (w *Webhook) SlackMeta() *SlackMeta {
|
func (w *Webhook) SlackMeta() *SlackMeta {
|
||||||
s := &SlackMeta{}
|
s := &SlackMeta{}
|
||||||
if err := jsoniter.Unmarshal([]byte(w.Meta), s); err != nil {
|
if err := json.Unmarshal([]byte(w.Meta), s); err != nil {
|
||||||
log.Error("Failed to get Slack meta [webhook_id: %d]: %v", w.ID, err)
|
log.Error("Failed to get Slack meta [webhook_id: %d]: %v", w.ID, err)
|
||||||
}
|
}
|
||||||
return s
|
return s
|
||||||
@@ -151,7 +150,7 @@ func (w *Webhook) History(page int) ([]*HookTask, error) {
|
|||||||
|
|
||||||
// UpdateEvent handles conversion from HookEvent to Events.
|
// UpdateEvent handles conversion from HookEvent to Events.
|
||||||
func (w *Webhook) UpdateEvent() error {
|
func (w *Webhook) UpdateEvent() error {
|
||||||
data, err := jsoniter.Marshal(w.HookEvent)
|
data, err := json.Marshal(w.HookEvent)
|
||||||
w.Events = string(data)
|
w.Events = string(data)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -235,7 +234,7 @@ func CreateWebhook(w *Webhook) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ errutil.NotFound = (*ErrWebhookNotExist)(nil)
|
var _ errx.NotFound = (*ErrWebhookNotExist)(nil)
|
||||||
|
|
||||||
type ErrWebhookNotExist struct {
|
type ErrWebhookNotExist struct {
|
||||||
args map[string]any
|
args map[string]any
|
||||||
@@ -430,21 +429,21 @@ type HookResponse struct {
|
|||||||
|
|
||||||
// HookTask represents a hook task.
|
// HookTask represents a hook task.
|
||||||
type HookTask struct {
|
type HookTask struct {
|
||||||
ID int64
|
ID int64
|
||||||
RepoID int64 `xorm:"INDEX"`
|
RepoID int64 `xorm:"INDEX"`
|
||||||
HookID int64
|
HookID int64
|
||||||
UUID string
|
UUID string
|
||||||
Type HookTaskType
|
Type HookTaskType
|
||||||
URL string `xorm:"TEXT"`
|
URL string `xorm:"TEXT"`
|
||||||
Signature string `xorm:"TEXT"`
|
Signature string `xorm:"TEXT"`
|
||||||
api.Payloader `xorm:"-" json:"-" gorm:"-"`
|
apiv1types.WebhookPayloader `xorm:"-" json:"-" gorm:"-"`
|
||||||
PayloadContent string `xorm:"TEXT"`
|
PayloadContent string `xorm:"TEXT"`
|
||||||
ContentType HookContentType
|
ContentType HookContentType
|
||||||
EventType HookEventType
|
EventType HookEventType
|
||||||
IsSSL bool
|
IsSSL bool
|
||||||
IsDelivered bool
|
IsDelivered bool
|
||||||
Delivered int64
|
Delivered int64
|
||||||
DeliveredString string `xorm:"-" json:"-" gorm:"-"`
|
DeliveredString string `xorm:"-" json:"-" gorm:"-"`
|
||||||
|
|
||||||
// History info.
|
// History info.
|
||||||
IsSucceed bool
|
IsSucceed bool
|
||||||
@@ -475,7 +474,7 @@ func (t *HookTask) AfterSet(colName string, _ xorm.Cell) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
t.RequestInfo = &HookRequest{}
|
t.RequestInfo = &HookRequest{}
|
||||||
if err = jsoniter.Unmarshal([]byte(t.RequestContent), t.RequestInfo); err != nil {
|
if err = json.Unmarshal([]byte(t.RequestContent), t.RequestInfo); err != nil {
|
||||||
log.Error("Unmarshal[%d]: %v", t.ID, err)
|
log.Error("Unmarshal[%d]: %v", t.ID, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -485,14 +484,14 @@ func (t *HookTask) AfterSet(colName string, _ xorm.Cell) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
t.ResponseInfo = &HookResponse{}
|
t.ResponseInfo = &HookResponse{}
|
||||||
if err = jsoniter.Unmarshal([]byte(t.ResponseContent), t.ResponseInfo); err != nil {
|
if err = json.Unmarshal([]byte(t.ResponseContent), t.ResponseInfo); err != nil {
|
||||||
log.Error("Unmarshal [%d]: %v", t.ID, err)
|
log.Error("Unmarshal [%d]: %v", t.ID, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *HookTask) ToJSON(v any) string {
|
func (t *HookTask) ToJSON(v any) string {
|
||||||
p, err := jsoniter.Marshal(v)
|
p, err := json.Marshal(v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Marshal [%d]: %v", t.ID, err)
|
log.Error("Marshal [%d]: %v", t.ID, err)
|
||||||
}
|
}
|
||||||
@@ -518,7 +517,7 @@ func createHookTask(e Engine, t *HookTask) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ errutil.NotFound = (*ErrHookTaskNotExist)(nil)
|
var _ errx.NotFound = (*ErrHookTaskNotExist)(nil)
|
||||||
|
|
||||||
type ErrHookTaskNotExist struct {
|
type ErrHookTaskNotExist struct {
|
||||||
args map[string]any
|
args map[string]any
|
||||||
@@ -559,12 +558,12 @@ func UpdateHookTask(t *HookTask) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// prepareHookTasks adds list of webhooks to task queue.
|
// prepareHookTasks adds list of webhooks to task queue.
|
||||||
func prepareHookTasks(e Engine, repo *Repository, event HookEventType, p api.Payloader, webhooks []*Webhook) (err error) {
|
func prepareHookTasks(e Engine, repo *Repository, event HookEventType, p apiv1types.WebhookPayloader, webhooks []*Webhook) (err error) {
|
||||||
if len(webhooks) == 0 {
|
if len(webhooks) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var payloader api.Payloader
|
var payloader apiv1types.WebhookPayloader
|
||||||
for _, w := range webhooks {
|
for _, w := range webhooks {
|
||||||
switch event {
|
switch event {
|
||||||
case HookEventTypeCreate:
|
case HookEventTypeCreate:
|
||||||
@@ -634,15 +633,15 @@ func prepareHookTasks(e Engine, repo *Repository, event HookEventType, p api.Pay
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err = createHookTask(e, &HookTask{
|
if err = createHookTask(e, &HookTask{
|
||||||
RepoID: repo.ID,
|
RepoID: repo.ID,
|
||||||
HookID: w.ID,
|
HookID: w.ID,
|
||||||
Type: w.HookTaskType,
|
Type: w.HookTaskType,
|
||||||
URL: w.URL,
|
URL: w.URL,
|
||||||
Signature: signature,
|
Signature: signature,
|
||||||
Payloader: payloader,
|
WebhookPayloader: payloader,
|
||||||
ContentType: w.ContentType,
|
ContentType: w.ContentType,
|
||||||
EventType: event,
|
EventType: event,
|
||||||
IsSSL: w.IsSSL,
|
IsSSL: w.IsSSL,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return errors.Newf("createHookTask: %v", err)
|
return errors.Newf("createHookTask: %v", err)
|
||||||
}
|
}
|
||||||
@@ -655,7 +654,7 @@ func prepareHookTasks(e Engine, repo *Repository, event HookEventType, p api.Pay
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func prepareWebhooks(e Engine, repo *Repository, event HookEventType, p api.Payloader) error {
|
func prepareWebhooks(e Engine, repo *Repository, event HookEventType, p apiv1types.WebhookPayloader) error {
|
||||||
webhooks, err := getActiveWebhooksByRepoID(e, repo.ID)
|
webhooks, err := getActiveWebhooksByRepoID(e, repo.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Newf("getActiveWebhooksByRepoID [%d]: %v", repo.ID, err)
|
return errors.Newf("getActiveWebhooksByRepoID [%d]: %v", repo.ID, err)
|
||||||
@@ -674,17 +673,17 @@ func prepareWebhooks(e Engine, repo *Repository, event HookEventType, p api.Payl
|
|||||||
}
|
}
|
||||||
|
|
||||||
// PrepareWebhooks adds all active webhooks to task queue.
|
// PrepareWebhooks adds all active webhooks to task queue.
|
||||||
func PrepareWebhooks(repo *Repository, event HookEventType, p api.Payloader) error {
|
func PrepareWebhooks(repo *Repository, event HookEventType, p apiv1types.WebhookPayloader) error {
|
||||||
// NOTE: To prevent too many cascading changes in a single refactoring PR, we
|
// NOTE: To prevent too many cascading changes in a single refactoring PR, we
|
||||||
// choose to ignore this function in tests.
|
// choose to ignore this function in tests.
|
||||||
if x == nil && testutil.InTest {
|
if x == nil && testx.InTest {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return prepareWebhooks(x, repo, event, p)
|
return prepareWebhooks(x, repo, event, p)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestWebhook adds the test webhook matches the ID to task queue.
|
// TestWebhook adds the test webhook matches the ID to task queue.
|
||||||
func TestWebhook(repo *Repository, event HookEventType, p api.Payloader, webhookID int64) error {
|
func TestWebhook(repo *Repository, event HookEventType, p apiv1types.WebhookPayloader, webhookID int64) error {
|
||||||
webhook, err := GetWebhookOfRepoByID(repo.ID, webhookID)
|
webhook, err := GetWebhookOfRepoByID(repo.ID, webhookID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Newf("GetWebhookOfRepoByID [repo_id: %d, id: %d]: %v", repo.ID, webhookID, err)
|
return errors.Newf("GetWebhookOfRepoByID [repo_id: %d, id: %d]: %v", repo.ID, webhookID, err)
|
||||||
@@ -698,7 +697,7 @@ func (t *HookTask) deliver() {
|
|||||||
t.ResponseContent = fmt.Sprintf(`{"body": "Cannot parse payload URL: %v"}`, err)
|
t.ResponseContent = fmt.Sprintf(`{"body": "Cannot parse payload URL: %v"}`, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if netutil.IsBlockedLocalHostname(payloadURL.Hostname(), conf.Security.LocalNetworkAllowlist) {
|
if netx.IsBlockedLocalHostname(payloadURL.Hostname(), conf.Security.LocalNetworkAllowlist) {
|
||||||
t.ResponseContent = `{"body": "Payload URL resolved to a local network address that is implicitly blocked."}`
|
t.ResponseContent = `{"body": "Payload URL resolved to a local network address that is implicitly blocked."}`
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user