mirror of
https://github.com/gogs/gogs.git
synced 2026-02-28 17:20:59 +01:00
Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f0e3cd90f8 | ||
|
|
fbe34c8c61 | ||
|
|
e6b4c467e8 | ||
|
|
6b6bfe8bb0 | ||
|
|
253b2bef4c | ||
|
|
1a051ae5f8 | ||
|
|
ca54cbd055 | ||
|
|
9044afa40f | ||
|
|
672625b55c | ||
|
|
98c65f319f |
11
.github/workflows/go.yml
vendored
11
.github/workflows/go.yml
vendored
@@ -1,8 +1,14 @@
|
||||
name: Go
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
branches:
|
||||
- main
|
||||
- 'release/**'
|
||||
paths:
|
||||
- '**.go'
|
||||
pull_request:
|
||||
paths:
|
||||
- '**.go'
|
||||
env:
|
||||
GOPROXY: "https://proxy.golang.org"
|
||||
|
||||
@@ -21,7 +27,7 @@ jobs:
|
||||
name: Test
|
||||
strategy:
|
||||
matrix:
|
||||
go-version: [1.14.x]
|
||||
go-version: [1.14.x, 1.15.x]
|
||||
platform: [ubuntu-latest, macos-latest, windows-latest]
|
||||
runs-on: ${{ matrix.platform }}
|
||||
steps:
|
||||
@@ -45,4 +51,3 @@ jobs:
|
||||
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-go-
|
||||
|
||||
|
||||
51
CHANGELOG.md
51
CHANGELOG.md
@@ -2,13 +2,60 @@
|
||||
|
||||
All notable changes to Gogs are documented in this file.
|
||||
|
||||
## 0.13.0+dev (`master`)
|
||||
## 0.13.0+dev (`main`)
|
||||
|
||||
### Added
|
||||
|
||||
- An unlisted option is added when create or migrate a repository. Unlisted repositories are public but not being listed for users without direct access in the UI. [#5733](https://github.com/gogs/gogs/issues/5733)
|
||||
|
||||
### Changed
|
||||
|
||||
- The default branch has been changed to `main`. [#6285](https://github.com/gogs/gogs/pull/6285)
|
||||
- MSSQL as database backend is deprecated, installation page no longer shows it as an option. Existing installations and manually craft configuration file continue to work. [#6295](https://github.com/gogs/gogs/pull/6295)
|
||||
- Use [Task](https://github.com/go-task/task) as the default build tool for development. [#6297](https://github.com/gogs/gogs/pull/6297)
|
||||
|
||||
### Fixed
|
||||
|
||||
- _Regression:_ Pages are correctly rendered when requesting `?go-get=1` for subdirectories. [#6314](https://github.com/gogs/gogs/issues/6314)
|
||||
- _Regression:_ Submodule with a relative path is linked correctly. [#6319](https://github.com/gogs/gogs/issues/6319)
|
||||
- Backup can be processed when `--target` is specified on Windows. [#6339](https://github.com/gogs/gogs/issues/6339)
|
||||
- Commit message contains keywords look like an issue reference no longer fails the push entirely. [#6289](https://github.com/gogs/gogs/issues/6289)
|
||||
- _Regression:_ When running Gogs on Windows, push commits no longer fail on a daily basis with the error "pre-receive hook declined". [#6316](https://github.com/gogs/gogs/issues/6316)
|
||||
- Auto-linked commit SHAs now have correct links. [#6300](https://github.com/gogs/gogs/issues/6300)
|
||||
- Git LFS client (with version >= 2.5.0) wasn't able to upload files with known format (e.g. PNG, JPEG), and the server is expecting the HTTP Header `Content-Type` to be `application/octet-stream`. The server now tells the LFS client to always use `Content-Type: application/octet-stream` when upload files.
|
||||
|
||||
### Removed
|
||||
|
||||
- ⚠️ Migrations before 0.12 are removed, installations not on 0.12 should upgrade to it to run the migrations and then upgrade to 0.13.
|
||||
- Configuration section `[mailer]` is no longer used.
|
||||
- Configuration section `[service]` is no longer used.
|
||||
- Configuration option `APP_NAME` is no longer used.
|
||||
- Configuration option `[security] REVERSE_PROXY_AUTHENTICATION_USER` is no longer used.
|
||||
- Configuration option `[database] PASSWD` is no longer used.
|
||||
- Configuration option `[auth] ACTIVE_CODE_LIVE_MINUTES` is no longer used.
|
||||
- Configuration option `[auth] RESET_PASSWD_CODE_LIVE_MINUTES` is no longer used.
|
||||
- Configuration option `[auth] ENABLE_CAPTCHA` is no longer used.
|
||||
- Configuration option `[auth] ENABLE_NOTIFY_MAIL` is no longer used.
|
||||
- Configuration option `[auth] REGISTER_EMAIL_CONFIRM` is no longer used.
|
||||
- Configuration option `[session] GC_INTERVAL_TIME` is no longer used.
|
||||
- Configuration option `[session] SESSION_LIFE_TIME` is no longer used.
|
||||
- Configuration option `[server] ROOT_URL` is no longer used.
|
||||
- Configuration option `[server] LANDING_PAGE` is no longer used.
|
||||
- Configuration option `[database] DB_TYPE` is no longer used.
|
||||
- Configuration option `[database] PASSWD` is no longer used.
|
||||
|
||||
## 0.12.1
|
||||
|
||||
### Fixed
|
||||
|
||||
- The `updated_at` field is now correctly updated when updates an issue. [#6209](https://github.com/gogs/gogs/issues/6209)
|
||||
- Fixed a regression which created `login_source.cfg` column to have `VARCHAR(255)` instead of `TEXT` in MySQL. [#6280](https://github.com/gogs/gogs/issues/6280)
|
||||
|
||||
## 0.12.0
|
||||
|
||||
### Added
|
||||
|
||||
- Support for Git LFS, you can read documentation for both [user](https://github.com/gogs/gogs/blob/master/docs/user/lfs.md) and [admin](https://github.com/gogs/gogs/blob/master/docs/admin/lfs.md). [#1322](https://github.com/gogs/gogs/issues/1322)
|
||||
- Support for Git LFS, you can read documentation for both [user](https://github.com/gogs/gogs/blob/main/docs/user/lfs.md) and [admin](https://github.com/gogs/gogs/blob/main/docs/admin/lfs.md). [#1322](https://github.com/gogs/gogs/issues/1322)
|
||||
- Allow admin to remove observers from the repository. [#5803](https://github.com/gogs/gogs/pull/5803)
|
||||
- Use `Last-Modified` HTTP header for raw files. [#5811](https://github.com/gogs/gogs/issues/5811)
|
||||
- Support syntax highlighting for SAS code files (i.e. `.r`, `.sas`, `.tex`, `.yaml`). [#5856](https://github.com/gogs/gogs/pull/5856)
|
||||
|
||||
2
go.mod
2
go.mod
@@ -51,7 +51,7 @@ require (
|
||||
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect
|
||||
github.com/stretchr/testify v1.6.1
|
||||
github.com/t-tiger/gorm-bulk-insert v1.3.0
|
||||
github.com/unknwon/cae v1.0.0
|
||||
github.com/unknwon/cae v1.0.2
|
||||
github.com/unknwon/com v1.0.1
|
||||
github.com/unknwon/i18n v0.0.0-20190805065654-5c6446a380b6
|
||||
github.com/unknwon/paginater v0.0.0-20170405233947-45e5d631308e
|
||||
|
||||
12
go.sum
12
go.sum
@@ -266,6 +266,7 @@ github.com/smartystreets/assertions v1.0.1/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUr
|
||||
github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s=
|
||||
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf h1:pvbZ0lM0XWPBqUKqFU8cmavspvIl9nulOYwdy6IFRRo=
|
||||
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=
|
||||
@@ -282,8 +283,8 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
||||
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
|
||||
github.com/t-tiger/gorm-bulk-insert v1.3.0 h1:9k7BaVEhw/3fsvh6GTOBwJ2RXk3asc5xs5m6hwozq20=
|
||||
github.com/t-tiger/gorm-bulk-insert v1.3.0/go.mod h1:ruDlk8xDl+8sX4bA7PQuYly9YEb3pbp1eP2LCyeRrFY=
|
||||
github.com/unknwon/cae v1.0.0 h1:i39lOFaBXZxhGjQOy/RNbi8uzettCs6OQxpR0xXohGU=
|
||||
github.com/unknwon/cae v1.0.0/go.mod h1:QaSeRctcea9fK6piJpAMCCPKxzJ01+xFcr2k1m3WRPU=
|
||||
github.com/unknwon/cae v1.0.2 h1:3L8/RCN1ARvD5quyNjU30EdvYkFbxBfnRcIBXugpHlg=
|
||||
github.com/unknwon/cae v1.0.2/go.mod h1:HqpmD2fVq9G1oGEXrXzbgIp51uJ29Hshv41n9ljm+AA=
|
||||
github.com/unknwon/com v0.0.0-20190804042917-757f69c95f3e/go.mod h1:tOOxU81rwgoCLoOVVPHb6T/wt8HZygqH5id+GNnlCXM=
|
||||
github.com/unknwon/com v1.0.1 h1:3d1LTxD+Lnf3soQiD4Cp/0BRB+Rsa/+RTvz8GMMzIXs=
|
||||
github.com/unknwon/com v1.0.1/go.mod h1:tOOxU81rwgoCLoOVVPHb6T/wt8HZygqH5id+GNnlCXM=
|
||||
@@ -353,7 +354,6 @@ golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f h1:gWF768j/LaZugp8dyS4UwsslY
|
||||
golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
@@ -400,7 +400,6 @@ gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMy
|
||||
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.55.0 h1:E8yzL5unfpW3M6fz/eB7Cb5MQAYSZ7GKo4Qth+N2sgQ=
|
||||
gopkg.in/ini.v1 v1.55.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/ini.v1 v1.56.0 h1:DPMeDvGTM54DXbPkVIZsp19fp/I2K7zwA/itHYHKo8Y=
|
||||
gopkg.in/ini.v1 v1.56.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
@@ -408,10 +407,6 @@ gopkg.in/ldap.v2 v2.5.1 h1:wiu0okdNfjlBzg6UWvd1Hn8Y+Ux17/u/4nlk4CQr6tU=
|
||||
gopkg.in/ldap.v2 v2.5.1/go.mod h1:oI0cpe/D7HRtBQl8aTg+ZmzFUAvu4lsv3eLXMLGFxWk=
|
||||
gopkg.in/macaron.v1 v1.3.4/go.mod h1:/RoHTdC8ALpyJ3+QR36mKjwnT1F1dyYtsGM9Ate6ZFI=
|
||||
gopkg.in/macaron.v1 v1.3.5/go.mod h1:uMZCFccv9yr5TipIalVOyAyZQuOH3OkmXvgcWwhJuP4=
|
||||
gopkg.in/macaron.v1 v1.3.6 h1:mHw5qRGj2f86sCjBV/S5OOPvPbiZpu0OEs1F5l66fYI=
|
||||
gopkg.in/macaron.v1 v1.3.6/go.mod h1:uMZCFccv9yr5TipIalVOyAyZQuOH3OkmXvgcWwhJuP4=
|
||||
gopkg.in/macaron.v1 v1.3.8 h1:45bQT4dDF+5SLd75qlj+dulQsuFQ9aFyLlvZX6YUJWE=
|
||||
gopkg.in/macaron.v1 v1.3.8/go.mod h1:uMZCFccv9yr5TipIalVOyAyZQuOH3OkmXvgcWwhJuP4=
|
||||
gopkg.in/macaron.v1 v1.3.9 h1:Dw+DDRYdXgQyEsPlfAfKz+UA5qVUrH3KPD7JhmZ9MFc=
|
||||
gopkg.in/macaron.v1 v1.3.9/go.mod h1:uMZCFccv9yr5TipIalVOyAyZQuOH3OkmXvgcWwhJuP4=
|
||||
gopkg.in/redis.v2 v2.3.2 h1:GPVIIB/JnL1wvfULefy3qXmPu1nfNu2d0yA09FHgwfs=
|
||||
@@ -421,7 +416,6 @@ 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.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
|
||||
2
gogs.go
2
gogs.go
@@ -18,7 +18,7 @@ import (
|
||||
)
|
||||
|
||||
func init() {
|
||||
conf.App.Version = "0.12.1"
|
||||
conf.App.Version = "0.12.3"
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -66,7 +66,7 @@ func runHookPreReceive(c *cli.Context) error {
|
||||
if len(os.Getenv("SSH_ORIGINAL_COMMAND")) == 0 {
|
||||
return nil
|
||||
}
|
||||
setup(c, "hooks/pre-receive.log", true)
|
||||
setup(c, "pre-receive.log", true)
|
||||
|
||||
isWiki := strings.Contains(os.Getenv(db.ENV_REPO_CUSTOM_HOOKS_PATH), ".wiki.git/")
|
||||
|
||||
@@ -159,7 +159,7 @@ func runHookUpdate(c *cli.Context) error {
|
||||
if len(os.Getenv("SSH_ORIGINAL_COMMAND")) == 0 {
|
||||
return nil
|
||||
}
|
||||
setup(c, "hooks/update.log", false)
|
||||
setup(c, "update.log", false)
|
||||
|
||||
args := c.Args()
|
||||
if len(args) != 3 {
|
||||
@@ -193,7 +193,7 @@ func runHookPostReceive(c *cli.Context) error {
|
||||
if len(os.Getenv("SSH_ORIGINAL_COMMAND")) == 0 {
|
||||
return nil
|
||||
}
|
||||
setup(c, "hooks/post-receive.log", true)
|
||||
setup(c, "post-receive.log", true)
|
||||
|
||||
// Post-receive hook does more than just gather Git information,
|
||||
// so we need to setup additional services for email notifications.
|
||||
|
||||
@@ -38,7 +38,7 @@ var Serv = cli.Command{
|
||||
// logs error message on the server side. When not in "prod" mode,
|
||||
// error message is also printed to the client for easier debugging.
|
||||
func fail(userMessage, errMessage string, args ...interface{}) {
|
||||
fmt.Fprintln(os.Stderr, "Gogs:", userMessage)
|
||||
_, _ = fmt.Fprintln(os.Stderr, "Gogs:", userMessage)
|
||||
|
||||
if len(errMessage) > 0 {
|
||||
if !conf.IsProdMode() {
|
||||
@@ -47,10 +47,11 @@ func fail(userMessage, errMessage string, args ...interface{}) {
|
||||
log.Error(errMessage, args...)
|
||||
}
|
||||
|
||||
log.Stop()
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
func setup(c *cli.Context, logPath string, connectDB bool) {
|
||||
func setup(c *cli.Context, logFile string, connectDB bool) {
|
||||
conf.HookMode = true
|
||||
|
||||
var customConf string
|
||||
@@ -73,7 +74,7 @@ func setup(c *cli.Context, logPath string, connectDB bool) {
|
||||
|
||||
err = log.NewFile(log.FileConfig{
|
||||
Level: level,
|
||||
Filename: filepath.Join(conf.Log.RootPath, logPath),
|
||||
Filename: filepath.Join(conf.Log.RootPath, "hooks", logFile),
|
||||
FileRotationConfig: log.FileRotationConfig{
|
||||
Rotate: true,
|
||||
Daily: true,
|
||||
|
||||
@@ -611,7 +611,7 @@ func runWeb(c *cli.Context) error {
|
||||
m.Get("/compare/:before([a-z0-9]{40})\\.\\.\\.:after([a-z0-9]{40})", repo.MustBeNotBare, context.RepoRef(), repo.CompareDiff)
|
||||
}, ignSignIn, context.RepoAssignment())
|
||||
m.Group("/:username/:reponame", func() {
|
||||
m.Get("", repo.Home)
|
||||
m.Get("", context.ServeGoGet(), repo.Home)
|
||||
m.Get("/stars", repo.Stars)
|
||||
m.Get("/watchers", repo.Watchers)
|
||||
}, ignSignIn, context.RepoAssignment(), context.RepoRef())
|
||||
@@ -659,7 +659,7 @@ func runWeb(c *cli.Context) error {
|
||||
lfs.RegisterRoutes(m.Router)
|
||||
})
|
||||
|
||||
m.Route("/*", "GET,POST,OPTIONS", repo.HTTPContexter(), repo.HTTP)
|
||||
m.Route("/*", "GET,POST,OPTIONS", context.ServeGoGet(), repo.HTTPContexter(), repo.HTTP)
|
||||
})
|
||||
|
||||
// ***************************
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"path"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -16,7 +15,6 @@ import (
|
||||
"github.com/go-macaron/csrf"
|
||||
"github.com/go-macaron/i18n"
|
||||
"github.com/go-macaron/session"
|
||||
"github.com/unknwon/com"
|
||||
"gopkg.in/macaron.v1"
|
||||
log "unknwon.dev/clog/v2"
|
||||
|
||||
@@ -249,52 +247,6 @@ func Contexter() macaron.Handler {
|
||||
c.Data["Link"] = template.EscapePound(c.Link)
|
||||
c.Data["PageStartTime"] = time.Now()
|
||||
|
||||
// Quick responses appropriate go-get meta with status 200
|
||||
// regardless of if user have access to the repository,
|
||||
// or the repository does not exist at all.
|
||||
// This is particular a workaround for "go get" command which does not respect
|
||||
// .netrc file.
|
||||
if c.Query("go-get") == "1" {
|
||||
ownerName := c.Params(":username")
|
||||
repoName := c.Params(":reponame")
|
||||
branchName := "master"
|
||||
|
||||
owner, err := db.GetUserByName(ownerName)
|
||||
if err != nil {
|
||||
c.NotFoundOrError(err, "get user by name")
|
||||
return
|
||||
}
|
||||
|
||||
repo, err := db.GetRepositoryByName(owner.ID, repoName)
|
||||
if err == nil && len(repo.DefaultBranch) > 0 {
|
||||
branchName = repo.DefaultBranch
|
||||
}
|
||||
|
||||
prefix := conf.Server.ExternalURL + path.Join(ownerName, repoName, "src", branchName)
|
||||
insecureFlag := ""
|
||||
if !strings.HasPrefix(conf.Server.ExternalURL, "https://") {
|
||||
insecureFlag = "--insecure "
|
||||
}
|
||||
c.PlainText(http.StatusOK, com.Expand(`<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta name="go-import" content="{GoGetImport} git {CloneLink}">
|
||||
<meta name="go-source" content="{GoGetImport} _ {GoDocDirectory} {GoDocFile}">
|
||||
</head>
|
||||
<body>
|
||||
go get {InsecureFlag}{GoGetImport}
|
||||
</body>
|
||||
</html>
|
||||
`, map[string]string{
|
||||
"GoGetImport": path.Join(conf.Server.URL.Host, conf.Server.Subpath, ownerName, repoName),
|
||||
"CloneLink": db.ComposeHTTPSCloneURL(ownerName, repoName),
|
||||
"GoDocDirectory": prefix + "{/dir}",
|
||||
"GoDocFile": prefix + "{/dir}/{file}#L{line}",
|
||||
"InsecureFlag": insecureFlag,
|
||||
}))
|
||||
return
|
||||
}
|
||||
|
||||
if len(conf.HTTP.AccessControlAllowOrigin) > 0 {
|
||||
c.Header().Set("Access-Control-Allow-Origin", conf.HTTP.AccessControlAllowOrigin)
|
||||
c.Header().Set("'Access-Control-Allow-Credentials' ", "true")
|
||||
|
||||
62
internal/context/go_get.go
Normal file
62
internal/context/go_get.go
Normal file
@@ -0,0 +1,62 @@
|
||||
package context
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/unknwon/com"
|
||||
"gopkg.in/macaron.v1"
|
||||
|
||||
"gogs.io/gogs/internal/conf"
|
||||
"gogs.io/gogs/internal/db"
|
||||
)
|
||||
|
||||
// ServeGoGet does quick responses for appropriate go-get meta with status OK
|
||||
// regardless of whether the user has access to the repository, or the repository
|
||||
// does exist at all. This is particular a workaround for "go get" command which
|
||||
// does not respect .netrc file.
|
||||
func ServeGoGet() macaron.Handler {
|
||||
return func(c *macaron.Context) {
|
||||
if c.Query("go-get") != "1" {
|
||||
return
|
||||
}
|
||||
|
||||
ownerName := c.Params(":username")
|
||||
repoName := c.Params(":reponame")
|
||||
branchName := "master"
|
||||
|
||||
owner, err := db.Users.GetByUsername(ownerName)
|
||||
if err == nil {
|
||||
repo, err := db.Repos.GetByName(owner.ID, repoName)
|
||||
if err == nil && repo.DefaultBranch != "" {
|
||||
branchName = repo.DefaultBranch
|
||||
}
|
||||
}
|
||||
|
||||
prefix := conf.Server.ExternalURL + path.Join(ownerName, repoName, "src", branchName)
|
||||
insecureFlag := ""
|
||||
if !strings.HasPrefix(conf.Server.ExternalURL, "https://") {
|
||||
insecureFlag = "--insecure "
|
||||
}
|
||||
c.PlainText(http.StatusOK, []byte(com.Expand(`<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta name="go-import" content="{GoGetImport} git {CloneLink}">
|
||||
<meta name="go-source" content="{GoGetImport} _ {GoDocDirectory} {GoDocFile}">
|
||||
</head>
|
||||
<body>
|
||||
go get {InsecureFlag}{GoGetImport}
|
||||
</body>
|
||||
</html>
|
||||
`,
|
||||
map[string]string{
|
||||
"GoGetImport": path.Join(conf.Server.URL.Host, conf.Server.Subpath, ownerName, repoName),
|
||||
"CloneLink": db.ComposeHTTPSCloneURL(ownerName, repoName),
|
||||
"GoDocDirectory": prefix + "{/dir}",
|
||||
"GoDocFile": prefix + "{/dir}/{file}#L{line}",
|
||||
"InsecureFlag": insecureFlag,
|
||||
},
|
||||
)))
|
||||
}
|
||||
}
|
||||
@@ -57,9 +57,9 @@ var (
|
||||
IssueCloseKeywords = []string{"close", "closes", "closed", "fix", "fixes", "fixed", "resolve", "resolves", "resolved"}
|
||||
IssueReopenKeywords = []string{"reopen", "reopens", "reopened"}
|
||||
|
||||
IssueCloseKeywordsPat = lazyregexp.New(assembleKeywordsPattern(IssueCloseKeywords))
|
||||
IssueReopenKeywordsPat = lazyregexp.New(assembleKeywordsPattern(IssueReopenKeywords))
|
||||
IssueReferenceKeywordsPat = lazyregexp.New(`(?i)(?:)(^| )\S+`)
|
||||
IssueCloseKeywordsPat = lazyregexp.New(assembleKeywordsPattern(IssueCloseKeywords))
|
||||
IssueReopenKeywordsPat = lazyregexp.New(assembleKeywordsPattern(IssueReopenKeywords))
|
||||
issueReferencePattern = lazyregexp.New(`(?i)(?:)(^| )\S*#\d+`)
|
||||
)
|
||||
|
||||
func assembleKeywordsPattern(words []string) string {
|
||||
@@ -321,8 +321,8 @@ func UpdateIssuesCommit(doer *User, repo *Repository, commits []*PushCommit) err
|
||||
c := commits[i]
|
||||
|
||||
refMarked := make(map[int64]bool)
|
||||
for _, ref := range IssueReferenceKeywordsPat.FindAllString(c.Message, -1) {
|
||||
ref = ref[strings.IndexByte(ref, byte(' '))+1:]
|
||||
for _, ref := range issueReferencePattern.FindAllString(c.Message, -1) {
|
||||
ref = strings.TrimSpace(ref)
|
||||
ref = strings.TrimRightFunc(ref, issueIndexTrimRight)
|
||||
|
||||
if len(ref) == 0 {
|
||||
@@ -455,7 +455,7 @@ type CommitRepoActionOptions struct {
|
||||
Commits *PushCommits
|
||||
}
|
||||
|
||||
// CommitRepoAction adds new commit actio to the repository, and prepare corresponding webhooks.
|
||||
// CommitRepoAction adds new commit action to the repository, and prepare corresponding webhooks.
|
||||
func CommitRepoAction(opts CommitRepoActionOptions) error {
|
||||
pusher, err := GetUserByName(opts.PusherName)
|
||||
if err != nil {
|
||||
|
||||
41
internal/db/action_test.go
Normal file
41
internal/db/action_test.go
Normal file
@@ -0,0 +1,41 @@
|
||||
// Copyright 2020 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package db
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func Test_issueReferencePattern(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
message string
|
||||
expStrings []string
|
||||
}{
|
||||
{
|
||||
name: "no match",
|
||||
message: "Hello world!",
|
||||
expStrings: nil,
|
||||
},
|
||||
{
|
||||
name: "contains issue numbers",
|
||||
message: "#123 is fixed, and #456 is WIP",
|
||||
expStrings: []string{"#123", " #456"},
|
||||
},
|
||||
{
|
||||
name: "contains full issue references",
|
||||
message: "#123 is fixed, and user/repo#456 is WIP",
|
||||
expStrings: []string{"#123", " user/repo#456"},
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
strs := issueReferencePattern.FindAllString(test.message, -1)
|
||||
assert.Equal(t, test.expStrings, strs)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -128,7 +128,7 @@ var tables = []interface{}{
|
||||
new(LFSObject), new(LoginSource),
|
||||
}
|
||||
|
||||
func Init() (*gorm.DB, error) {
|
||||
func Init(w io.Writer) (*gorm.DB, error) {
|
||||
db, err := openDB(conf.Database)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "open database")
|
||||
@@ -138,10 +138,6 @@ func Init() (*gorm.DB, error) {
|
||||
db.DB().SetMaxIdleConns(conf.Database.MaxIdleConns)
|
||||
db.DB().SetConnMaxLifetime(time.Minute)
|
||||
|
||||
w, err := getLogWriter()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "get log writer")
|
||||
}
|
||||
db.SetLogger(&dbutil.Writer{Writer: w})
|
||||
if !conf.IsProdMode() {
|
||||
db = db.LogMode(true)
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
// Copyright 2017 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package errors
|
||||
|
||||
import "fmt"
|
||||
|
||||
type InvalidIssueReference struct {
|
||||
Ref string
|
||||
}
|
||||
|
||||
func IsInvalidIssueReference(err error) bool {
|
||||
_, ok := err.(InvalidIssueReference)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err InvalidIssueReference) Error() string {
|
||||
return fmt.Sprintf("invalid issue reference [ref: %s]", err.Ref)
|
||||
}
|
||||
@@ -817,12 +817,11 @@ func (ErrIssueNotExist) NotFound() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// GetIssueByRef returns an Issue specified by a GFM reference.
|
||||
// See https://help.github.com/articles/writing-on-github#references for more information on the syntax.
|
||||
// GetIssueByRef returns an Issue specified by a GFM reference, e.g. owner/repo#123.
|
||||
func GetIssueByRef(ref string) (*Issue, error) {
|
||||
n := strings.IndexByte(ref, byte('#'))
|
||||
if n == -1 {
|
||||
return nil, errors.InvalidIssueReference{Ref: ref}
|
||||
return nil, ErrIssueNotExist{args: map[string]interface{}{"ref": ref}}
|
||||
}
|
||||
|
||||
index := com.StrTo(ref[n+1:]).MustInt64()
|
||||
|
||||
@@ -7,13 +7,16 @@ package db
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/url"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/jinzhu/gorm"
|
||||
"github.com/pkg/errors"
|
||||
log "unknwon.dev/clog/v2"
|
||||
"xorm.io/core"
|
||||
"xorm.io/xorm"
|
||||
@@ -130,16 +133,21 @@ func SetEngine() (*gorm.DB, error) {
|
||||
|
||||
x.SetMapper(core.GonicMapper{})
|
||||
|
||||
// WARNING: for serv command, MUST remove the output to os.stdout,
|
||||
// so use log file to instead print to stdout.
|
||||
var logPath string
|
||||
if conf.HookMode {
|
||||
logPath = filepath.Join(conf.Log.RootPath, "hooks", "xorm.log")
|
||||
} else {
|
||||
logPath = filepath.Join(conf.Log.RootPath, "xorm.log")
|
||||
}
|
||||
sec := conf.File.Section("log.xorm")
|
||||
logger, err := log.NewFileWriter(path.Join(conf.Log.RootPath, "xorm.log"),
|
||||
fileWriter, err := log.NewFileWriter(logPath,
|
||||
log.FileRotationConfig{
|
||||
Rotate: sec.Key("ROTATE").MustBool(true),
|
||||
Daily: sec.Key("ROTATE_DAILY").MustBool(true),
|
||||
MaxSize: sec.Key("MAX_SIZE").MustInt64(100) * 1024 * 1024,
|
||||
MaxDays: sec.Key("MAX_DAYS").MustInt64(3),
|
||||
})
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("create 'xorm.log': %v", err)
|
||||
}
|
||||
@@ -149,12 +157,22 @@ func SetEngine() (*gorm.DB, error) {
|
||||
x.SetConnMaxLifetime(time.Second)
|
||||
|
||||
if conf.IsProdMode() {
|
||||
x.SetLogger(xorm.NewSimpleLogger3(logger, xorm.DEFAULT_LOG_PREFIX, xorm.DEFAULT_LOG_FLAG, core.LOG_WARNING))
|
||||
x.SetLogger(xorm.NewSimpleLogger3(fileWriter, xorm.DEFAULT_LOG_PREFIX, xorm.DEFAULT_LOG_FLAG, core.LOG_WARNING))
|
||||
} else {
|
||||
x.SetLogger(xorm.NewSimpleLogger(logger))
|
||||
x.SetLogger(xorm.NewSimpleLogger(fileWriter))
|
||||
}
|
||||
x.ShowSQL(true)
|
||||
return Init()
|
||||
|
||||
var w io.Writer
|
||||
if conf.HookMode {
|
||||
w = fileWriter
|
||||
} else {
|
||||
w, err = getLogWriter()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "get log writer")
|
||||
}
|
||||
}
|
||||
return Init(w)
|
||||
}
|
||||
|
||||
func NewEngine() (err error) {
|
||||
|
||||
@@ -426,24 +426,29 @@ func (repo *Repository) UpdateSize() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ComposeMetas composes a map of metas for rendering external issue tracker URL.
|
||||
// ComposeMetas composes a map of metas for rendering SHA1 URL and external issue tracker URL.
|
||||
func (repo *Repository) ComposeMetas() map[string]string {
|
||||
if !repo.EnableExternalTracker {
|
||||
return nil
|
||||
} else if repo.ExternalMetas == nil {
|
||||
repo.ExternalMetas = map[string]string{
|
||||
"format": repo.ExternalTrackerFormat,
|
||||
"user": repo.MustOwner().Name,
|
||||
"repo": repo.Name,
|
||||
}
|
||||
if repo.ExternalMetas != nil {
|
||||
return repo.ExternalMetas
|
||||
}
|
||||
|
||||
repo.ExternalMetas = map[string]string{
|
||||
"repoLink": repo.Link(),
|
||||
}
|
||||
|
||||
if repo.EnableExternalTracker {
|
||||
repo.ExternalMetas["user"] = repo.MustOwner().Name
|
||||
repo.ExternalMetas["repo"] = repo.Name
|
||||
repo.ExternalMetas["format"] = repo.ExternalTrackerFormat
|
||||
|
||||
switch repo.ExternalTrackerStyle {
|
||||
case markup.ISSUE_NAME_STYLE_ALPHANUMERIC:
|
||||
repo.ExternalMetas["style"] = markup.ISSUE_NAME_STYLE_ALPHANUMERIC
|
||||
default:
|
||||
repo.ExternalMetas["style"] = markup.ISSUE_NAME_STYLE_NUMERIC
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return repo.ExternalMetas
|
||||
}
|
||||
|
||||
|
||||
@@ -19,14 +19,19 @@ func TestRepository_ComposeMetas(t *testing.T) {
|
||||
|
||||
t.Run("no external tracker is configured", func(t *testing.T) {
|
||||
repo.EnableExternalTracker = false
|
||||
assert.Equal(t, map[string]string(nil), repo.ComposeMetas())
|
||||
|
||||
// Should be nil even if other settings are present
|
||||
repo.ExternalTrackerStyle = markup.ISSUE_NAME_STYLE_NUMERIC
|
||||
assert.Equal(t, map[string]string(nil), repo.ComposeMetas())
|
||||
metas := repo.ComposeMetas()
|
||||
assert.Equal(t, metas["repoLink"], repo.Link())
|
||||
|
||||
// Should no format and style if no external tracker is configured
|
||||
_, ok := metas["format"]
|
||||
assert.False(t, ok)
|
||||
_, ok = metas["style"]
|
||||
assert.False(t, ok)
|
||||
})
|
||||
|
||||
t.Run("an external issue tracker is configured", func(t *testing.T) {
|
||||
repo.ExternalMetas = nil
|
||||
repo.EnableExternalTracker = true
|
||||
|
||||
// Default to numeric issue style
|
||||
|
||||
@@ -17,10 +17,21 @@ import (
|
||||
var scpSyntax = lazyregexp.New(`^([a-zA-Z0-9_]+@)?([a-zA-Z0-9._-]+):(.*)$`)
|
||||
|
||||
// InferSubmoduleURL returns the inferred external URL of the submodule at best effort.
|
||||
func InferSubmoduleURL(mod *git.Submodule) string {
|
||||
// The `baseURL` should be the URL of the current repository. If the submodule URL looks
|
||||
// like a relative path, it assumes that the submodule is another repository on the same
|
||||
// Gogs instance by appending it to the `baseURL` with the commit.
|
||||
func InferSubmoduleURL(baseURL string, mod *git.Submodule) string {
|
||||
if !strings.HasSuffix(baseURL, "/") {
|
||||
baseURL += "/"
|
||||
}
|
||||
|
||||
raw := strings.TrimSuffix(mod.URL, "/")
|
||||
raw = strings.TrimSuffix(raw, ".git")
|
||||
|
||||
if strings.HasPrefix(raw, "../") {
|
||||
return fmt.Sprintf("%s%s/commit/%s", baseURL, raw, mod.Commit)
|
||||
}
|
||||
|
||||
parsed, err := url.Parse(raw)
|
||||
if err != nil {
|
||||
// Try parse as SCP syntax again
|
||||
|
||||
@@ -41,6 +41,14 @@ func TestInferSubmoduleURL(t *testing.T) {
|
||||
},
|
||||
expURL: "http://github.com/gogs/docs-api/commit/6b08f76a5313fa3d26859515b30aa17a5faa2807",
|
||||
},
|
||||
{
|
||||
name: "relative path",
|
||||
submodule: &git.Submodule{
|
||||
URL: "../repo2.git",
|
||||
Commit: "6b08f76a5313fa3d26859515b30aa17a5faa2807",
|
||||
},
|
||||
expURL: "https://gogs.example.com/user/repo/../repo2/commit/6b08f76a5313fa3d26859515b30aa17a5faa2807",
|
||||
},
|
||||
{
|
||||
name: "bad URL",
|
||||
submodule: &git.Submodule{
|
||||
@@ -52,7 +60,7 @@ func TestInferSubmoduleURL(t *testing.T) {
|
||||
}
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
assert.Equal(t, test.expURL, InferSubmoduleURL(test.submodule))
|
||||
assert.Equal(t, test.expURL, InferSubmoduleURL("https://gogs.example.com/user/repo", test.submodule))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,7 +145,8 @@ func RenderSha1CurrentPattern(rawBytes []byte, urlPrefix string) []byte {
|
||||
if com.StrTo(m).MustInt() > 0 {
|
||||
return m
|
||||
}
|
||||
return fmt.Sprintf(`<a href="%s/commit/%s"><code>%s</code></a>`, urlPrefix, m, tool.ShortSHA1(string(m)))
|
||||
|
||||
return fmt.Sprintf(`<a href="%s/commit/%s"><code>%s</code></a>`, urlPrefix, m, tool.ShortSHA1(m))
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -160,7 +161,7 @@ func RenderSpecialLink(rawBytes []byte, urlPrefix string, metas map[string]strin
|
||||
|
||||
rawBytes = RenderIssueIndexPattern(rawBytes, urlPrefix, metas)
|
||||
rawBytes = RenderCrossReferenceIssueIndexPattern(rawBytes, urlPrefix, metas)
|
||||
rawBytes = RenderSha1CurrentPattern(rawBytes, urlPrefix)
|
||||
rawBytes = RenderSha1CurrentPattern(rawBytes, metas["repoLink"])
|
||||
return rawBytes
|
||||
}
|
||||
|
||||
|
||||
@@ -215,3 +215,41 @@ func Test_RenderIssueIndexPattern(t *testing.T) {
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestRenderSha1CurrentPattern(t *testing.T) {
|
||||
metas := map[string]string{
|
||||
"repoLink": "/someuser/somerepo",
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
desc string
|
||||
input string
|
||||
prefix string
|
||||
expVal string
|
||||
}{
|
||||
{
|
||||
desc: "Full SHA (40 symbols)",
|
||||
input: "ad8ced4f57d9068cb2874557245be3c7f341149d",
|
||||
prefix: metas["repoLink"],
|
||||
expVal: `<a href="/someuser/somerepo/commit/ad8ced4f57d9068cb2874557245be3c7f341149d"><code>ad8ced4f57</code></a>`,
|
||||
},
|
||||
{
|
||||
desc: "Short SHA (8 symbols)",
|
||||
input: "ad8ced4f",
|
||||
prefix: metas["repoLink"],
|
||||
expVal: `<a href="/someuser/somerepo/commit/ad8ced4f"><code>ad8ced4f</code></a>`,
|
||||
},
|
||||
{
|
||||
desc: "9 digits",
|
||||
input: "123456789",
|
||||
prefix: metas["repoLink"],
|
||||
expVal: "123456789",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
assert.Equal(t, test.expVal, string(RenderSha1CurrentPattern([]byte(test.input), test.prefix)))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,6 +44,11 @@ func serveBatch(c *macaron.Context, owner *db.User, repo *db.Repository) {
|
||||
actions = batchActions{
|
||||
Upload: &batchAction{
|
||||
Href: fmt.Sprintf("%s/%s", baseHref, obj.Oid),
|
||||
Header: map[string]string{
|
||||
// NOTE: git-lfs v2.5.0 sets the Content-Type based on the uploaded file.
|
||||
// This ensures that the client always uses the designated value for the header.
|
||||
"Content-Type": "application/octet-stream",
|
||||
},
|
||||
},
|
||||
Verify: &batchAction{
|
||||
Href: fmt.Sprintf("%s/verify", baseHref),
|
||||
@@ -136,7 +141,8 @@ type batchError struct {
|
||||
}
|
||||
|
||||
type batchAction struct {
|
||||
Href string `json:"href"`
|
||||
Href string `json:"href"`
|
||||
Header map[string]string `json:"header,omitempty"`
|
||||
}
|
||||
|
||||
type batchActions struct {
|
||||
|
||||
@@ -6,6 +6,7 @@ package lfs
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
@@ -42,7 +43,7 @@ func Test_serveBatch(t *testing.T) {
|
||||
name: "unrecognized operation",
|
||||
body: `{"operation": "update"}`,
|
||||
expStatusCode: http.StatusBadRequest,
|
||||
expBody: `{"message":"Operation not recognized"}` + "\n",
|
||||
expBody: `{"message": "Operation not recognized"}` + "\n",
|
||||
},
|
||||
{
|
||||
name: "upload: contains invalid oid",
|
||||
@@ -53,7 +54,25 @@ func Test_serveBatch(t *testing.T) {
|
||||
{"oid": "ef797c8118f02dfb649607dd5d3f8c7623048c9c063d532cc95c5ed7a898a64f", "size": 123}
|
||||
]}`,
|
||||
expStatusCode: http.StatusOK,
|
||||
expBody: `{"transfer":"basic","objects":[{"oid":"bad_oid","size":123,"actions":{"error":{"code":422,"message":"Object has invalid oid"}}},{"oid":"ef797c8118f02dfb649607dd5d3f8c7623048c9c063d532cc95c5ed7a898a64f","size":123,"actions":{"upload":{"href":"https://gogs.example.com/owner/repo.git/info/lfs/objects/basic/ef797c8118f02dfb649607dd5d3f8c7623048c9c063d532cc95c5ed7a898a64f"},"verify":{"href":"https://gogs.example.com/owner/repo.git/info/lfs/objects/basic/verify"}}}]}` + "\n",
|
||||
expBody: `{
|
||||
"transfer": "basic",
|
||||
"objects": [
|
||||
{"oid": "bad_oid", "size":123, "actions": {"error": {"code": 422, "message": "Object has invalid oid"}}},
|
||||
{
|
||||
"oid": "ef797c8118f02dfb649607dd5d3f8c7623048c9c063d532cc95c5ed7a898a64f",
|
||||
"size": 123,
|
||||
"actions": {
|
||||
"upload": {
|
||||
"href": "https://gogs.example.com/owner/repo.git/info/lfs/objects/basic/ef797c8118f02dfb649607dd5d3f8c7623048c9c063d532cc95c5ed7a898a64f",
|
||||
"header": {"Content-Type": "application/octet-stream"}
|
||||
},
|
||||
"verify": {
|
||||
"href": "https://gogs.example.com/owner/repo.git/info/lfs/objects/basic/verify"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}` + "\n",
|
||||
},
|
||||
{
|
||||
name: "download: contains non-existent oid and mismatched size",
|
||||
@@ -78,7 +97,26 @@ func Test_serveBatch(t *testing.T) {
|
||||
},
|
||||
},
|
||||
expStatusCode: http.StatusOK,
|
||||
expBody: `{"transfer":"basic","objects":[{"oid":"bad_oid","size":123,"actions":{"error":{"code":404,"message":"Object does not exist"}}},{"oid":"ef797c8118f02dfb649607dd5d3f8c7623048c9c063d532cc95c5ed7a898a64f","size":123,"actions":{"error":{"code":422,"message":"Object size mismatch"}}},{"oid":"5cac0a318669fadfee734fb340a5f5b70b428ac57a9f4b109cb6e150b2ba7e57","size":456,"actions":{"download":{"href":"https://gogs.example.com/owner/repo.git/info/lfs/objects/basic/5cac0a318669fadfee734fb340a5f5b70b428ac57a9f4b109cb6e150b2ba7e57"}}}]}` + "\n",
|
||||
expBody: `{
|
||||
"transfer": "basic",
|
||||
"objects": [
|
||||
{"oid": "bad_oid", "size": 123, "actions": {"error": {"code": 404, "message": "Object does not exist"}}},
|
||||
{
|
||||
"oid": "ef797c8118f02dfb649607dd5d3f8c7623048c9c063d532cc95c5ed7a898a64f",
|
||||
"size": 123,
|
||||
"actions": {"error": {"code": 422, "message": "Object size mismatch"}}
|
||||
},
|
||||
{
|
||||
"oid": "5cac0a318669fadfee734fb340a5f5b70b428ac57a9f4b109cb6e150b2ba7e57",
|
||||
"size": 456,
|
||||
"actions": {
|
||||
"download": {
|
||||
"href": "https://gogs.example.com/owner/repo.git/info/lfs/objects/basic/5cac0a318669fadfee734fb340a5f5b70b428ac57a9f4b109cb6e150b2ba7e57"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}` + "\n",
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
@@ -100,7 +138,20 @@ func Test_serveBatch(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
assert.Equal(t, test.expBody, string(body))
|
||||
|
||||
var expBody bytes.Buffer
|
||||
err = json.Indent(&expBody, []byte(test.expBody), "", " ")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var gotBody bytes.Buffer
|
||||
err = json.Indent(&gotBody, body, "", " ")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
assert.Equal(t, expBody.String(), gotBody.String())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,6 +135,8 @@ func authorize(mode db.AccessMode) macaron.Handler {
|
||||
return
|
||||
}
|
||||
|
||||
log.Trace("[LFS] Authorized user %q to %q", actor.Name, username+"/"+reponame)
|
||||
|
||||
c.Map(owner) // NOTE: Override actor
|
||||
c.Map(repo)
|
||||
}
|
||||
@@ -144,10 +146,15 @@ func authorize(mode db.AccessMode) macaron.Handler {
|
||||
// When not, response given "failCode" as status code.
|
||||
func verifyHeader(key, value string, failCode int) macaron.Handler {
|
||||
return func(c *macaron.Context) {
|
||||
if !strings.Contains(c.Req.Header.Get(key), value) {
|
||||
c.Status(failCode)
|
||||
return
|
||||
vals := c.Req.Header.Values(key)
|
||||
for _, val := range vals {
|
||||
if strings.Contains(val, value) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
log.Trace("[LFS] HTTP header %q does not contain value %q", key, value)
|
||||
c.Status(failCode)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
{{if .Submodule}}
|
||||
<td>
|
||||
<span class="octicon octicon-file-submodule"></span>
|
||||
<a href="{{InferSubmoduleURL .Submodule}}">{{.Entry.Name}} @ {{ShortSHA1 .Submodule.Commit}}</a>
|
||||
<a href="{{InferSubmoduleURL $.RepoLink .Submodule}}">{{.Entry.Name}} @ {{ShortSHA1 .Submodule.Commit}}</a>
|
||||
</td>
|
||||
{{else}}
|
||||
<td class="name">
|
||||
|
||||
Reference in New Issue
Block a user