mirror of
https://github.com/gogs/gogs.git
synced 2026-03-01 09:40:55 +01:00
Compare commits
41 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bb005f3f9a | ||
|
|
e6dbfd918c | ||
|
|
c2f0711db0 | ||
|
|
92153fd898 | ||
|
|
a9d2480c7f | ||
|
|
fd70d503e0 | ||
|
|
8b73c8076f | ||
|
|
971a96a962 | ||
|
|
e9838a83ce | ||
|
|
837fc9847d | ||
|
|
7e883f891a | ||
|
|
e19a69442d | ||
|
|
ebd95dd082 | ||
|
|
f7b7d008b6 | ||
|
|
b39454ca16 | ||
|
|
00943a025f | ||
|
|
600f748cb0 | ||
|
|
038b107c3d | ||
|
|
c6e08d76fd | ||
|
|
6daac151b8 | ||
|
|
e08161a302 | ||
|
|
341eafcf04 | ||
|
|
dd649eb4cc | ||
|
|
d43f5f17fd | ||
|
|
193cc3ba9a | ||
|
|
fd667ca1d8 | ||
|
|
b0169ba064 | ||
|
|
ca2cfaf71e | ||
|
|
b06f299748 | ||
|
|
beea014343 | ||
|
|
70072e2842 | ||
|
|
f0086e66ae | ||
|
|
7fe13e72d8 | ||
|
|
87f0ce793d | ||
|
|
25cf755f30 | ||
|
|
c7a8051a71 | ||
|
|
a47553b7aa | ||
|
|
d7954014a4 | ||
|
|
429345b9df | ||
|
|
eaab01fa49 | ||
|
|
4f9c5981a9 |
4
.gitattributes
vendored
4
.gitattributes
vendored
@@ -5,7 +5,7 @@ public/plugins/* linguist-vendored
|
||||
public/plugins/* linguist-vendored
|
||||
public/css/themes/* linguist-vendored
|
||||
public/css/github.min.css linguist-vendored
|
||||
public/css/semantic-2.2.9.min.css linguist-vendored
|
||||
public/css/semantic-2.2.7.min.css linguist-vendored
|
||||
public/js/libs/* linguist-vendored
|
||||
public/js/jquery-1.11.3.min.js linguist-vendored
|
||||
public/js/semantic-2.2.9.min.js linguist-vendored
|
||||
public/js/semantic-2.2.7.min.js linguist-vendored
|
||||
1
.github/ISSUE_TEMPLATE.md
vendored
1
.github/ISSUE_TEMPLATE.md
vendored
@@ -13,6 +13,7 @@ The issue will be closed without any reasons if it does not satisfy any of follo
|
||||
- Database (use `[x]`):
|
||||
- [ ] PostgreSQL
|
||||
- [ ] MySQL
|
||||
- [ ] MSSQL
|
||||
- [ ] SQLite
|
||||
- Can you reproduce the bug at https://try.gogs.io:
|
||||
- [ ] Yes (provide example URL)
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
FROM aarch64/alpine:3.5
|
||||
MAINTAINER atzoum@gmail.com
|
||||
|
||||
# Install system utils & Gogs runtime dependencies
|
||||
ADD https://github.com/tianon/gosu/releases/download/1.9/gosu-arm64 /usr/sbin/gosu
|
||||
@@ -8,9 +7,12 @@ RUN chmod +x /usr/sbin/gosu \
|
||||
|
||||
ENV GOGS_CUSTOM /data/gogs
|
||||
|
||||
COPY . /app/gogs/
|
||||
WORKDIR /app/gogs/
|
||||
RUN ./docker/build.sh
|
||||
COPY . /app/gogs/build
|
||||
WORKDIR /app/gogs/build
|
||||
|
||||
RUN ./docker/build-go.sh \
|
||||
&& ./docker/build.sh \
|
||||
&& ./docker/finalize.sh
|
||||
|
||||
# Configure LibC Name Service
|
||||
COPY docker/nsswitch.conf /etc/nsswitch.conf
|
||||
@@ -18,5 +20,5 @@ COPY docker/nsswitch.conf /etc/nsswitch.conf
|
||||
# Configure Docker Container
|
||||
VOLUME ["/data"]
|
||||
EXPOSE 22 3000
|
||||
ENTRYPOINT ["docker/start.sh"]
|
||||
ENTRYPOINT ["/app/gogs/docker/start.sh"]
|
||||
CMD ["/bin/s6-svscan", "/app/gogs/docker/s6/"]
|
||||
|
||||
@@ -14,7 +14,7 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
CmdAdmin = cli.Command{
|
||||
Admin = cli.Command{
|
||||
Name: "admin",
|
||||
Usage: "Preform admin operations on command line",
|
||||
Description: `Allow using internal logic of Gogs without hacking into the source code
|
||||
|
||||
135
cmd/backup.go
Normal file
135
cmd/backup.go
Normal file
@@ -0,0 +1,135 @@
|
||||
// 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 cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"time"
|
||||
|
||||
"github.com/Unknwon/cae/zip"
|
||||
"github.com/Unknwon/com"
|
||||
"github.com/urfave/cli"
|
||||
log "gopkg.in/clog.v1"
|
||||
"gopkg.in/ini.v1"
|
||||
|
||||
"github.com/gogits/gogs/models"
|
||||
"github.com/gogits/gogs/modules/setting"
|
||||
)
|
||||
|
||||
var Backup = cli.Command{
|
||||
Name: "backup",
|
||||
Usage: "Backup files and database",
|
||||
Description: `Backup dumps and compresses all related files and database into zip file,
|
||||
which can be used for migrating Gogs to another server. The output format is meant to be
|
||||
portable among all supported database engines.`,
|
||||
Action: runBackup,
|
||||
Flags: []cli.Flag{
|
||||
stringFlag("config, c", "custom/conf/app.ini", "Custom configuration file path"),
|
||||
boolFlag("verbose, v", "Show process details"),
|
||||
stringFlag("tempdir, t", os.TempDir(), "Temporary directory path"),
|
||||
stringFlag("target", "./", "Target directory path to save backup archive"),
|
||||
boolFlag("database-only", "Only dump database"),
|
||||
boolFlag("exclude-repos", "Exclude repositories"),
|
||||
},
|
||||
}
|
||||
|
||||
const _ARCHIVE_ROOT_DIR = "gogs-backup"
|
||||
|
||||
func runBackup(c *cli.Context) error {
|
||||
zip.Verbose = c.Bool("verbose")
|
||||
if c.IsSet("config") {
|
||||
setting.CustomConf = c.String("config")
|
||||
}
|
||||
setting.NewContext()
|
||||
models.LoadConfigs()
|
||||
models.SetEngine()
|
||||
|
||||
tmpDir := c.String("tempdir")
|
||||
if !com.IsExist(tmpDir) {
|
||||
log.Fatal(0, "'--tempdir' does not exist: %s", tmpDir)
|
||||
}
|
||||
rootDir, err := ioutil.TempDir(tmpDir, "gogs-backup-")
|
||||
if err != nil {
|
||||
log.Fatal(0, "Fail to create backup root directory '%s': %v", rootDir, err)
|
||||
}
|
||||
log.Info("Backup root directory: %s", rootDir)
|
||||
|
||||
// Metadata
|
||||
metaFile := path.Join(rootDir, "metadata.ini")
|
||||
metadata := ini.Empty()
|
||||
metadata.Section("").Key("VERSION").SetValue("1")
|
||||
metadata.Section("").Key("DATE_TIME").SetValue(time.Now().String())
|
||||
metadata.Section("").Key("GOGS_VERSION").SetValue(setting.AppVer)
|
||||
if err = metadata.SaveTo(metaFile); err != nil {
|
||||
log.Fatal(0, "Fail to save metadata '%s': %v", metaFile, err)
|
||||
}
|
||||
|
||||
archiveName := path.Join(c.String("target"), fmt.Sprintf("gogs-backup-%d.zip", time.Now().Unix()))
|
||||
log.Info("Packing backup files to: %s", archiveName)
|
||||
|
||||
z, err := zip.Create(archiveName)
|
||||
if err != nil {
|
||||
log.Fatal(0, "Fail to create backup archive '%s': %v", archiveName, err)
|
||||
}
|
||||
if err = z.AddFile(_ARCHIVE_ROOT_DIR+"/metadata.ini", metaFile); err != nil {
|
||||
log.Fatal(0, "Fail to include 'metadata.ini': %v", err)
|
||||
}
|
||||
|
||||
// Database
|
||||
dbDir := path.Join(rootDir, "db")
|
||||
if err = models.DumpDatabase(dbDir); err != nil {
|
||||
log.Fatal(0, "Fail to dump database: %v", err)
|
||||
}
|
||||
if err = z.AddDir(_ARCHIVE_ROOT_DIR+"/db", dbDir); err != nil {
|
||||
log.Fatal(0, "Fail to include 'db': %v", err)
|
||||
}
|
||||
|
||||
// Custom files
|
||||
if !c.Bool("database-only") {
|
||||
if err = z.AddDir(_ARCHIVE_ROOT_DIR+"/custom", setting.CustomPath); err != nil {
|
||||
log.Fatal(0, "Fail to include 'custom': %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Data files
|
||||
if !c.Bool("database-only") {
|
||||
for _, dir := range []string{"attachments", "avatars"} {
|
||||
dirPath := path.Join(setting.AppDataPath, dir)
|
||||
if !com.IsDir(dirPath) {
|
||||
continue
|
||||
}
|
||||
|
||||
if err = z.AddDir(path.Join(_ARCHIVE_ROOT_DIR+"/data", dir), dirPath); err != nil {
|
||||
log.Fatal(0, "Fail to include 'data': %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Repositories
|
||||
if !c.Bool("exclude-repos") && !c.Bool("database-only") {
|
||||
reposDump := path.Join(rootDir, "repositories.zip")
|
||||
log.Info("Dumping repositories in '%s'", setting.RepoRootPath)
|
||||
if err = zip.PackTo(setting.RepoRootPath, reposDump, true); err != nil {
|
||||
log.Fatal(0, "Fail to dump repositories: %v", err)
|
||||
}
|
||||
log.Info("Repositories dumped to: %s", reposDump)
|
||||
|
||||
if err = z.AddFile(_ARCHIVE_ROOT_DIR+"/repositories.zip", reposDump); err != nil {
|
||||
log.Fatal(0, "Fail to include 'repositories.zip': %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
if err = z.Close(); err != nil {
|
||||
log.Fatal(0, "Fail to save backup archive '%s': %v", archiveName, err)
|
||||
}
|
||||
|
||||
os.RemoveAll(rootDir)
|
||||
log.Info("Backup succeed! Archive is located at: %s", archiveName)
|
||||
log.Shutdown()
|
||||
return nil
|
||||
}
|
||||
@@ -25,10 +25,10 @@ import (
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
var CmdCert = cli.Command{
|
||||
var Cert = cli.Command{
|
||||
Name: "cert",
|
||||
Usage: "Generate self-signed certificate",
|
||||
Description: `Generate a self-signed X.509 certificate for a TLS server.
|
||||
Description: `Generate a self-signed X.509 certificate for a TLS server.
|
||||
Outputs to 'cert.pem' and 'key.pem' and will overwrite existing files.`,
|
||||
Action: runCert,
|
||||
Flags: []cli.Flag{
|
||||
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
var CmdCert = cli.Command{
|
||||
var Cert = cli.Command{
|
||||
Name: "cert",
|
||||
Usage: "Generate self-signed certificate",
|
||||
Description: `Please use build tags "cert" to rebuild Gogs in order to have this ability`,
|
||||
|
||||
122
cmd/dump.go
122
cmd/dump.go
@@ -1,122 +0,0 @@
|
||||
// Copyright 2014 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 cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
"time"
|
||||
|
||||
"io/ioutil"
|
||||
|
||||
"github.com/Unknwon/cae/zip"
|
||||
"github.com/Unknwon/com"
|
||||
"github.com/urfave/cli"
|
||||
|
||||
"github.com/gogits/gogs/models"
|
||||
"github.com/gogits/gogs/modules/setting"
|
||||
)
|
||||
|
||||
var CmdDump = cli.Command{
|
||||
Name: "dump",
|
||||
Usage: "Dump Gogs files and database",
|
||||
Description: `Dump compresses all related files and database into zip file.
|
||||
It can be used for backup and capture Gogs server image to send to maintainer`,
|
||||
Action: runDump,
|
||||
Flags: []cli.Flag{
|
||||
stringFlag("config, c", "custom/conf/app.ini", "Custom configuration file path"),
|
||||
boolFlag("verbose, v", "Show process details"),
|
||||
stringFlag("tempdir, t", os.TempDir(), "Temporary dir path"),
|
||||
},
|
||||
}
|
||||
|
||||
func runDump(ctx *cli.Context) error {
|
||||
if ctx.IsSet("config") {
|
||||
setting.CustomConf = ctx.String("config")
|
||||
}
|
||||
setting.NewContext()
|
||||
models.LoadConfigs()
|
||||
models.SetEngine()
|
||||
|
||||
tmpDir := ctx.String("tempdir")
|
||||
if _, err := os.Stat(tmpDir); os.IsNotExist(err) {
|
||||
log.Fatalf("Path does not exist: %s", tmpDir)
|
||||
}
|
||||
TmpWorkDir, err := ioutil.TempDir(tmpDir, "gogs-dump-")
|
||||
if err != nil {
|
||||
log.Fatalf("Fail to create tmp work directory: %v", err)
|
||||
}
|
||||
log.Printf("Creating tmp work dir: %s", TmpWorkDir)
|
||||
|
||||
reposDump := path.Join(TmpWorkDir, "gogs-repo.zip")
|
||||
dbDump := path.Join(TmpWorkDir, "gogs-db.sql")
|
||||
|
||||
log.Printf("Dumping local repositories...%s", setting.RepoRootPath)
|
||||
zip.Verbose = ctx.Bool("verbose")
|
||||
if err := zip.PackTo(setting.RepoRootPath, reposDump, true); err != nil {
|
||||
log.Fatalf("Fail to dump local repositories: %v", err)
|
||||
}
|
||||
|
||||
log.Printf("Dumping database...")
|
||||
if err := models.DumpDatabase(dbDump); err != nil {
|
||||
log.Fatalf("Fail to dump database: %v", err)
|
||||
}
|
||||
|
||||
fileName := fmt.Sprintf("gogs-dump-%d.zip", time.Now().Unix())
|
||||
log.Printf("Packing dump files...")
|
||||
z, err := zip.Create(fileName)
|
||||
if err != nil {
|
||||
os.Remove(fileName)
|
||||
log.Fatalf("Fail to create %s: %v", fileName, err)
|
||||
}
|
||||
|
||||
if err := z.AddFile("gogs-repo.zip", reposDump); err != nil {
|
||||
log.Fatalf("Fail to include gogs-repo.zip: %v", err)
|
||||
}
|
||||
if err := z.AddFile("gogs-db.sql", dbDump); err != nil {
|
||||
log.Fatalf("Fail to include gogs-db.sql: %v", err)
|
||||
}
|
||||
customDir, err := os.Stat(setting.CustomPath)
|
||||
if err == nil && customDir.IsDir() {
|
||||
if err := z.AddDir("custom", setting.CustomPath); err != nil {
|
||||
log.Fatalf("Fail to include custom: %v", err)
|
||||
}
|
||||
} else {
|
||||
log.Printf("Custom dir %s doesn't exist, skipped", setting.CustomPath)
|
||||
}
|
||||
|
||||
if err := z.AddDir("log", setting.LogRootPath); err != nil {
|
||||
log.Fatalf("Fail to include log: %v", err)
|
||||
}
|
||||
|
||||
for _, dir := range []string{"attachments", "avatars"} {
|
||||
dirPath := path.Join(setting.AppDataPath, dir)
|
||||
if !com.IsDir(dirPath) {
|
||||
continue
|
||||
}
|
||||
|
||||
if err := z.AddDir(path.Join("data", dir), dirPath); err != nil {
|
||||
log.Fatalf("Fail to include '%s': %v", dirPath, err)
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: SSH key file.
|
||||
if err = z.Close(); err != nil {
|
||||
os.Remove(fileName)
|
||||
log.Fatalf("Fail to save %s: %v", fileName, err)
|
||||
}
|
||||
|
||||
if err := os.Chmod(fileName, 0600); err != nil {
|
||||
log.Printf("Can't change file access permissions mask to 0600: %v", err)
|
||||
}
|
||||
|
||||
log.Printf("Removing tmp work dir: %s", TmpWorkDir)
|
||||
os.RemoveAll(TmpWorkDir)
|
||||
log.Printf("Finish dumping in file %s", fileName)
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -27,7 +27,7 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
CmdHook = cli.Command{
|
||||
Hook = cli.Command{
|
||||
Name: "hook",
|
||||
Usage: "Delegate commands to corresponding Git hooks",
|
||||
Description: "All sub-commands should only be called by Git",
|
||||
@@ -117,7 +117,8 @@ func runHookPreReceive(c *cli.Context) error {
|
||||
}
|
||||
|
||||
// Check force push
|
||||
output, err := git.NewCommand("rev-list", oldCommitID, "^"+newCommitID).Run()
|
||||
output, err := git.NewCommand("rev-list", oldCommitID, "^"+newCommitID).
|
||||
RunInDir(models.RepoPath(os.Getenv(http.ENV_REPO_OWNER_NAME), os.Getenv(http.ENV_REPO_NAME)))
|
||||
if err != nil {
|
||||
fail("Internal error", "Fail to detect force push: %v", err)
|
||||
} else if len(output) > 0 {
|
||||
@@ -131,6 +132,7 @@ func runHookPreReceive(c *cli.Context) error {
|
||||
}
|
||||
|
||||
hookCmd := exec.Command(customHooksPath)
|
||||
hookCmd.Dir = models.RepoPath(os.Getenv(http.ENV_REPO_OWNER_NAME), os.Getenv(http.ENV_REPO_NAME))
|
||||
hookCmd.Stdout = os.Stdout
|
||||
hookCmd.Stdin = buf
|
||||
hookCmd.Stderr = os.Stderr
|
||||
@@ -159,6 +161,7 @@ func runHookUpdate(c *cli.Context) error {
|
||||
}
|
||||
|
||||
hookCmd := exec.Command(customHooksPath, args...)
|
||||
hookCmd.Dir = models.RepoPath(os.Getenv(http.ENV_REPO_OWNER_NAME), os.Getenv(http.ENV_REPO_NAME))
|
||||
hookCmd.Stdout = os.Stdout
|
||||
hookCmd.Stdin = os.Stdin
|
||||
hookCmd.Stderr = os.Stderr
|
||||
@@ -231,6 +234,7 @@ func runHookPostReceive(c *cli.Context) error {
|
||||
}
|
||||
|
||||
hookCmd := exec.Command(customHooksPath)
|
||||
hookCmd.Dir = models.RepoPath(os.Getenv(http.ENV_REPO_OWNER_NAME), os.Getenv(http.ENV_REPO_NAME))
|
||||
hookCmd.Stdout = os.Stdout
|
||||
hookCmd.Stdin = buf
|
||||
hookCmd.Stderr = os.Stderr
|
||||
|
||||
@@ -19,7 +19,7 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
CmdImport = cli.Command{
|
||||
Import = cli.Command{
|
||||
Name: "import",
|
||||
Usage: "Import portable data as local Gogs data",
|
||||
Description: `Allow user import data from other Gogs installations to local instance
|
||||
|
||||
129
cmd/restore.go
Normal file
129
cmd/restore.go
Normal file
@@ -0,0 +1,129 @@
|
||||
// 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 cmd
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path"
|
||||
|
||||
"github.com/Unknwon/cae/zip"
|
||||
"github.com/Unknwon/com"
|
||||
"github.com/mcuadros/go-version"
|
||||
"github.com/urfave/cli"
|
||||
log "gopkg.in/clog.v1"
|
||||
"gopkg.in/ini.v1"
|
||||
|
||||
"github.com/gogits/gogs/models"
|
||||
"github.com/gogits/gogs/modules/setting"
|
||||
)
|
||||
|
||||
var Restore = cli.Command{
|
||||
Name: "restore",
|
||||
Usage: "Restore files and database from backup",
|
||||
Description: `Restore imports all related files and database from a backup archive.
|
||||
The backup version must lower or equal to current Gogs version. You can also import
|
||||
backup from other database engines, which is useful for database migrating.
|
||||
|
||||
If corresponding files or database tables are not presented in the archive, they will
|
||||
be skipped and remian unchanged.`,
|
||||
Action: runRestore,
|
||||
Flags: []cli.Flag{
|
||||
stringFlag("config, c", "custom/conf/app.ini", "Custom configuration file path"),
|
||||
boolFlag("verbose, v", "Show process details"),
|
||||
stringFlag("tempdir, t", os.TempDir(), "Temporary directory path"),
|
||||
stringFlag("from", "", "Path to backup archive"),
|
||||
boolFlag("database-only", "Only import database"),
|
||||
boolFlag("exclude-repos", "Exclude repositories"),
|
||||
},
|
||||
}
|
||||
|
||||
func runRestore(c *cli.Context) error {
|
||||
zip.Verbose = c.Bool("verbose")
|
||||
|
||||
tmpDir := c.String("tempdir")
|
||||
if !com.IsExist(tmpDir) {
|
||||
log.Fatal(0, "'--tempdir' does not exist: %s", tmpDir)
|
||||
}
|
||||
|
||||
log.Info("Restore backup from: %s", c.String("from"))
|
||||
if err := zip.ExtractTo(c.String("from"), tmpDir); err != nil {
|
||||
log.Fatal(0, "Fail to extract backup archive: %v", err)
|
||||
}
|
||||
archivePath := path.Join(tmpDir, _ARCHIVE_ROOT_DIR)
|
||||
|
||||
// Check backup version
|
||||
metaFile := path.Join(archivePath, "metadata.ini")
|
||||
if !com.IsExist(metaFile) {
|
||||
log.Fatal(0, "File 'metadata.ini' is missing")
|
||||
}
|
||||
metadata, err := ini.Load(metaFile)
|
||||
if err != nil {
|
||||
log.Fatal(0, "Fail to load metadata '%s': %v", metaFile, err)
|
||||
}
|
||||
backupVersion := metadata.Section("").Key("GOGS_VERSION").MustString("999.0")
|
||||
if version.Compare(setting.AppVer, backupVersion, "<") {
|
||||
log.Fatal(0, "Current Gogs version is lower than backup version: %s < %s", setting.AppVer, backupVersion)
|
||||
}
|
||||
|
||||
// If config file is not present in backup, user must set this file via flag.
|
||||
// Otherwise, it's optional to set config file flag.
|
||||
configFile := path.Join(archivePath, "custom/conf/app.ini")
|
||||
if c.IsSet("config") {
|
||||
setting.CustomConf = c.String("config")
|
||||
} else if !com.IsExist(configFile) {
|
||||
log.Fatal(0, "'--config' is not specified and custom config file is not found in backup")
|
||||
} else {
|
||||
setting.CustomConf = configFile
|
||||
}
|
||||
setting.NewContext()
|
||||
models.LoadConfigs()
|
||||
models.SetEngine()
|
||||
|
||||
// Database
|
||||
dbDir := path.Join(archivePath, "db")
|
||||
if err = models.ImportDatabase(dbDir); err != nil {
|
||||
log.Fatal(0, "Fail to import database: %v", err)
|
||||
}
|
||||
|
||||
// Custom files
|
||||
if !c.Bool("database-only") {
|
||||
if com.IsExist(setting.CustomPath) {
|
||||
if err = os.Rename(setting.CustomPath, setting.CustomPath+".bak"); err != nil {
|
||||
log.Fatal(0, "Fail to backup current 'custom': %v", err)
|
||||
}
|
||||
}
|
||||
if err = os.Rename(path.Join(archivePath, "custom"), setting.CustomPath); err != nil {
|
||||
log.Fatal(0, "Fail to import 'custom': %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Data files
|
||||
if !c.Bool("database-only") {
|
||||
for _, dir := range []string{"attachments", "avatars"} {
|
||||
dirPath := path.Join(setting.AppDataPath, dir)
|
||||
if com.IsExist(dirPath) {
|
||||
if err = os.Rename(dirPath, dirPath+".bak"); err != nil {
|
||||
log.Fatal(0, "Fail to backup current 'data': %v", err)
|
||||
}
|
||||
}
|
||||
if err = os.Rename(path.Join(archivePath, "data", dir), dirPath); err != nil {
|
||||
log.Fatal(0, "Fail to import 'data': %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Repositories
|
||||
reposPath := path.Join(archivePath, "repositories.zip")
|
||||
if !c.Bool("exclude-repos") && !c.Bool("database-only") && com.IsExist(reposPath) {
|
||||
if err := zip.ExtractTo(reposPath, path.Dir(setting.RepoRootPath)); err != nil {
|
||||
log.Fatal(0, "Fail to extract 'repositories.zip': %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
os.RemoveAll(path.Join(tmpDir, _ARCHIVE_ROOT_DIR))
|
||||
log.Info("Restore succeed!")
|
||||
log.Shutdown()
|
||||
return nil
|
||||
}
|
||||
121
cmd/web.go
121
cmd/web.go
@@ -34,9 +34,9 @@ import (
|
||||
"github.com/gogits/go-gogs-client"
|
||||
|
||||
"github.com/gogits/gogs/models"
|
||||
"github.com/gogits/gogs/modules/auth"
|
||||
"github.com/gogits/gogs/modules/bindata"
|
||||
"github.com/gogits/gogs/modules/context"
|
||||
"github.com/gogits/gogs/modules/form"
|
||||
"github.com/gogits/gogs/modules/mailer"
|
||||
"github.com/gogits/gogs/modules/setting"
|
||||
"github.com/gogits/gogs/modules/template"
|
||||
@@ -49,9 +49,9 @@ import (
|
||||
"github.com/gogits/gogs/routers/user"
|
||||
)
|
||||
|
||||
var CmdWeb = cli.Command{
|
||||
var Web = cli.Command{
|
||||
Name: "web",
|
||||
Usage: "Start Gogs web server",
|
||||
Usage: "Start web server",
|
||||
Description: `Gogs web server is the only thing you need to run,
|
||||
and it takes care of all the other things for you`,
|
||||
Action: runWeb,
|
||||
@@ -219,35 +219,35 @@ func runWeb(ctx *cli.Context) error {
|
||||
m.Get("/organizations", routers.ExploreOrganizations)
|
||||
}, ignSignIn)
|
||||
m.Combo("/install", routers.InstallInit).Get(routers.Install).
|
||||
Post(bindIgnErr(auth.InstallForm{}), routers.InstallPost)
|
||||
Post(bindIgnErr(form.Install{}), routers.InstallPost)
|
||||
m.Get("/^:type(issues|pulls)$", reqSignIn, user.Issues)
|
||||
|
||||
// ***** START: User *****
|
||||
m.Group("/user", func() {
|
||||
m.Get("/login", user.SignIn)
|
||||
m.Post("/login", bindIgnErr(auth.SignInForm{}), user.SignInPost)
|
||||
m.Post("/login", bindIgnErr(form.SignIn{}), user.SignInPost)
|
||||
m.Get("/sign_up", user.SignUp)
|
||||
m.Post("/sign_up", bindIgnErr(auth.RegisterForm{}), user.SignUpPost)
|
||||
m.Post("/sign_up", bindIgnErr(form.Register{}), user.SignUpPost)
|
||||
m.Get("/reset_password", user.ResetPasswd)
|
||||
m.Post("/reset_password", user.ResetPasswdPost)
|
||||
}, reqSignOut)
|
||||
|
||||
m.Group("/user/settings", func() {
|
||||
m.Get("", user.Settings)
|
||||
m.Post("", bindIgnErr(auth.UpdateProfileForm{}), user.SettingsPost)
|
||||
m.Post("", bindIgnErr(form.UpdateProfile{}), user.SettingsPost)
|
||||
m.Combo("/avatar").Get(user.SettingsAvatar).
|
||||
Post(binding.MultipartForm(auth.AvatarForm{}), user.SettingsAvatarPost)
|
||||
Post(binding.MultipartForm(form.Avatar{}), user.SettingsAvatarPost)
|
||||
m.Post("/avatar/delete", user.SettingsDeleteAvatar)
|
||||
m.Combo("/email").Get(user.SettingsEmails).
|
||||
Post(bindIgnErr(auth.AddEmailForm{}), user.SettingsEmailPost)
|
||||
Post(bindIgnErr(form.AddEmail{}), user.SettingsEmailPost)
|
||||
m.Post("/email/delete", user.DeleteEmail)
|
||||
m.Get("/password", user.SettingsPassword)
|
||||
m.Post("/password", bindIgnErr(auth.ChangePasswordForm{}), user.SettingsPasswordPost)
|
||||
m.Post("/password", bindIgnErr(form.ChangePassword{}), user.SettingsPasswordPost)
|
||||
m.Combo("/ssh").Get(user.SettingsSSHKeys).
|
||||
Post(bindIgnErr(auth.AddSSHKeyForm{}), user.SettingsSSHKeysPost)
|
||||
Post(bindIgnErr(form.AddSSHKey{}), user.SettingsSSHKeysPost)
|
||||
m.Post("/ssh/delete", user.DeleteSSHKey)
|
||||
m.Combo("/applications").Get(user.SettingsApplications).
|
||||
Post(bindIgnErr(auth.NewAccessTokenForm{}), user.SettingsApplicationsPost)
|
||||
Post(bindIgnErr(form.NewAccessToken{}), user.SettingsApplicationsPost)
|
||||
m.Post("/applications/delete", user.SettingsDeleteApplication)
|
||||
|
||||
m.Group("/organizations", func() {
|
||||
@@ -261,7 +261,7 @@ func runWeb(ctx *cli.Context) error {
|
||||
})
|
||||
|
||||
m.Group("/user", func() {
|
||||
// r.Get("/feeds", binding.Bind(auth.FeedsForm{}), user.Feeds)
|
||||
// r.Get("/feeds", binding.Bind(form.Feeds{}), user.Feeds)
|
||||
m.Any("/activate", user.Activate)
|
||||
m.Any("/activate_email", user.ActivateEmail)
|
||||
m.Get("/email2user", user.Email2User)
|
||||
@@ -282,8 +282,8 @@ func runWeb(ctx *cli.Context) error {
|
||||
|
||||
m.Group("/users", func() {
|
||||
m.Get("", admin.Users)
|
||||
m.Combo("/new").Get(admin.NewUser).Post(bindIgnErr(auth.AdminCrateUserForm{}), admin.NewUserPost)
|
||||
m.Combo("/:userid").Get(admin.EditUser).Post(bindIgnErr(auth.AdminEditUserForm{}), admin.EditUserPost)
|
||||
m.Combo("/new").Get(admin.NewUser).Post(bindIgnErr(form.AdminCrateUser{}), admin.NewUserPost)
|
||||
m.Combo("/:userid").Get(admin.EditUser).Post(bindIgnErr(form.AdminEditUser{}), admin.EditUserPost)
|
||||
m.Post("/:userid/delete", admin.DeleteUser)
|
||||
})
|
||||
|
||||
@@ -298,9 +298,9 @@ func runWeb(ctx *cli.Context) error {
|
||||
|
||||
m.Group("/auths", func() {
|
||||
m.Get("", admin.Authentications)
|
||||
m.Combo("/new").Get(admin.NewAuthSource).Post(bindIgnErr(auth.AuthenticationForm{}), admin.NewAuthSourcePost)
|
||||
m.Combo("/new").Get(admin.NewAuthSource).Post(bindIgnErr(form.Authentication{}), admin.NewAuthSourcePost)
|
||||
m.Combo("/:authid").Get(admin.EditAuthSource).
|
||||
Post(bindIgnErr(auth.AuthenticationForm{}), admin.EditAuthSourcePost)
|
||||
Post(bindIgnErr(form.Authentication{}), admin.EditAuthSourcePost)
|
||||
m.Post("/:authid/delete", admin.DeleteAuthSource)
|
||||
})
|
||||
|
||||
@@ -365,7 +365,7 @@ func runWeb(ctx *cli.Context) error {
|
||||
m.Group("/org", func() {
|
||||
m.Group("", func() {
|
||||
m.Get("/create", org.Create)
|
||||
m.Post("/create", bindIgnErr(auth.CreateOrgForm{}), org.CreatePost)
|
||||
m.Post("/create", bindIgnErr(form.CreateOrg{}), org.CreatePost)
|
||||
}, func(ctx *context.Context) {
|
||||
if !ctx.User.CanCreateOrganization() {
|
||||
ctx.NotFound()
|
||||
@@ -390,28 +390,28 @@ func runWeb(ctx *cli.Context) error {
|
||||
|
||||
m.Group("/:org", func() {
|
||||
m.Get("/teams/new", org.NewTeam)
|
||||
m.Post("/teams/new", bindIgnErr(auth.CreateTeamForm{}), org.NewTeamPost)
|
||||
m.Post("/teams/new", bindIgnErr(form.CreateTeam{}), org.NewTeamPost)
|
||||
m.Get("/teams/:team/edit", org.EditTeam)
|
||||
m.Post("/teams/:team/edit", bindIgnErr(auth.CreateTeamForm{}), org.EditTeamPost)
|
||||
m.Post("/teams/:team/edit", bindIgnErr(form.CreateTeam{}), org.EditTeamPost)
|
||||
m.Post("/teams/:team/delete", org.DeleteTeam)
|
||||
|
||||
m.Group("/settings", func() {
|
||||
m.Combo("").Get(org.Settings).
|
||||
Post(bindIgnErr(auth.UpdateOrgSettingForm{}), org.SettingsPost)
|
||||
m.Post("/avatar", binding.MultipartForm(auth.AvatarForm{}), org.SettingsAvatar)
|
||||
Post(bindIgnErr(form.UpdateOrgSetting{}), org.SettingsPost)
|
||||
m.Post("/avatar", binding.MultipartForm(form.Avatar{}), org.SettingsAvatar)
|
||||
m.Post("/avatar/delete", org.SettingsDeleteAvatar)
|
||||
|
||||
m.Group("/hooks", func() {
|
||||
m.Get("", org.Webhooks)
|
||||
m.Post("/delete", org.DeleteWebhook)
|
||||
m.Get("/:type/new", repo.WebhooksNew)
|
||||
m.Post("/gogs/new", bindIgnErr(auth.NewWebhookForm{}), repo.WebHooksNewPost)
|
||||
m.Post("/slack/new", bindIgnErr(auth.NewSlackHookForm{}), repo.SlackHooksNewPost)
|
||||
m.Post("/discord/new", bindIgnErr(auth.NewDiscordHookForm{}), repo.DiscordHooksNewPost)
|
||||
m.Post("/gogs/new", bindIgnErr(form.NewWebhook{}), repo.WebHooksNewPost)
|
||||
m.Post("/slack/new", bindIgnErr(form.NewSlackHook{}), repo.SlackHooksNewPost)
|
||||
m.Post("/discord/new", bindIgnErr(form.NewDiscordHook{}), repo.DiscordHooksNewPost)
|
||||
m.Get("/:id", repo.WebHooksEdit)
|
||||
m.Post("/gogs/:id", bindIgnErr(auth.NewWebhookForm{}), repo.WebHooksEditPost)
|
||||
m.Post("/slack/:id", bindIgnErr(auth.NewSlackHookForm{}), repo.SlackHooksEditPost)
|
||||
m.Post("/discord/:id", bindIgnErr(auth.NewDiscordHookForm{}), repo.DiscordHooksEditPost)
|
||||
m.Post("/gogs/:id", bindIgnErr(form.NewWebhook{}), repo.WebHooksEditPost)
|
||||
m.Post("/slack/:id", bindIgnErr(form.NewSlackHook{}), repo.SlackHooksEditPost)
|
||||
m.Post("/discord/:id", bindIgnErr(form.NewDiscordHook{}), repo.DiscordHooksEditPost)
|
||||
})
|
||||
|
||||
m.Route("/delete", "GET,POST", org.SettingsDelete)
|
||||
@@ -425,17 +425,17 @@ func runWeb(ctx *cli.Context) error {
|
||||
// ***** START: Repository *****
|
||||
m.Group("/repo", func() {
|
||||
m.Get("/create", repo.Create)
|
||||
m.Post("/create", bindIgnErr(auth.CreateRepoForm{}), repo.CreatePost)
|
||||
m.Post("/create", bindIgnErr(form.CreateRepo{}), repo.CreatePost)
|
||||
m.Get("/migrate", repo.Migrate)
|
||||
m.Post("/migrate", bindIgnErr(auth.MigrateRepoForm{}), repo.MigratePost)
|
||||
m.Post("/migrate", bindIgnErr(form.MigrateRepo{}), repo.MigratePost)
|
||||
m.Combo("/fork/:repoid").Get(repo.Fork).
|
||||
Post(bindIgnErr(auth.CreateRepoForm{}), repo.ForkPost)
|
||||
Post(bindIgnErr(form.CreateRepo{}), repo.ForkPost)
|
||||
}, reqSignIn)
|
||||
|
||||
m.Group("/:username/:reponame", func() {
|
||||
m.Group("/settings", func() {
|
||||
m.Combo("").Get(repo.Settings).
|
||||
Post(bindIgnErr(auth.RepoSettingForm{}), repo.SettingsPost)
|
||||
Post(bindIgnErr(form.RepoSetting{}), repo.SettingsPost)
|
||||
m.Group("/collaboration", func() {
|
||||
m.Combo("").Get(repo.SettingsCollaboration).Post(repo.SettingsCollaborationPost)
|
||||
m.Post("/access_mode", repo.ChangeCollaborationAccessMode)
|
||||
@@ -445,7 +445,7 @@ func runWeb(ctx *cli.Context) error {
|
||||
m.Get("", repo.SettingsBranches)
|
||||
m.Post("/default_branch", repo.UpdateDefaultBranch)
|
||||
m.Combo("/*").Get(repo.SettingsProtectedBranch).
|
||||
Post(bindIgnErr(auth.ProtectBranchForm{}), repo.SettingsProtectedBranchPost)
|
||||
Post(bindIgnErr(form.ProtectBranch{}), repo.SettingsProtectedBranchPost)
|
||||
}, func(ctx *context.Context) {
|
||||
if ctx.Repo.Repository.IsMirror {
|
||||
ctx.NotFound()
|
||||
@@ -457,14 +457,14 @@ func runWeb(ctx *cli.Context) error {
|
||||
m.Get("", repo.Webhooks)
|
||||
m.Post("/delete", repo.DeleteWebhook)
|
||||
m.Get("/:type/new", repo.WebhooksNew)
|
||||
m.Post("/gogs/new", bindIgnErr(auth.NewWebhookForm{}), repo.WebHooksNewPost)
|
||||
m.Post("/slack/new", bindIgnErr(auth.NewSlackHookForm{}), repo.SlackHooksNewPost)
|
||||
m.Post("/discord/new", bindIgnErr(auth.NewDiscordHookForm{}), repo.DiscordHooksNewPost)
|
||||
m.Post("/gogs/new", bindIgnErr(form.NewWebhook{}), repo.WebHooksNewPost)
|
||||
m.Post("/slack/new", bindIgnErr(form.NewSlackHook{}), repo.SlackHooksNewPost)
|
||||
m.Post("/discord/new", bindIgnErr(form.NewDiscordHook{}), repo.DiscordHooksNewPost)
|
||||
m.Get("/:id", repo.WebHooksEdit)
|
||||
m.Post("/:id/test", repo.TestWebhook)
|
||||
m.Post("/gogs/:id", bindIgnErr(auth.NewWebhookForm{}), repo.WebHooksEditPost)
|
||||
m.Post("/slack/:id", bindIgnErr(auth.NewSlackHookForm{}), repo.SlackHooksEditPost)
|
||||
m.Post("/discord/:id", bindIgnErr(auth.NewDiscordHookForm{}), repo.DiscordHooksEditPost)
|
||||
m.Post("/gogs/:id", bindIgnErr(form.NewWebhook{}), repo.WebHooksEditPost)
|
||||
m.Post("/slack/:id", bindIgnErr(form.NewSlackHook{}), repo.SlackHooksEditPost)
|
||||
m.Post("/discord/:id", bindIgnErr(form.NewDiscordHook{}), repo.DiscordHooksEditPost)
|
||||
|
||||
m.Group("/git", func() {
|
||||
m.Get("", repo.SettingsGitHooks)
|
||||
@@ -475,7 +475,7 @@ func runWeb(ctx *cli.Context) error {
|
||||
|
||||
m.Group("/keys", func() {
|
||||
m.Combo("").Get(repo.SettingsDeployKeys).
|
||||
Post(bindIgnErr(auth.AddSSHKeyForm{}), repo.SettingsDeployKeysPost)
|
||||
Post(bindIgnErr(form.AddSSHKey{}), repo.SettingsDeployKeysPost)
|
||||
m.Post("/delete", repo.DeleteDeployKey)
|
||||
})
|
||||
|
||||
@@ -490,7 +490,7 @@ func runWeb(ctx *cli.Context) error {
|
||||
// So they can apply their own enable/disable logic on routers.
|
||||
m.Group("/issues", func() {
|
||||
m.Combo("/new", repo.MustEnableIssues).Get(context.RepoRef(), repo.NewIssue).
|
||||
Post(bindIgnErr(auth.CreateIssueForm{}), repo.NewIssuePost)
|
||||
Post(bindIgnErr(form.CreateIssue{}), repo.NewIssuePost)
|
||||
|
||||
m.Group("/:index", func() {
|
||||
m.Post("/label", repo.UpdateIssueLabel)
|
||||
@@ -501,7 +501,7 @@ func runWeb(ctx *cli.Context) error {
|
||||
m.Group("/:index", func() {
|
||||
m.Post("/title", repo.UpdateIssueTitle)
|
||||
m.Post("/content", repo.UpdateIssueContent)
|
||||
m.Combo("/comments").Post(bindIgnErr(auth.CreateCommentForm{}), repo.NewComment)
|
||||
m.Combo("/comments").Post(bindIgnErr(form.CreateComment{}), repo.NewComment)
|
||||
})
|
||||
})
|
||||
m.Group("/comments/:id", func() {
|
||||
@@ -509,26 +509,26 @@ func runWeb(ctx *cli.Context) error {
|
||||
m.Post("/delete", repo.DeleteComment)
|
||||
})
|
||||
m.Group("/labels", func() {
|
||||
m.Post("/new", bindIgnErr(auth.CreateLabelForm{}), repo.NewLabel)
|
||||
m.Post("/edit", bindIgnErr(auth.CreateLabelForm{}), repo.UpdateLabel)
|
||||
m.Post("/new", bindIgnErr(form.CreateLabel{}), repo.NewLabel)
|
||||
m.Post("/edit", bindIgnErr(form.CreateLabel{}), repo.UpdateLabel)
|
||||
m.Post("/delete", repo.DeleteLabel)
|
||||
m.Post("/initialize", bindIgnErr(auth.InitializeLabelsForm{}), repo.InitializeLabels)
|
||||
m.Post("/initialize", bindIgnErr(form.InitializeLabels{}), repo.InitializeLabels)
|
||||
}, reqRepoWriter, context.RepoRef())
|
||||
m.Group("/milestones", func() {
|
||||
m.Combo("/new").Get(repo.NewMilestone).
|
||||
Post(bindIgnErr(auth.CreateMilestoneForm{}), repo.NewMilestonePost)
|
||||
Post(bindIgnErr(form.CreateMilestone{}), repo.NewMilestonePost)
|
||||
m.Get("/:id/edit", repo.EditMilestone)
|
||||
m.Post("/:id/edit", bindIgnErr(auth.CreateMilestoneForm{}), repo.EditMilestonePost)
|
||||
m.Post("/:id/edit", bindIgnErr(form.CreateMilestone{}), repo.EditMilestonePost)
|
||||
m.Get("/:id/:action", repo.ChangeMilestonStatus)
|
||||
m.Post("/delete", repo.DeleteMilestone)
|
||||
}, reqRepoWriter, context.RepoRef())
|
||||
|
||||
m.Group("/releases", func() {
|
||||
m.Get("/new", repo.NewRelease)
|
||||
m.Post("/new", bindIgnErr(auth.NewReleaseForm{}), repo.NewReleasePost)
|
||||
m.Post("/new", bindIgnErr(form.NewRelease{}), repo.NewReleasePost)
|
||||
m.Post("/delete", repo.DeleteRelease)
|
||||
m.Get("/edit/*", repo.EditRelease)
|
||||
m.Post("/edit/*", bindIgnErr(auth.EditReleaseForm{}), repo.EditReleasePost)
|
||||
m.Post("/edit/*", bindIgnErr(form.EditRelease{}), repo.EditReleasePost)
|
||||
}, reqRepoWriter, context.RepoRef())
|
||||
|
||||
// FIXME: Should use ctx.Repo.PullRequest to unify template, currently we have inconsistent URL
|
||||
@@ -536,22 +536,22 @@ func runWeb(ctx *cli.Context) error {
|
||||
// e.g. /org1/test-repo/compare/master...org1:develop
|
||||
// which should be /org1/test-repo/compare/master...develop
|
||||
m.Combo("/compare/*", repo.MustAllowPulls).Get(repo.CompareAndPullRequest).
|
||||
Post(bindIgnErr(auth.CreateIssueForm{}), repo.CompareAndPullRequestPost)
|
||||
Post(bindIgnErr(form.CreateIssue{}), repo.CompareAndPullRequestPost)
|
||||
|
||||
m.Group("", func() {
|
||||
m.Combo("/_edit/*").Get(repo.EditFile).
|
||||
Post(bindIgnErr(auth.EditRepoFileForm{}), repo.EditFilePost)
|
||||
Post(bindIgnErr(form.EditRepoFile{}), repo.EditFilePost)
|
||||
m.Combo("/_new/*").Get(repo.NewFile).
|
||||
Post(bindIgnErr(auth.EditRepoFileForm{}), repo.NewFilePost)
|
||||
m.Post("/_preview/*", bindIgnErr(auth.EditPreviewDiffForm{}), repo.DiffPreviewPost)
|
||||
Post(bindIgnErr(form.EditRepoFile{}), repo.NewFilePost)
|
||||
m.Post("/_preview/*", bindIgnErr(form.EditPreviewDiff{}), repo.DiffPreviewPost)
|
||||
m.Combo("/_delete/*").Get(repo.DeleteFile).
|
||||
Post(bindIgnErr(auth.DeleteRepoFileForm{}), repo.DeleteFilePost)
|
||||
Post(bindIgnErr(form.DeleteRepoFile{}), repo.DeleteFilePost)
|
||||
|
||||
m.Group("", func() {
|
||||
m.Combo("/_upload/*").Get(repo.UploadFile).
|
||||
Post(bindIgnErr(auth.UploadRepoFileForm{}), repo.UploadFilePost)
|
||||
Post(bindIgnErr(form.UploadRepoFile{}), repo.UploadFilePost)
|
||||
m.Post("/upload-file", repo.UploadFileToServer)
|
||||
m.Post("/upload-remove", bindIgnErr(auth.RemoveUploadFileForm{}), repo.RemoveUploadFileFromServer)
|
||||
m.Post("/upload-remove", bindIgnErr(form.RemoveUploadFile{}), repo.RemoveUploadFileFromServer)
|
||||
}, func(ctx *context.Context) {
|
||||
if !setting.Repository.Upload.Enabled {
|
||||
ctx.NotFound()
|
||||
@@ -584,9 +584,9 @@ func runWeb(ctx *cli.Context) error {
|
||||
|
||||
m.Group("", func() {
|
||||
m.Combo("/_new").Get(repo.NewWiki).
|
||||
Post(bindIgnErr(auth.NewWikiForm{}), repo.NewWikiPost)
|
||||
Post(bindIgnErr(form.NewWiki{}), repo.NewWikiPost)
|
||||
m.Combo("/:page/_edit").Get(repo.EditWiki).
|
||||
Post(bindIgnErr(auth.NewWikiForm{}), repo.EditWikiPost)
|
||||
Post(bindIgnErr(form.NewWiki{}), repo.EditWikiPost)
|
||||
m.Post("/:page/delete", repo.DeleteWikiPagePost)
|
||||
}, reqSignIn, reqRepoWriter)
|
||||
}, repo.MustEnableWiki, context.RepoRef())
|
||||
@@ -623,11 +623,14 @@ func runWeb(ctx *cli.Context) error {
|
||||
m.Group("/:reponame", func() {
|
||||
m.Head("/tasks/trigger", repo.TriggerTask)
|
||||
})
|
||||
// Use the regexp to match the repository name validation
|
||||
// Use the regexp to match the repository name
|
||||
// Duplicated routes to enable different ways of accessing same set of URLs,
|
||||
// e.g. with or without ".git" suffix.
|
||||
m.Group("/:reponame([\\d\\w-_\\.]+\\.git$)", func() {
|
||||
m.Get("", ignSignIn, context.RepoAssignment(true), context.RepoRef(), repo.Home)
|
||||
m.Route("/*", "GET,POST", ignSignInAndCsrf, repo.HTTPContexter(), repo.HTTP)
|
||||
})
|
||||
m.Route("/:reponame/*", "GET,POST", ignSignInAndCsrf, repo.HTTPContexter(), repo.HTTP)
|
||||
})
|
||||
// ***** END: Repository *****
|
||||
|
||||
|
||||
@@ -218,8 +218,8 @@ FROM =
|
||||
; Mailer user name and password
|
||||
USER =
|
||||
PASSWD =
|
||||
; Use text/html as alternative format of content
|
||||
ENABLE_HTML_ALTERNATIVE = false
|
||||
; Use text/plain as format of content
|
||||
USE_PLAIN_TEXT = false
|
||||
|
||||
[cache]
|
||||
; Either "memory", "redis", or "memcache", default is "memory"
|
||||
|
||||
@@ -1,24 +1,25 @@
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
|
||||
# Icon must end with two \r
|
||||
Icon
|
||||
|
||||
# Thumbnails
|
||||
._*
|
||||
|
||||
# Files that might appear in the root of a volume
|
||||
.DocumentRevisions-V100
|
||||
.fseventsd
|
||||
.Spotlight-V100
|
||||
.TemporaryItems
|
||||
.Trashes
|
||||
.VolumeIcon.icns
|
||||
|
||||
# Directories potentially created on remote AFP share
|
||||
.AppleDB
|
||||
.AppleDesktop
|
||||
Network Trash Folder
|
||||
Temporary Items
|
||||
.apdisk
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
|
||||
# Icon must end with two \r
|
||||
Icon
|
||||
|
||||
|
||||
# Thumbnails
|
||||
._*
|
||||
|
||||
# Files that might appear in the root of a volume
|
||||
.DocumentRevisions-V100
|
||||
.fseventsd
|
||||
.Spotlight-V100
|
||||
.TemporaryItems
|
||||
.Trashes
|
||||
.VolumeIcon.icns
|
||||
|
||||
# Directories potentially created on remote AFP share
|
||||
.AppleDB
|
||||
.AppleDesktop
|
||||
Network Trash Folder
|
||||
Temporary Items
|
||||
.apdisk
|
||||
@@ -18,6 +18,8 @@ Antoine GIRARD <sapk AT sapk DOT fr>
|
||||
Arthur Aslanyan <arthur DOT e DOT aslanyan AT gmail DOT com>
|
||||
Aurelien Darragon <aurelien DOT darragon AT gmail DOT com>
|
||||
Barış Arda Yılmaz <ardayilmazgamer AT gmail DOT com>
|
||||
Bo-Yi Wu <appleboy DOT tw AT gmail DOT com>
|
||||
Breton Corentin <contact AT neodarz DOT net>
|
||||
Camille Baronnet <gogs AT camillebaronnet DOT fr>
|
||||
Christoph Kisfeld <christoph DOT kisfeld AT gmail DOT com>
|
||||
Cysioland
|
||||
|
||||
@@ -654,7 +654,7 @@ settings.protect_this_branch=Diesen Branch schützen
|
||||
settings.protect_this_branch_desc=Verhindere forcierte Pushes sowie Löschungen.
|
||||
settings.protect_require_pull_request=Verlange Pull-Request an Stelle von direkten Pushes
|
||||
settings.protect_require_pull_request_desc=Aktivieren Sie diese Option, um direktes Pushen in diesen Branch zu verhindern. Commits müssen in einen anderen, ungeschützten Branch gepusht werden und dann per Pull-Request in diesen Branch überführt werden.
|
||||
settings.protect_whitelist_committers=Fügt die Benutzer zu Whitelist hinzu, die in diesen Branch pushen dürfen
|
||||
settings.protect_whitelist_committers=Hinzufügen von Benutzern oder Teams zur Whitelist, die in diesen Branch pushen dürfen
|
||||
settings.protect_whitelist_committers_desc=Benutzer oder Teams zur Whitelist hinzufügen.
|
||||
settings.protect_whitelist_users=Benutzer, die in diesen Branch pushen können
|
||||
settings.protect_whitelist_search_users=Benutzer suchen
|
||||
@@ -688,7 +688,7 @@ settings.tracker_issue_style.alphanumeric=Alphanumerisch
|
||||
settings.tracker_url_format_desc=Sie können die Platzhalter <code>{user} {repo} {index}</code> für den Benutzernamen, den Namen des Repositories und die Issue-Nummer verwenden.
|
||||
settings.pulls_desc=Pull-Requests aktivieren, um öffentliche Mitwirkung zu ermöglichen
|
||||
settings.danger_zone=Gefahrenzone
|
||||
settings.cannot_fork_to_same_owner=You cannot fork a repository to its original owner.
|
||||
settings.cannot_fork_to_same_owner=Besitzer kann das Repository nicht forken.
|
||||
settings.new_owner_has_same_repo=Der neue Eigentümer hat bereits ein Repository mit dem gleichen Namen. Bitte wählen Sie einen anderen Namen.
|
||||
settings.convert=In ein normales Repository umwandeln
|
||||
settings.convert_desc=Dieser Mirror kann in ein normales Repository umgewandelt werden. Dies kann nicht rückgängig gemacht werden.
|
||||
@@ -745,7 +745,7 @@ settings.add_webhook_desc=Gogs sendet einen <code>POST</code>-Request an die unt
|
||||
settings.payload_url=Payload URL
|
||||
settings.content_type=Inhaltstyp
|
||||
settings.secret=Secret
|
||||
settings.secret_desc=Secret will be sent as SHA256 HMAC hex digest of payload via <code>X-Gogs-Signature</code> header.
|
||||
settings.secret_desc=Das Secret wird im <code>X-Gogs-Signature</code> Header als hexadezimalem SHA256 HMAC Stempel der Nutzlast.
|
||||
settings.slack_username=Benutzername
|
||||
settings.slack_icon_url=Icon URL
|
||||
settings.slack_color=Farbe
|
||||
|
||||
@@ -201,6 +201,7 @@ Content = Content
|
||||
require_error = ` cannot be empty.`
|
||||
alpha_dash_error = ` must be valid alpha or numeric or dash(-_) characters.`
|
||||
alpha_dash_dot_error = ` must be valid alpha or numeric or dash(-_) or dot characters.`
|
||||
alpha_dash_dot_slash_error = ` must be valid alpha or numeric or dash(-_) or dot characters or slashes.`
|
||||
size_error = ` must be size %s.`
|
||||
min_size_error = ` must contain at least %s characters.`
|
||||
max_size_error = ` must contain at most %s characters.`
|
||||
@@ -754,7 +755,11 @@ settings.event_push_only = Just the <code>push</code> event.
|
||||
settings.event_send_everything = I need <strong>everything</strong>.
|
||||
settings.event_choose = Let me choose what I need.
|
||||
settings.event_create = Create
|
||||
settings.event_create_desc = Branch, or tag created
|
||||
settings.event_create_desc = Branch or tag created
|
||||
settings.event_delete = Delete
|
||||
settings.event_delete_desc = Branch or tag deleted
|
||||
settings.event_fork = Fork
|
||||
settings.event_fork_desc = Repository forked
|
||||
settings.event_pull_request = Pull Request
|
||||
settings.event_pull_request_desc = Pull request opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, or synchronized.
|
||||
settings.event_push = Push
|
||||
@@ -1176,7 +1181,8 @@ config.git_pull_timeout = Pull Operation Timeout
|
||||
config.git_gc_timeout = GC Operation Timeout
|
||||
|
||||
config.log_config = Log Configuration
|
||||
config.log_mode = Log Mode
|
||||
config.log_mode = Mode
|
||||
config.log_options = Options
|
||||
|
||||
monitor.cron = Cron Tasks
|
||||
monitor.name = Name
|
||||
@@ -1205,19 +1211,23 @@ notices.delete_success = System notices have been deleted successfully.
|
||||
|
||||
[action]
|
||||
create_repo = created repository <a href="%s">%s</a>
|
||||
fork_repo = forked a repository to <a href="%s">%s</a>
|
||||
rename_repo = renamed repository from <code>%[1]s</code> to <a href="%[2]s">%[3]s</a>
|
||||
commit_repo = pushed to <a href="%[1]s/src/%[2]s">%[3]s</a> at <a href="%[1]s">%[4]s</a>
|
||||
compare_commits = View comparison for these %d commits
|
||||
transfer_repo = transfered repository <code>%s</code> to <a href="%s">%s</a>
|
||||
create_issue = `opened issue <a href="%s/issues/%s">%s#%[2]s</a>`
|
||||
close_issue = `closed issue <a href="%s/issues/%s">%s#%[2]s</a>`
|
||||
reopen_issue = `reopened issue <a href="%s/issues/%s">%s#%[2]s</a>`
|
||||
comment_issue = `commented on issue <a href="%s/issues/%s">%s#%[2]s</a>`
|
||||
create_pull_request = `created pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
|
||||
close_pull_request = `closed pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
|
||||
reopen_pull_request = `reopened pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
|
||||
comment_issue = `commented on issue <a href="%s/issues/%s">%s#%[2]s</a>`
|
||||
merge_pull_request = `merged pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
|
||||
transfer_repo = transfered repository <code>%s</code> to <a href="%s">%s</a>
|
||||
create_branch = created new branch <a href="%[1]s/src/%[2]s">%[3]s</a> at <a href="%[1]s">%[4]s</a>
|
||||
delete_branch = deleted branch <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
|
||||
push_tag = pushed tag <a href="%s/src/%s">%[2]s</a> to <a href="%[1]s">%[3]s</a>
|
||||
compare_commits = View comparison for these %d commits
|
||||
delete_tag = deleted tag <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
|
||||
|
||||
[tool]
|
||||
ago = ago
|
||||
|
||||
@@ -399,7 +399,7 @@ migrate.failed=Echec de migration: %v
|
||||
mirror_from=miroir de
|
||||
forked_from=forké depuis
|
||||
copy_link=Copier
|
||||
copy_link_success=Copié!
|
||||
copy_link_success=Copié !
|
||||
copy_link_error=Appuyez sur ⌘-C ou Ctrl-C pour copier
|
||||
copied=Copié
|
||||
unwatch=Ne plus suivre
|
||||
@@ -423,7 +423,7 @@ branches=Branches
|
||||
tags=Tags
|
||||
issues=Tickets
|
||||
pulls=Pull Requests
|
||||
labels=Etiquettes
|
||||
labels=Étiquettes
|
||||
milestones=Jalons
|
||||
commits=Commits
|
||||
releases=Publications
|
||||
@@ -484,7 +484,7 @@ commits.older=Précédemment
|
||||
commits.newer=Récemment
|
||||
|
||||
issues.new=Nouveau ticket
|
||||
issues.new.labels=Etiquettes
|
||||
issues.new.labels=Étiquettes
|
||||
issues.new.no_label=Pas d'étiquette
|
||||
issues.new.clear_labels=Effacer les étiquettes
|
||||
issues.new.milestone=Jalon
|
||||
@@ -688,7 +688,7 @@ settings.tracker_issue_style.alphanumeric=Alphanumérique
|
||||
settings.tracker_url_format_desc=Vous pouvez utiliser l'espace réservé <code>{user} {repo} {index}</code> pour le nom d'utilisateur, le nom du dépôt et le numéro de bug.
|
||||
settings.pulls_desc=Activer les pull requests pour accepter les contributions publiques
|
||||
settings.danger_zone=Zone de danger
|
||||
settings.cannot_fork_to_same_owner=You cannot fork a repository to its original owner.
|
||||
settings.cannot_fork_to_same_owner=Vous ne pouvez par créer un fork d'un dépot à son propriétaire actuel.
|
||||
settings.new_owner_has_same_repo=Le nouveau propriétaire a déjà un dépôt nommé ainsi.
|
||||
settings.convert=Convertir en dépôt ordinaire
|
||||
settings.convert_desc=Vous pouvez convertir ce miroir en dépôt ordinaire. Cela ne peut pas être inversée.
|
||||
@@ -745,7 +745,7 @@ settings.add_webhook_desc=Une requête <code>POST</code> sera transmise vers l'U
|
||||
settings.payload_url=URL des Données Utiles
|
||||
settings.content_type=Type de contenu
|
||||
settings.secret=Confidentiel
|
||||
settings.secret_desc=Secret will be sent as SHA256 HMAC hex digest of payload via <code>X-Gogs-Signature</code> header.
|
||||
settings.secret_desc=Le secret sera envoyé comme digest de payload SHA256 HMAC hex avec l'entête <code>X-Gogs-Signature</code>.
|
||||
settings.slack_username=Nom d'utilisateur
|
||||
settings.slack_icon_url=URL de l'icône
|
||||
settings.slack_color=Couleur
|
||||
@@ -786,7 +786,7 @@ settings.deploy_key_deletion=Supprimer la Clé de Déploiement
|
||||
settings.deploy_key_deletion_desc=Supprimer cette clé de déploiement effacera tous les accès relatifs pour ce référentiel. Voulez-vous continuer ?
|
||||
settings.deploy_key_deletion_success=La clé de déploiement a été supprimée avec succès !
|
||||
|
||||
diff.browse_source=Parcourir la Source
|
||||
diff.browse_source=Parcourir la source
|
||||
diff.parent=Parent
|
||||
diff.commit=commit
|
||||
diff.data_not_available=Données Diff indisponibles.
|
||||
|
||||
@@ -531,7 +531,7 @@ issues.next=Páxina seguinte
|
||||
issues.open_title=Aberta
|
||||
issues.closed_title=Cerrada
|
||||
issues.num_comments=%d comentarios
|
||||
issues.commented_at='comentado <a href="#%s"> %s'</a>
|
||||
issues.commented_at=`comentado <a href="#%s"> %s'</a>`
|
||||
issues.delete_comment_confirm=Seguro que desexas eliminar este comentario?
|
||||
issues.no_content=Aínda non existe contido.
|
||||
issues.close_issue=Cerrar
|
||||
|
||||
@@ -531,7 +531,7 @@ issues.next=Следующая страница
|
||||
issues.open_title=Открыто
|
||||
issues.closed_title=Закрыто
|
||||
issues.num_comments=комментариев: %d
|
||||
issues.commented_at=«прокомментировал <a href="#%s"> %s</a>»
|
||||
issues.commented_at=`прокомментировал <a href="#%s"> %s</a>`
|
||||
issues.delete_comment_confirm=Вы уверены, что хотите удалить этот комментарий?
|
||||
issues.no_content=Пока нет содержимого.
|
||||
issues.close_issue=Закрыть
|
||||
|
||||
@@ -688,7 +688,7 @@ settings.tracker_issue_style.alphanumeric=Буквено-цифровий
|
||||
settings.tracker_url_format_desc=Ви можете використовувати заповнювач <code>{user} {repo} {index}</code> для ім'я користувача, назви репозиторію на номеру проблеми.
|
||||
settings.pulls_desc=Увімкнути публічні запроси на злиття
|
||||
settings.danger_zone=Небезпечна зона
|
||||
settings.cannot_fork_to_same_owner=You cannot fork a repository to its original owner.
|
||||
settings.cannot_fork_to_same_owner=Ви не можете клонувати репозиторій його ж власнику.
|
||||
settings.new_owner_has_same_repo=Новий власник вже має репозиторій з такою назвою.
|
||||
settings.convert=Перетворити на звичайний репозиторій
|
||||
settings.convert_desc=Ви можете сконвертувати це дзеркало у звичайний репозиторій. Це не може бути повернуто.
|
||||
@@ -745,7 +745,7 @@ settings.add_webhook_desc=Gogs відправляє <code>POST</code> запит
|
||||
settings.payload_url=URL розробника
|
||||
settings.content_type=Тип змісту
|
||||
settings.secret=Таємний код
|
||||
settings.secret_desc=Secret will be sent as SHA256 HMAC hex digest of payload via <code>X-Gogs-Signature</code> header.
|
||||
settings.secret_desc=Секрет буде вислано SHA256 HMAC hex-сумою вміста у хідері <code>X-Gogs-Signature</code>.
|
||||
settings.slack_username=Ім'я користувача
|
||||
settings.slack_icon_url=URL іконки
|
||||
settings.slack_color=Колір
|
||||
|
||||
@@ -656,10 +656,10 @@ settings.protect_require_pull_request=請使用 pull request 來更新(合併)
|
||||
settings.protect_require_pull_request_desc=啟用這個選項之後,程式碼將無法直接 Push 到這個分支,所有 Commit 必須先 Push 到另一個非保護的分支,再透過 Pull Request 來要求合併。
|
||||
settings.protect_whitelist_committers=限制誰可以 Push 到這個分支
|
||||
settings.protect_whitelist_committers_desc=新增用戶或團隊到可以直接push到這個分支的白名單。
|
||||
settings.protect_whitelist_users=Users who can push to this branch
|
||||
settings.protect_whitelist_search_users=Search users
|
||||
settings.protect_whitelist_users=限制那些使用者可以 push 到這個分支
|
||||
settings.protect_whitelist_search_users=搜尋用戶
|
||||
settings.protect_whitelist_teams=Teams for which members of them can push to this branch
|
||||
settings.protect_whitelist_search_teams=Search teams
|
||||
settings.protect_whitelist_search_teams=搜尋團隊
|
||||
settings.update_protect_branch_success=此分支設置保護已更新成功!
|
||||
settings.hooks=管理 Web 鉤子
|
||||
settings.githooks=管理 Git 鉤子
|
||||
|
||||
@@ -65,7 +65,7 @@ $ docker run --name=gogs -p 10022:22 -p 10080:3000 -v gogs-data:/data gogs/gogs
|
||||
Most of settings are obvious and easy to understand, but there are some settings can be confusing by running Gogs inside Docker:
|
||||
|
||||
- **Repository Root Path**: keep it as default value `/home/git/gogs-repositories` because `start.sh` already made a symbolic link for you.
|
||||
- **Run User**: keep it as default value `git` because `start.sh` already setup a user with name `git`.
|
||||
- **Run User**: keep it as default value `git` because `build.sh` already setup a user with name `git`.
|
||||
- **Domain**: fill in with Docker container IP (e.g. `192.168.99.100`). But if you want to access your Gogs instance from a different physical machine, please fill in with the hostname or IP address of the Docker host machine.
|
||||
- **SSH Port**: Use the exposed port from Docker container. For example, your SSH server listens on `22` inside Docker, **but** you expose it by `10022:22`, then use `10022` for this value. **Builtin SSH server is not recommended inside Docker Container**
|
||||
- **HTTP Port**: Use port you want Gogs to listen on inside Docker container. For example, your Gogs listens on `3000` inside Docker, **and** you expose it by `10080:3000`, but you still use `3000` for this value.
|
||||
@@ -112,4 +112,4 @@ Steps to upgrade Gogs with Docker:
|
||||
|
||||
## Useful Links
|
||||
|
||||
- [Share port 22 between Gogs inside Docker & the local system](http://www.ateijelo.com/blog/2016/07/09/share-port-22-between-docker-gogs-ssh-and-local-system)
|
||||
- [Share port 22 between Gogs inside Docker & the local system](http://www.ateijelo.com/blog/2016/07/09/share-port-22-between-docker-gogs-ssh-and-local-system)
|
||||
|
||||
15
gogs.go
15
gogs.go
@@ -16,7 +16,7 @@ import (
|
||||
"github.com/gogits/gogs/modules/setting"
|
||||
)
|
||||
|
||||
const APP_VER = "0.10.1.0228"
|
||||
const APP_VER = "0.10.8.0307"
|
||||
|
||||
func init() {
|
||||
setting.AppVer = APP_VER
|
||||
@@ -28,13 +28,14 @@ func main() {
|
||||
app.Usage = "A painless self-hosted Git service"
|
||||
app.Version = APP_VER
|
||||
app.Commands = []cli.Command{
|
||||
cmd.CmdWeb,
|
||||
cmd.Web,
|
||||
cmd.Serv,
|
||||
cmd.CmdHook,
|
||||
cmd.CmdDump,
|
||||
cmd.CmdCert,
|
||||
cmd.CmdAdmin,
|
||||
cmd.CmdImport,
|
||||
cmd.Hook,
|
||||
cmd.Cert,
|
||||
cmd.Admin,
|
||||
cmd.Import,
|
||||
cmd.Backup,
|
||||
cmd.Restore,
|
||||
}
|
||||
app.Flags = append(app.Flags, []cli.Flag{}...)
|
||||
app.Run(os.Args)
|
||||
|
||||
141
models/action.go
141
models/action.go
@@ -26,6 +26,7 @@ import (
|
||||
|
||||
type ActionType int
|
||||
|
||||
// To maintain backward compatibility only append to the end of list
|
||||
const (
|
||||
ACTION_CREATE_REPO ActionType = iota + 1 // 1
|
||||
ACTION_RENAME_REPO // 2
|
||||
@@ -42,6 +43,10 @@ const (
|
||||
ACTION_REOPEN_ISSUE // 13
|
||||
ACTION_CLOSE_PULL_REQUEST // 14
|
||||
ACTION_REOPEN_PULL_REQUEST // 15
|
||||
ACTION_CREATE_BRANCH // 16
|
||||
ACTION_DELETE_BRANCH // 17
|
||||
ACTION_DELETE_TAG // 18
|
||||
ACTION_FORK_REPO // 19
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -66,7 +71,7 @@ func init() {
|
||||
// Action represents user operation type and other information to repository,
|
||||
// it implemented interface base.Actioner so that can be used in template render.
|
||||
type Action struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
ID int64
|
||||
UserID int64 // Receiver user id.
|
||||
OpType ActionType
|
||||
ActUserID int64 // Action user id.
|
||||
@@ -172,26 +177,26 @@ func (a *Action) GetIssueContent() string {
|
||||
return issue.Content
|
||||
}
|
||||
|
||||
func newRepoAction(e Engine, u *User, repo *Repository) (err error) {
|
||||
if err = notifyWatchers(e, &Action{
|
||||
ActUserID: u.ID,
|
||||
ActUserName: u.Name,
|
||||
OpType: ACTION_CREATE_REPO,
|
||||
func newRepoAction(e Engine, doer, owner *User, repo *Repository) (err error) {
|
||||
opType := ACTION_CREATE_REPO
|
||||
if repo.IsFork {
|
||||
opType = ACTION_FORK_REPO
|
||||
}
|
||||
|
||||
return notifyWatchers(e, &Action{
|
||||
ActUserID: doer.ID,
|
||||
ActUserName: doer.Name,
|
||||
OpType: opType,
|
||||
RepoID: repo.ID,
|
||||
RepoUserName: repo.Owner.Name,
|
||||
RepoName: repo.Name,
|
||||
IsPrivate: repo.IsPrivate,
|
||||
}); err != nil {
|
||||
return fmt.Errorf("notify watchers '%d/%d': %v", u.ID, repo.ID, err)
|
||||
}
|
||||
|
||||
log.Trace("action.newRepoAction: %s/%s", u.Name, repo.Name)
|
||||
return err
|
||||
})
|
||||
}
|
||||
|
||||
// NewRepoAction adds new action for creating repository.
|
||||
func NewRepoAction(u *User, repo *Repository) (err error) {
|
||||
return newRepoAction(x, u, repo)
|
||||
func NewRepoAction(doer, owner *User, repo *Repository) (err error) {
|
||||
return newRepoAction(x, doer, owner, repo)
|
||||
}
|
||||
|
||||
func renameRepoAction(e Engine, actUser *User, oldRepoName string, repo *Repository) (err error) {
|
||||
@@ -458,18 +463,16 @@ func CommitRepoAction(opts CommitRepoActionOptions) error {
|
||||
return fmt.Errorf("UpdateRepository: %v", err)
|
||||
}
|
||||
|
||||
isNewBranch := false
|
||||
isNewRef := opts.OldCommitID == git.EMPTY_SHA
|
||||
isDelRef := opts.NewCommitID == git.EMPTY_SHA
|
||||
|
||||
opType := ACTION_COMMIT_REPO
|
||||
// Check it's tag push or branch.
|
||||
// Check if it's tag push or branch.
|
||||
if strings.HasPrefix(opts.RefFullName, git.TAG_PREFIX) {
|
||||
opType = ACTION_PUSH_TAG
|
||||
opts.Commits = &PushCommits{}
|
||||
} else {
|
||||
// TODO: detect branch deletion
|
||||
// if not the first commit, set the compare URL.
|
||||
if opts.OldCommitID == git.EMPTY_SHA {
|
||||
isNewBranch = true
|
||||
} else {
|
||||
if !isNewRef && !isDelRef {
|
||||
opts.Commits.CompareURL = repo.ComposeCompareURL(opts.OldCommitID, opts.NewCommitID)
|
||||
}
|
||||
|
||||
@@ -488,38 +491,57 @@ func CommitRepoAction(opts CommitRepoActionOptions) error {
|
||||
}
|
||||
|
||||
refName := git.RefEndName(opts.RefFullName)
|
||||
if err = NotifyWatchers(&Action{
|
||||
action := &Action{
|
||||
ActUserID: pusher.ID,
|
||||
ActUserName: pusher.Name,
|
||||
OpType: opType,
|
||||
Content: string(data),
|
||||
RepoID: repo.ID,
|
||||
RepoUserName: repo.MustOwner().Name,
|
||||
RepoName: repo.Name,
|
||||
RefName: refName,
|
||||
IsPrivate: repo.IsPrivate,
|
||||
}); err != nil {
|
||||
return fmt.Errorf("NotifyWatchers: %v", err)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
go HookQueue.Add(repo.ID)
|
||||
}()
|
||||
|
||||
apiPusher := pusher.APIFormat()
|
||||
apiRepo := repo.APIFormat(nil)
|
||||
apiPusher := pusher.APIFormat()
|
||||
switch opType {
|
||||
case ACTION_COMMIT_REPO: // Push
|
||||
if isDelRef {
|
||||
if err = PrepareWebhooks(repo, HOOK_EVENT_DELETE, &api.DeletePayload{
|
||||
Ref: refName,
|
||||
RefType: "branch",
|
||||
PusherType: api.PUSHER_TYPE_USER,
|
||||
Repo: apiRepo,
|
||||
Sender: apiPusher,
|
||||
}); err != nil {
|
||||
return fmt.Errorf("PrepareWebhooks.(delete branch): %v", err)
|
||||
}
|
||||
|
||||
action.OpType = ACTION_DELETE_BRANCH
|
||||
if err = NotifyWatchers(action); err != nil {
|
||||
return fmt.Errorf("NotifyWatchers.(delete branch): %v", err)
|
||||
}
|
||||
|
||||
// Delete branch doesn't have anything to push or compare
|
||||
return nil
|
||||
}
|
||||
|
||||
compareURL := setting.AppUrl + opts.Commits.CompareURL
|
||||
if isNewBranch {
|
||||
if isNewRef {
|
||||
compareURL = ""
|
||||
if err = PrepareWebhooks(repo, HOOK_EVENT_CREATE, &api.CreatePayload{
|
||||
Ref: refName,
|
||||
RefType: "branch",
|
||||
Repo: apiRepo,
|
||||
Sender: apiPusher,
|
||||
Ref: refName,
|
||||
RefType: "branch",
|
||||
DefaultBranch: repo.DefaultBranch,
|
||||
Repo: apiRepo,
|
||||
Sender: apiPusher,
|
||||
}); err != nil {
|
||||
return fmt.Errorf("PrepareWebhooks (new branch): %v", err)
|
||||
return fmt.Errorf("PrepareWebhooks.(new branch): %v", err)
|
||||
}
|
||||
|
||||
action.OpType = ACTION_CREATE_BRANCH
|
||||
if err = NotifyWatchers(action); err != nil {
|
||||
return fmt.Errorf("NotifyWatchers.(new branch): %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -533,16 +555,47 @@ func CommitRepoAction(opts CommitRepoActionOptions) error {
|
||||
Pusher: apiPusher,
|
||||
Sender: apiPusher,
|
||||
}); err != nil {
|
||||
return fmt.Errorf("PrepareWebhooks (new commit): %v", err)
|
||||
return fmt.Errorf("PrepareWebhooks.(new commit): %v", err)
|
||||
}
|
||||
|
||||
case ACTION_PUSH_TAG: // Create
|
||||
return PrepareWebhooks(repo, HOOK_EVENT_CREATE, &api.CreatePayload{
|
||||
Ref: refName,
|
||||
RefType: "tag",
|
||||
Repo: apiRepo,
|
||||
Sender: apiPusher,
|
||||
})
|
||||
action.OpType = ACTION_COMMIT_REPO
|
||||
if err = NotifyWatchers(action); err != nil {
|
||||
return fmt.Errorf("NotifyWatchers.(new commit): %v", err)
|
||||
}
|
||||
|
||||
case ACTION_PUSH_TAG: // Tag
|
||||
if isDelRef {
|
||||
if err = PrepareWebhooks(repo, HOOK_EVENT_DELETE, &api.DeletePayload{
|
||||
Ref: refName,
|
||||
RefType: "tag",
|
||||
PusherType: api.PUSHER_TYPE_USER,
|
||||
Repo: apiRepo,
|
||||
Sender: apiPusher,
|
||||
}); err != nil {
|
||||
return fmt.Errorf("PrepareWebhooks.(delete tag): %v", err)
|
||||
}
|
||||
|
||||
action.OpType = ACTION_DELETE_TAG
|
||||
if err = NotifyWatchers(action); err != nil {
|
||||
return fmt.Errorf("NotifyWatchers.(delete tag): %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if err = PrepareWebhooks(repo, HOOK_EVENT_CREATE, &api.CreatePayload{
|
||||
Ref: refName,
|
||||
RefType: "tag",
|
||||
DefaultBranch: repo.DefaultBranch,
|
||||
Repo: apiRepo,
|
||||
Sender: apiPusher,
|
||||
}); err != nil {
|
||||
return fmt.Errorf("PrepareWebhooks.(new tag): %v", err)
|
||||
}
|
||||
|
||||
action.OpType = ACTION_PUSH_TAG
|
||||
if err = NotifyWatchers(action); err != nil {
|
||||
return fmt.Errorf("NotifyWatchers.(new tag): %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -42,7 +42,7 @@ func (m *migration) Migrate(x *xorm.Engine) error {
|
||||
|
||||
// The version table. Should have only one row with id==1
|
||||
type Version struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
ID int64
|
||||
Version int64
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,9 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
@@ -13,6 +15,7 @@ import (
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/Unknwon/com"
|
||||
_ "github.com/denisenkom/go-mssqldb"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/go-xorm/core"
|
||||
@@ -262,7 +265,89 @@ func Ping() error {
|
||||
return x.Ping()
|
||||
}
|
||||
|
||||
// DumpDatabase dumps all data from database to file system.
|
||||
func DumpDatabase(filePath string) error {
|
||||
return x.DumpAllToFile(filePath)
|
||||
// The version table. Should have only one row with id==1
|
||||
type Version struct {
|
||||
ID int64
|
||||
Version int64
|
||||
}
|
||||
|
||||
// DumpDatabase dumps all data from database to file system in JSON format.
|
||||
func DumpDatabase(dirPath string) (err error) {
|
||||
os.MkdirAll(dirPath, os.ModePerm)
|
||||
// Purposely create a local variable to not modify global variable
|
||||
tables := append(tables, new(Version))
|
||||
for _, table := range tables {
|
||||
tableName := strings.TrimPrefix(fmt.Sprintf("%T", table), "*models.")
|
||||
tableFile := path.Join(dirPath, tableName+".json")
|
||||
f, err := os.Create(tableFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("fail to create JSON file: %v", err)
|
||||
}
|
||||
|
||||
if err = x.Asc("id").Iterate(table, func(idx int, bean interface{}) (err error) {
|
||||
enc := json.NewEncoder(f)
|
||||
return enc.Encode(bean)
|
||||
}); err != nil {
|
||||
f.Close()
|
||||
return fmt.Errorf("fail to dump table '%s': %v", tableName, err)
|
||||
}
|
||||
f.Close()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ImportDatabase imports data from backup archive.
|
||||
func ImportDatabase(dirPath string) (err error) {
|
||||
// Purposely create a local variable to not modify global variable
|
||||
tables := append(tables, new(Version))
|
||||
for _, table := range tables {
|
||||
tableName := strings.TrimPrefix(fmt.Sprintf("%T", table), "*models.")
|
||||
tableFile := path.Join(dirPath, tableName+".json")
|
||||
if !com.IsExist(tableFile) {
|
||||
continue
|
||||
}
|
||||
|
||||
if err = x.DropTables(table); err != nil {
|
||||
return fmt.Errorf("fail to drop table '%s': %v", tableName, err)
|
||||
} else if err = x.Sync2(table); err != nil {
|
||||
return fmt.Errorf("fail to sync table '%s': %v", tableName, err)
|
||||
}
|
||||
|
||||
f, err := os.Open(tableFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("fail to open JSON file: %v", err)
|
||||
}
|
||||
scanner := bufio.NewScanner(f)
|
||||
for scanner.Scan() {
|
||||
switch bean := table.(type) {
|
||||
case *LoginSource:
|
||||
meta := make(map[string]interface{})
|
||||
if err = json.Unmarshal(scanner.Bytes(), &meta); err != nil {
|
||||
return fmt.Errorf("fail to unmarshal to map: %v", err)
|
||||
}
|
||||
|
||||
tp := LoginType(com.StrTo(com.ToStr(meta["Type"])).MustInt64())
|
||||
switch tp {
|
||||
case LOGIN_LDAP, LOGIN_DLDAP:
|
||||
bean.Cfg = new(LDAPConfig)
|
||||
case LOGIN_SMTP:
|
||||
bean.Cfg = new(SMTPConfig)
|
||||
case LOGIN_PAM:
|
||||
bean.Cfg = new(PAMConfig)
|
||||
default:
|
||||
return fmt.Errorf("unrecognized login source type:: %v", tp)
|
||||
}
|
||||
table = bean
|
||||
}
|
||||
|
||||
if err = json.Unmarshal(scanner.Bytes(), table); err != nil {
|
||||
return fmt.Errorf("fail to unmarshal to struct: %v", err)
|
||||
}
|
||||
|
||||
if _, err = x.Insert(table); err != nil {
|
||||
return fmt.Errorf("fail to insert strcut: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -20,8 +20,8 @@ var (
|
||||
)
|
||||
|
||||
// IsOwnedBy returns true if given user is in the owner team.
|
||||
func (org *User) IsOwnedBy(uid int64) bool {
|
||||
return IsOrganizationOwner(org.ID, uid)
|
||||
func (org *User) IsOwnedBy(userID int64) bool {
|
||||
return IsOrganizationOwner(org.ID, userID)
|
||||
}
|
||||
|
||||
// IsOrgMember returns true if given user is member of organization.
|
||||
@@ -246,8 +246,8 @@ type OrgUser struct {
|
||||
}
|
||||
|
||||
// IsOrganizationOwner returns true if given user is in the owner team.
|
||||
func IsOrganizationOwner(orgId, uid int64) bool {
|
||||
has, _ := x.Where("is_owner=?", true).And("uid=?", uid).And("org_id=?", orgId).Get(new(OrgUser))
|
||||
func IsOrganizationOwner(orgID, userID int64) bool {
|
||||
has, _ := x.Where("is_owner = ?", true).And("uid = ?", userID).And("org_id = ?", orgID).Get(new(OrgUser))
|
||||
return has
|
||||
}
|
||||
|
||||
@@ -303,16 +303,15 @@ func GetOwnedOrgsByUserIDDesc(userID int64, desc string) ([]*User, error) {
|
||||
return getOwnedOrgsByUserID(sess.Desc(desc), userID)
|
||||
}
|
||||
|
||||
// GetOrgUsersByUserID returns all organization-user relations by user ID.
|
||||
func GetOrgUsersByUserID(uid int64, all bool) ([]*OrgUser, error) {
|
||||
ous := make([]*OrgUser, 0, 10)
|
||||
sess := x.Where("uid=?", uid)
|
||||
if !all {
|
||||
// Only show public organizations
|
||||
sess.And("is_public=?", true)
|
||||
// GetOrgIDsByUserID returns a list of organization IDs that user belongs to.
|
||||
// The showPrivate indicates whether to include private memberships.
|
||||
func GetOrgIDsByUserID(userID int64, showPrivate bool) ([]int64, error) {
|
||||
orgIDs := make([]int64, 0, 5)
|
||||
sess := x.Table("org_user").Where("uid = ?", userID)
|
||||
if !showPrivate {
|
||||
sess.And("is_public = ?", true)
|
||||
}
|
||||
err := sess.Find(&ous)
|
||||
return ous, err
|
||||
return orgIDs, sess.Distinct("org_id").Find(&orgIDs)
|
||||
}
|
||||
|
||||
func getOrgUsersByOrgID(e Engine, orgID int64) ([]*OrgUser, error) {
|
||||
|
||||
111
models/repo.go
111
models/repo.go
@@ -628,8 +628,8 @@ func wikiRemoteURL(remote string) string {
|
||||
}
|
||||
|
||||
// MigrateRepository migrates a existing repository from other project hosting.
|
||||
func MigrateRepository(u *User, opts MigrateRepoOptions) (*Repository, error) {
|
||||
repo, err := CreateRepository(u, CreateRepoOptions{
|
||||
func MigrateRepository(doer, owner *User, opts MigrateRepoOptions) (*Repository, error) {
|
||||
repo, err := CreateRepository(doer, owner, CreateRepoOptions{
|
||||
Name: opts.Name,
|
||||
Description: opts.Description,
|
||||
IsPrivate: opts.IsPrivate,
|
||||
@@ -639,11 +639,11 @@ func MigrateRepository(u *User, opts MigrateRepoOptions) (*Repository, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
repoPath := RepoPath(u.Name, opts.Name)
|
||||
wikiPath := WikiPath(u.Name, opts.Name)
|
||||
repoPath := RepoPath(owner.Name, opts.Name)
|
||||
wikiPath := WikiPath(owner.Name, opts.Name)
|
||||
|
||||
if u.IsOrganization() {
|
||||
t, err := u.GetOwnerTeam()
|
||||
if owner.IsOrganization() {
|
||||
t, err := owner.GetOwnerTeam()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -882,8 +882,8 @@ func prepareRepoCommit(repo *Repository, tmpDir, repoPath string, opts CreateRep
|
||||
return nil
|
||||
}
|
||||
|
||||
// InitRepository initializes README and .gitignore if needed.
|
||||
func initRepository(e Engine, repoPath string, u *User, repo *Repository, opts CreateRepoOptions) (err error) {
|
||||
// initRepository performs initial commit with chosen setup files on behave of doer.
|
||||
func initRepository(e Engine, repoPath string, doer *User, repo *Repository, opts CreateRepoOptions) (err error) {
|
||||
// Somehow the directory could exist.
|
||||
if com.IsExist(repoPath) {
|
||||
return fmt.Errorf("initRepository: path already exists: %s", repoPath)
|
||||
@@ -908,7 +908,7 @@ func initRepository(e Engine, repoPath string, u *User, repo *Repository, opts C
|
||||
}
|
||||
|
||||
// Apply changes and commit.
|
||||
if err = initRepoCommit(tmpDir, u.NewGitSig()); err != nil {
|
||||
if err = initRepoCommit(tmpDir, doer.NewGitSig()); err != nil {
|
||||
return fmt.Errorf("initRepoCommit: %v", err)
|
||||
}
|
||||
}
|
||||
@@ -941,32 +941,32 @@ func IsUsableRepoName(name string) error {
|
||||
return isUsableName(reservedRepoNames, reservedRepoPatterns, name)
|
||||
}
|
||||
|
||||
func createRepository(e *xorm.Session, u *User, repo *Repository) (err error) {
|
||||
func createRepository(e *xorm.Session, doer, owner *User, repo *Repository) (err error) {
|
||||
if err = IsUsableRepoName(repo.Name); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
has, err := isRepositoryExist(e, u, repo.Name)
|
||||
has, err := isRepositoryExist(e, owner, repo.Name)
|
||||
if err != nil {
|
||||
return fmt.Errorf("IsRepositoryExist: %v", err)
|
||||
} else if has {
|
||||
return ErrRepoAlreadyExist{u.Name, repo.Name}
|
||||
return ErrRepoAlreadyExist{owner.Name, repo.Name}
|
||||
}
|
||||
|
||||
if _, err = e.Insert(repo); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
u.NumRepos++
|
||||
owner.NumRepos++
|
||||
// Remember visibility preference.
|
||||
u.LastRepoVisibility = repo.IsPrivate
|
||||
if err = updateUser(e, u); err != nil {
|
||||
owner.LastRepoVisibility = repo.IsPrivate
|
||||
if err = updateUser(e, owner); err != nil {
|
||||
return fmt.Errorf("updateUser: %v", err)
|
||||
}
|
||||
|
||||
// Give access to all members in owner team.
|
||||
if u.IsOrganization() {
|
||||
t, err := u.getOwnerTeam(e)
|
||||
if owner.IsOrganization() {
|
||||
t, err := owner.getOwnerTeam(e)
|
||||
if err != nil {
|
||||
return fmt.Errorf("getOwnerTeam: %v", err)
|
||||
} else if err = t.addRepository(e, repo); err != nil {
|
||||
@@ -979,9 +979,9 @@ func createRepository(e *xorm.Session, u *User, repo *Repository) (err error) {
|
||||
}
|
||||
}
|
||||
|
||||
if err = watchRepo(e, u.ID, repo.ID, true); err != nil {
|
||||
if err = watchRepo(e, owner.ID, repo.ID, true); err != nil {
|
||||
return fmt.Errorf("watchRepo: %v", err)
|
||||
} else if err = newRepoAction(e, u, repo); err != nil {
|
||||
} else if err = newRepoAction(e, doer, owner, repo); err != nil {
|
||||
return fmt.Errorf("newRepoAction: %v", err)
|
||||
}
|
||||
|
||||
@@ -989,14 +989,14 @@ func createRepository(e *xorm.Session, u *User, repo *Repository) (err error) {
|
||||
}
|
||||
|
||||
// CreateRepository creates a repository for given user or organization.
|
||||
func CreateRepository(u *User, opts CreateRepoOptions) (_ *Repository, err error) {
|
||||
if !u.CanCreateRepo() {
|
||||
return nil, ErrReachLimitOfRepo{u.MaxRepoCreation}
|
||||
func CreateRepository(doer, owner *User, opts CreateRepoOptions) (_ *Repository, err error) {
|
||||
if !owner.CanCreateRepo() {
|
||||
return nil, ErrReachLimitOfRepo{owner.MaxRepoCreation}
|
||||
}
|
||||
|
||||
repo := &Repository{
|
||||
OwnerID: u.ID,
|
||||
Owner: u,
|
||||
OwnerID: owner.ID,
|
||||
Owner: owner,
|
||||
Name: opts.Name,
|
||||
LowerName: strings.ToLower(opts.Name),
|
||||
Description: opts.Description,
|
||||
@@ -1012,14 +1012,14 @@ func CreateRepository(u *User, opts CreateRepoOptions) (_ *Repository, err error
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err = createRepository(sess, u, repo); err != nil {
|
||||
if err = createRepository(sess, doer, owner, repo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// No need for init mirror.
|
||||
if !opts.IsMirror {
|
||||
repoPath := RepoPath(u.Name, repo.Name)
|
||||
if err = initRepository(sess, repoPath, u, repo, opts); err != nil {
|
||||
repoPath := RepoPath(owner.Name, repo.Name)
|
||||
if err = initRepository(sess, repoPath, doer, repo, opts); err != nil {
|
||||
RemoveAllWithNotice("Delete repository for initialization failure", repoPath)
|
||||
return nil, fmt.Errorf("initRepository: %v", err)
|
||||
}
|
||||
@@ -2068,25 +2068,28 @@ func (repo *Repository) GetWatchers(page int) ([]*User, error) {
|
||||
|
||||
func notifyWatchers(e Engine, act *Action) error {
|
||||
// Add feeds for user self and all watchers.
|
||||
watches, err := getWatchers(e, act.RepoID)
|
||||
watchers, err := getWatchers(e, act.RepoID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("get watchers: %v", err)
|
||||
return fmt.Errorf("getWatchers: %v", err)
|
||||
}
|
||||
|
||||
// Reset ID to reuse Action object
|
||||
act.ID = 0
|
||||
|
||||
// Add feed for actioner.
|
||||
act.UserID = act.ActUserID
|
||||
if _, err = e.InsertOne(act); err != nil {
|
||||
return fmt.Errorf("insert new actioner: %v", err)
|
||||
if _, err = e.Insert(act); err != nil {
|
||||
return fmt.Errorf("insert new action: %v", err)
|
||||
}
|
||||
|
||||
for i := range watches {
|
||||
if act.ActUserID == watches[i].UserID {
|
||||
for i := range watchers {
|
||||
if act.ActUserID == watchers[i].UserID {
|
||||
continue
|
||||
}
|
||||
|
||||
act.ID = 0
|
||||
act.UserID = watches[i].UserID
|
||||
if _, err = e.InsertOne(act); err != nil {
|
||||
act.UserID = watchers[i].UserID
|
||||
if _, err = e.Insert(act); err != nil {
|
||||
return fmt.Errorf("insert new action: %v", err)
|
||||
}
|
||||
}
|
||||
@@ -2161,24 +2164,26 @@ func (repo *Repository) GetStargazers(page int) ([]*User, error) {
|
||||
// \___ / \____/|__| |__|_ \
|
||||
// \/ \/
|
||||
|
||||
// HasForkedRepo checks if given user has already forked a repository with given ID.
|
||||
// HasForkedRepo checks if given user has already forked a repository.
|
||||
// When user has already forked, it returns true along with the repository.
|
||||
func HasForkedRepo(ownerID, repoID int64) (*Repository, bool) {
|
||||
repo := new(Repository)
|
||||
has, _ := x.Where("owner_id=? AND fork_id=?", ownerID, repoID).Get(repo)
|
||||
has, _ := x.Where("owner_id = ? AND fork_id = ?", ownerID, repoID).Get(repo)
|
||||
return repo, has
|
||||
}
|
||||
|
||||
func ForkRepository(u *User, oldRepo *Repository, name, desc string) (_ *Repository, err error) {
|
||||
// ForkRepository creates a fork of target repository under another user domain.
|
||||
func ForkRepository(doer, owner *User, baseRepo *Repository, name, desc string) (_ *Repository, err error) {
|
||||
repo := &Repository{
|
||||
OwnerID: u.ID,
|
||||
Owner: u,
|
||||
OwnerID: owner.ID,
|
||||
Owner: owner,
|
||||
Name: name,
|
||||
LowerName: strings.ToLower(name),
|
||||
Description: desc,
|
||||
DefaultBranch: oldRepo.DefaultBranch,
|
||||
IsPrivate: oldRepo.IsPrivate,
|
||||
DefaultBranch: baseRepo.DefaultBranch,
|
||||
IsPrivate: baseRepo.IsPrivate,
|
||||
IsFork: true,
|
||||
ForkID: oldRepo.ID,
|
||||
ForkID: baseRepo.ID,
|
||||
}
|
||||
|
||||
sess := x.NewSession()
|
||||
@@ -2187,18 +2192,16 @@ func ForkRepository(u *User, oldRepo *Repository, name, desc string) (_ *Reposit
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err = createRepository(sess, u, repo); err != nil {
|
||||
if err = createRepository(sess, doer, owner, repo); err != nil {
|
||||
return nil, err
|
||||
} else if _, err = sess.Exec("UPDATE `repository` SET num_forks=num_forks+1 WHERE id=?", baseRepo.ID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if _, err = sess.Exec("UPDATE `repository` SET num_forks=num_forks+1 WHERE id=?", oldRepo.ID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
repoPath := RepoPath(u.Name, repo.Name)
|
||||
repoPath := repo.repoPath(sess)
|
||||
_, stderr, err := process.ExecTimeout(10*time.Minute,
|
||||
fmt.Sprintf("ForkRepository 'git clone': %s/%s", u.Name, repo.Name),
|
||||
"git", "clone", "--bare", oldRepo.RepoPath(), repoPath)
|
||||
fmt.Sprintf("ForkRepository 'git clone': %s/%s", owner.Name, repo.Name),
|
||||
"git", "clone", "--bare", baseRepo.RepoPath(), repoPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("git clone: %v", stderr)
|
||||
}
|
||||
@@ -2212,6 +2215,12 @@ func ForkRepository(u *User, oldRepo *Repository, name, desc string) (_ *Reposit
|
||||
|
||||
if err = createDelegateHooks(repoPath); err != nil {
|
||||
return nil, fmt.Errorf("createDelegateHooks: %v", err)
|
||||
} else if err = prepareWebhooks(sess, baseRepo, HOOK_EVENT_FORK, &api.ForkPayload{
|
||||
Forkee: repo.APIFormat(nil),
|
||||
Repo: baseRepo.APIFormat(nil),
|
||||
Sender: doer.APIFormat(),
|
||||
}); err != nil {
|
||||
return nil, fmt.Errorf("prepareWebhooks: %v", err)
|
||||
}
|
||||
|
||||
return repo, sess.Commit()
|
||||
|
||||
@@ -10,8 +10,6 @@ import (
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
log "gopkg.in/clog.v1"
|
||||
|
||||
git "github.com/gogits/git-module"
|
||||
)
|
||||
|
||||
@@ -29,6 +27,10 @@ func CommitToPushCommit(commit *git.Commit) *PushCommit {
|
||||
}
|
||||
|
||||
func ListToPushCommits(l *list.List) *PushCommits {
|
||||
if l == nil {
|
||||
return &PushCommits{}
|
||||
}
|
||||
|
||||
commits := make([]*PushCommit, 0)
|
||||
var actEmail string
|
||||
for e := l.Front(); e != nil; e = e.Next() {
|
||||
@@ -68,12 +70,6 @@ func PushUpdate(opts PushUpdateOptions) (err error) {
|
||||
return fmt.Errorf("Fail to call 'git update-server-info': %v", err)
|
||||
}
|
||||
|
||||
if isDelRef {
|
||||
log.Trace("Reference '%s' has been deleted from '%s/%s' by %s",
|
||||
opts.RefFullName, opts.RepoUserName, opts.RepoName, opts.PusherName)
|
||||
return nil
|
||||
}
|
||||
|
||||
gitRepo, err := git.OpenRepository(repoPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("OpenRepository: %v", err)
|
||||
@@ -100,27 +96,30 @@ func PushUpdate(opts PushUpdateOptions) (err error) {
|
||||
NewCommitID: opts.NewCommitID,
|
||||
Commits: &PushCommits{},
|
||||
}); err != nil {
|
||||
return fmt.Errorf("CommitRepoAction (tag): %v", err)
|
||||
return fmt.Errorf("CommitRepoAction.(tag): %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
newCommit, err := gitRepo.GetCommit(opts.NewCommitID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("gitRepo.GetCommit: %v", err)
|
||||
}
|
||||
|
||||
// Push new branch.
|
||||
var l *list.List
|
||||
if isNewRef {
|
||||
l, err = newCommit.CommitsBeforeLimit(10)
|
||||
// Skip read parent commits when delete branch
|
||||
if !isDelRef {
|
||||
// Push new branch.
|
||||
newCommit, err := gitRepo.GetCommit(opts.NewCommitID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("newCommit.CommitsBeforeLimit: %v", err)
|
||||
return fmt.Errorf("GetCommit [commit_id: %s]: %v", opts.NewCommitID, err)
|
||||
}
|
||||
} else {
|
||||
l, err = newCommit.CommitsBeforeUntil(opts.OldCommitID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("newCommit.CommitsBeforeUntil: %v", err)
|
||||
|
||||
if isNewRef {
|
||||
l, err = newCommit.CommitsBeforeLimit(10)
|
||||
if err != nil {
|
||||
return fmt.Errorf("CommitsBeforeLimit [commit_id: %s]: %v", newCommit.ID, err)
|
||||
}
|
||||
} else {
|
||||
l, err = newCommit.CommitsBeforeUntil(opts.OldCommitID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("CommitsBeforeUntil [commit_id: %s]: %v", opts.OldCommitID, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,7 +132,7 @@ func PushUpdate(opts PushUpdateOptions) (err error) {
|
||||
NewCommitID: opts.NewCommitID,
|
||||
Commits: ListToPushCommits(l),
|
||||
}); err != nil {
|
||||
return fmt.Errorf("CommitRepoAction (branch): %v", err)
|
||||
return fmt.Errorf("CommitRepoAction.(branch): %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -448,18 +448,15 @@ func (u *User) GetOwnedOrganizations() (err error) {
|
||||
}
|
||||
|
||||
// GetOrganizations returns all organizations that user belongs to.
|
||||
func (u *User) GetOrganizations(all bool) error {
|
||||
ous, err := GetOrgUsersByUserID(u.ID, all)
|
||||
func (u *User) GetOrganizations(showPrivate bool) error {
|
||||
orgIDs, err := GetOrgIDsByUserID(u.ID, showPrivate)
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("GetOrgIDsByUserID: %v", err)
|
||||
}
|
||||
|
||||
u.Orgs = make([]*User, len(ous))
|
||||
for i, ou := range ous {
|
||||
u.Orgs[i], err = GetUserByID(ou.OrgID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
u.Orgs = make([]*User, 0, len(orgIDs))
|
||||
if err = x.In("id", orgIDs).Find(&u.Orgs); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -685,7 +682,13 @@ func ChangeUserName(u *User, newUserName string) (err error) {
|
||||
return fmt.Errorf("Delete repository wiki local copy: %v", err)
|
||||
}
|
||||
|
||||
return os.Rename(UserPath(u.Name), UserPath(newUserName))
|
||||
// Rename or create user base directory
|
||||
baseDir := UserPath(u.Name)
|
||||
newBaseDir := UserPath(newUserName)
|
||||
if com.IsExist(baseDir) {
|
||||
return os.Rename(baseDir, newBaseDir)
|
||||
}
|
||||
return os.MkdirAll(newBaseDir, os.ModePerm)
|
||||
}
|
||||
|
||||
func updateUser(e Engine, u *User) error {
|
||||
|
||||
@@ -63,6 +63,8 @@ func IsValidHookContentType(name string) bool {
|
||||
|
||||
type HookEvents struct {
|
||||
Create bool `json:"create"`
|
||||
Delete bool `json:"delete"`
|
||||
Fork bool `json:"fork"`
|
||||
Push bool `json:"push"`
|
||||
PullRequest bool `json:"pull_request"`
|
||||
}
|
||||
@@ -156,6 +158,18 @@ func (w *Webhook) HasCreateEvent() bool {
|
||||
(w.ChooseEvents && w.HookEvents.Create)
|
||||
}
|
||||
|
||||
// HasDeleteEvent returns true if hook enabled delete event.
|
||||
func (w *Webhook) HasDeleteEvent() bool {
|
||||
return w.SendEverything ||
|
||||
(w.ChooseEvents && w.HookEvents.Delete)
|
||||
}
|
||||
|
||||
// HasForkEvent returns true if hook enabled fork event.
|
||||
func (w *Webhook) HasForkEvent() bool {
|
||||
return w.SendEverything ||
|
||||
(w.ChooseEvents && w.HookEvents.Fork)
|
||||
}
|
||||
|
||||
// HasPushEvent returns true if hook enabled push event.
|
||||
func (w *Webhook) HasPushEvent() bool {
|
||||
return w.PushOnly || w.SendEverything ||
|
||||
@@ -169,15 +183,21 @@ func (w *Webhook) HasPullRequestEvent() bool {
|
||||
}
|
||||
|
||||
func (w *Webhook) EventsArray() []string {
|
||||
events := make([]string, 0, 3)
|
||||
events := make([]string, 0, 5)
|
||||
if w.HasCreateEvent() {
|
||||
events = append(events, "create")
|
||||
events = append(events, string(HOOK_EVENT_CREATE))
|
||||
}
|
||||
if w.HasDeleteEvent() {
|
||||
events = append(events, string(HOOK_EVENT_DELETE))
|
||||
}
|
||||
if w.HasForkEvent() {
|
||||
events = append(events, string(HOOK_EVENT_FORK))
|
||||
}
|
||||
if w.HasPushEvent() {
|
||||
events = append(events, "push")
|
||||
events = append(events, string(HOOK_EVENT_PUSH))
|
||||
}
|
||||
if w.HasPullRequestEvent() {
|
||||
events = append(events, "pull_request")
|
||||
events = append(events, string(HOOK_EVENT_PULL_REQUEST))
|
||||
}
|
||||
return events
|
||||
}
|
||||
@@ -225,10 +245,10 @@ func GetWebhookByOrgID(orgID, id int64) (*Webhook, error) {
|
||||
})
|
||||
}
|
||||
|
||||
// GetActiveWebhooksByRepoID returns all active webhooks of repository.
|
||||
func GetActiveWebhooksByRepoID(repoID int64) ([]*Webhook, error) {
|
||||
// getActiveWebhooksByRepoID returns all active webhooks of repository.
|
||||
func getActiveWebhooksByRepoID(e Engine, repoID int64) ([]*Webhook, error) {
|
||||
webhooks := make([]*Webhook, 0, 5)
|
||||
return webhooks, x.Where("repo_id = ?", repoID).And("is_active = ?", true).Find(&webhooks)
|
||||
return webhooks, e.Where("repo_id = ?", repoID).And("is_active = ?", true).Find(&webhooks)
|
||||
}
|
||||
|
||||
// GetWebhooksByRepoID returns all webhooks of a repository.
|
||||
@@ -283,10 +303,10 @@ func GetWebhooksByOrgID(orgID int64) (ws []*Webhook, err error) {
|
||||
return ws, err
|
||||
}
|
||||
|
||||
// GetActiveWebhooksByOrgID returns all active webhooks for an organization.
|
||||
func GetActiveWebhooksByOrgID(orgID int64) (ws []*Webhook, err error) {
|
||||
err = x.Where("org_id=?", orgID).And("is_active=?", true).Find(&ws)
|
||||
return ws, err
|
||||
// getActiveWebhooksByOrgID returns all active webhooks for an organization.
|
||||
func getActiveWebhooksByOrgID(e Engine, orgID int64) ([]*Webhook, error) {
|
||||
ws := make([]*Webhook, 0, 3)
|
||||
return ws, e.Where("org_id=?", orgID).And("is_active=?", true).Find(&ws)
|
||||
}
|
||||
|
||||
// ___ ___ __ ___________ __
|
||||
@@ -337,6 +357,8 @@ type HookEventType string
|
||||
|
||||
const (
|
||||
HOOK_EVENT_CREATE HookEventType = "create"
|
||||
HOOK_EVENT_DELETE HookEventType = "delete"
|
||||
HOOK_EVENT_FORK HookEventType = "fork"
|
||||
HOOK_EVENT_PUSH HookEventType = "push"
|
||||
HOOK_EVENT_PULL_REQUEST HookEventType = "pull_request"
|
||||
)
|
||||
@@ -430,16 +452,16 @@ func HookTasks(hookID int64, page int) ([]*HookTask, error) {
|
||||
return tasks, x.Limit(setting.Webhook.PagingNum, (page-1)*setting.Webhook.PagingNum).Where("hook_id=?", hookID).Desc("id").Find(&tasks)
|
||||
}
|
||||
|
||||
// CreateHookTask creates a new hook task,
|
||||
// createHookTask creates a new hook task,
|
||||
// it handles conversion from Payload to PayloadContent.
|
||||
func CreateHookTask(t *HookTask) error {
|
||||
func createHookTask(e Engine, t *HookTask) error {
|
||||
data, err := t.Payloader.JSONPayload()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
t.UUID = gouuid.NewV4().String()
|
||||
t.PayloadContent = string(data)
|
||||
_, err = x.Insert(t)
|
||||
_, err = e.Insert(t)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -449,8 +471,8 @@ func UpdateHookTask(t *HookTask) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// prepareWebhooks adds list of webhooks to task queue.
|
||||
func prepareWebhooks(repo *Repository, event HookEventType, p api.Payloader, webhooks []*Webhook) (err error) {
|
||||
// prepareHookTasks adds list of webhooks to task queue.
|
||||
func prepareHookTasks(e Engine, repo *Repository, event HookEventType, p api.Payloader, webhooks []*Webhook) (err error) {
|
||||
if len(webhooks) == 0 {
|
||||
return nil
|
||||
}
|
||||
@@ -462,6 +484,10 @@ func prepareWebhooks(repo *Repository, event HookEventType, p api.Payloader, web
|
||||
if !w.HasCreateEvent() {
|
||||
continue
|
||||
}
|
||||
case HOOK_EVENT_DELETE:
|
||||
if !w.HasDeleteEvent() {
|
||||
continue
|
||||
}
|
||||
case HOOK_EVENT_PUSH:
|
||||
if !w.HasPushEvent() {
|
||||
continue
|
||||
@@ -499,7 +525,7 @@ func prepareWebhooks(repo *Repository, event HookEventType, p api.Payloader, web
|
||||
signature = hex.EncodeToString(sig.Sum(nil))
|
||||
}
|
||||
|
||||
if err = CreateHookTask(&HookTask{
|
||||
if err = createHookTask(e, &HookTask{
|
||||
RepoID: repo.ID,
|
||||
HookID: w.ID,
|
||||
Type: w.HookTaskType,
|
||||
@@ -510,29 +536,37 @@ func prepareWebhooks(repo *Repository, event HookEventType, p api.Payloader, web
|
||||
EventType: event,
|
||||
IsSSL: w.IsSSL,
|
||||
}); err != nil {
|
||||
return fmt.Errorf("CreateHookTask: %v", err)
|
||||
return fmt.Errorf("createHookTask: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// It's safe to fail when the whole function is called during hook execution
|
||||
// because resource released after exit.
|
||||
go HookQueue.Add(repo.ID)
|
||||
return nil
|
||||
}
|
||||
|
||||
func prepareWebhooks(e Engine, repo *Repository, event HookEventType, p api.Payloader) error {
|
||||
webhooks, err := getActiveWebhooksByRepoID(e, repo.ID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("getActiveWebhooksByRepoID [%d]: %v", repo.ID, err)
|
||||
}
|
||||
|
||||
// check if repo belongs to org and append additional webhooks
|
||||
if repo.mustOwner(e).IsOrganization() {
|
||||
// get hooks for org
|
||||
orgws, err := getActiveWebhooksByOrgID(e, repo.OwnerID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("getActiveWebhooksByOrgID [%d]: %v", repo.OwnerID, err)
|
||||
}
|
||||
webhooks = append(webhooks, orgws...)
|
||||
}
|
||||
return prepareHookTasks(e, repo, event, p, webhooks)
|
||||
}
|
||||
|
||||
// PrepareWebhooks adds all active webhooks to task queue.
|
||||
func PrepareWebhooks(repo *Repository, event HookEventType, p api.Payloader) error {
|
||||
webhooks, err := GetActiveWebhooksByRepoID(repo.ID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("GetActiveWebhooksByRepoID [%d]: %v", repo.ID, err)
|
||||
}
|
||||
|
||||
// check if repo belongs to org and append additional webhooks
|
||||
if repo.MustOwner().IsOrganization() {
|
||||
// get hooks for org
|
||||
orgws, err := GetActiveWebhooksByOrgID(repo.OwnerID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("GetActiveWebhooksByOrgID [%d]: %v", repo.OwnerID, err)
|
||||
}
|
||||
webhooks = append(webhooks, orgws...)
|
||||
}
|
||||
return prepareWebhooks(repo, event, p, webhooks)
|
||||
return prepareWebhooks(x, repo, event, p)
|
||||
}
|
||||
|
||||
// TestWebhook adds the test webhook matches the ID to task queue.
|
||||
@@ -541,7 +575,7 @@ func TestWebhook(repo *Repository, event HookEventType, p api.Payloader, webhook
|
||||
if err != nil {
|
||||
return fmt.Errorf("GetWebhookOfRepoByID [repo_id: %d, id: %d]: %v", repo.ID, webhookID, err)
|
||||
}
|
||||
return prepareWebhooks(repo, event, p, []*Webhook{webhook})
|
||||
return prepareHookTasks(x, repo, event, p, []*Webhook{webhook})
|
||||
}
|
||||
|
||||
func (t *HookTask) deliver() {
|
||||
|
||||
@@ -68,22 +68,50 @@ func DiscordSHALinkFormatter(url string, text string) string {
|
||||
return fmt.Sprintf("[`%s`](%s)", text, url)
|
||||
}
|
||||
|
||||
func getDiscordCreatePayload(p *api.CreatePayload, slack *SlackMeta) (*DiscordPayload, error) {
|
||||
// Created tag/branch
|
||||
// getDiscordCreatePayload composes Discord payload for create new branch or tag.
|
||||
func getDiscordCreatePayload(p *api.CreatePayload) (*DiscordPayload, error) {
|
||||
refName := git.RefEndName(p.Ref)
|
||||
|
||||
repoLink := DiscordLinkFormatter(p.Repo.HTMLURL, p.Repo.Name)
|
||||
refLink := DiscordLinkFormatter(p.Repo.HTMLURL+"/src/"+refName, refName)
|
||||
content := fmt.Sprintf("Created new %s: %s/%s", p.RefType, repoLink, refLink)
|
||||
|
||||
color, _ := strconv.ParseInt(strings.TrimLeft(slack.Color, "#"), 16, 32)
|
||||
return &DiscordPayload{
|
||||
Username: slack.Username,
|
||||
AvatarURL: slack.IconURL,
|
||||
Embeds: []*DiscordEmbedObject{{
|
||||
Description: content,
|
||||
URL: setting.AppUrl + p.Sender.UserName,
|
||||
Color: int(color),
|
||||
Author: &DiscordEmbedAuthorObject{
|
||||
Name: p.Sender.UserName,
|
||||
IconURL: p.Sender.AvatarUrl,
|
||||
},
|
||||
}},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// getDiscordDeletePayload composes Discord payload for delete a branch or tag.
|
||||
func getDiscordDeletePayload(p *api.DeletePayload) (*DiscordPayload, error) {
|
||||
refName := git.RefEndName(p.Ref)
|
||||
repoLink := DiscordLinkFormatter(p.Repo.HTMLURL, p.Repo.Name)
|
||||
content := fmt.Sprintf("Deleted %s: %s/%s", p.RefType, repoLink, refName)
|
||||
return &DiscordPayload{
|
||||
Embeds: []*DiscordEmbedObject{{
|
||||
Description: content,
|
||||
URL: setting.AppUrl + p.Sender.UserName,
|
||||
Author: &DiscordEmbedAuthorObject{
|
||||
Name: p.Sender.UserName,
|
||||
IconURL: p.Sender.AvatarUrl,
|
||||
},
|
||||
}},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// getDiscordForkPayload composes Discord payload for forked by a repository.
|
||||
func getDiscordForkPayload(p *api.ForkPayload) (*DiscordPayload, error) {
|
||||
baseLink := DiscordLinkFormatter(p.Repo.HTMLURL, p.Repo.Name)
|
||||
forkLink := DiscordLinkFormatter(p.Forkee.HTMLURL, p.Forkee.FullName)
|
||||
content := fmt.Sprintf("%s is forked to %s", baseLink, forkLink)
|
||||
return &DiscordPayload{
|
||||
Embeds: []*DiscordEmbedObject{{
|
||||
Description: content,
|
||||
URL: setting.AppUrl + p.Sender.UserName,
|
||||
Author: &DiscordEmbedAuthorObject{
|
||||
Name: p.Sender.UserName,
|
||||
IconURL: p.Sender.AvatarUrl,
|
||||
@@ -206,22 +234,34 @@ func getDiscordPullRequestPayload(p *api.PullRequestPayload, slack *SlackMeta) (
|
||||
}, nil
|
||||
}
|
||||
|
||||
func GetDiscordPayload(p api.Payloader, event HookEventType, meta string) (*DiscordPayload, error) {
|
||||
d := new(DiscordPayload)
|
||||
|
||||
func GetDiscordPayload(p api.Payloader, event HookEventType, meta string) (payload *DiscordPayload, err error) {
|
||||
slack := &SlackMeta{}
|
||||
if err := json.Unmarshal([]byte(meta), &slack); err != nil {
|
||||
return d, fmt.Errorf("GetDiscordPayload meta json: %v", err)
|
||||
return nil, fmt.Errorf("json.Unmarshal: %v", err)
|
||||
}
|
||||
|
||||
switch event {
|
||||
case HOOK_EVENT_CREATE:
|
||||
return getDiscordCreatePayload(p.(*api.CreatePayload), slack)
|
||||
payload, err = getDiscordCreatePayload(p.(*api.CreatePayload))
|
||||
case HOOK_EVENT_DELETE:
|
||||
payload, err = getDiscordDeletePayload(p.(*api.DeletePayload))
|
||||
case HOOK_EVENT_FORK:
|
||||
payload, err = getDiscordForkPayload(p.(*api.ForkPayload))
|
||||
case HOOK_EVENT_PUSH:
|
||||
return getDiscordPushPayload(p.(*api.PushPayload), slack)
|
||||
payload, err = getDiscordPushPayload(p.(*api.PushPayload), slack)
|
||||
case HOOK_EVENT_PULL_REQUEST:
|
||||
return getDiscordPullRequestPayload(p.(*api.PullRequestPayload), slack)
|
||||
payload, err = getDiscordPullRequestPayload(p.(*api.PullRequestPayload), slack)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("event '%s': %v", event, err)
|
||||
}
|
||||
|
||||
return d, nil
|
||||
payload.Username = slack.Username
|
||||
payload.AvatarURL = slack.IconURL
|
||||
if len(payload.Embeds) > 0 {
|
||||
color, _ := strconv.ParseInt(strings.TrimLeft(slack.Color, "#"), 16, 32)
|
||||
payload.Embeds[0].Color = int(color)
|
||||
}
|
||||
|
||||
return payload, nil
|
||||
}
|
||||
|
||||
@@ -69,19 +69,34 @@ func SlackLinkFormatter(url string, text string) string {
|
||||
return fmt.Sprintf("<%s|%s>", url, SlackTextFormatter(text))
|
||||
}
|
||||
|
||||
func getSlackCreatePayload(p *api.CreatePayload, slack *SlackMeta) (*SlackPayload, error) {
|
||||
// Created tag/branch
|
||||
// getSlackCreatePayload composes Slack payload for create new branch or tag.
|
||||
func getSlackCreatePayload(p *api.CreatePayload) (*SlackPayload, error) {
|
||||
refName := git.RefEndName(p.Ref)
|
||||
|
||||
repoLink := SlackLinkFormatter(p.Repo.HTMLURL, p.Repo.Name)
|
||||
refLink := SlackLinkFormatter(p.Repo.HTMLURL+"/src/"+refName, refName)
|
||||
text := fmt.Sprintf("[%s:%s] %s created by %s", repoLink, refLink, p.RefType, p.Sender.UserName)
|
||||
|
||||
return &SlackPayload{
|
||||
Channel: slack.Channel,
|
||||
Text: text,
|
||||
Username: slack.Username,
|
||||
IconURL: slack.IconURL,
|
||||
Text: text,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// getSlackDeletePayload composes Slack payload for delete a branch or tag.
|
||||
func getSlackDeletePayload(p *api.DeletePayload) (*SlackPayload, error) {
|
||||
refName := git.RefEndName(p.Ref)
|
||||
repoLink := SlackLinkFormatter(p.Repo.HTMLURL, p.Repo.Name)
|
||||
text := fmt.Sprintf("[%s:%s] %s deleted by %s", repoLink, refName, p.RefType, p.Sender.UserName)
|
||||
return &SlackPayload{
|
||||
Text: text,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// getSlackForkPayload composes Slack payload for forked by a repository.
|
||||
func getSlackForkPayload(p *api.ForkPayload) (*SlackPayload, error) {
|
||||
baseLink := SlackLinkFormatter(p.Repo.HTMLURL, p.Repo.Name)
|
||||
forkLink := SlackLinkFormatter(p.Forkee.HTMLURL, p.Forkee.FullName)
|
||||
text := fmt.Sprintf("%s is forked to %s", baseLink, forkLink)
|
||||
return &SlackPayload{
|
||||
Text: text,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -178,22 +193,34 @@ func getSlackPullRequestPayload(p *api.PullRequestPayload, slack *SlackMeta) (*S
|
||||
}, nil
|
||||
}
|
||||
|
||||
func GetSlackPayload(p api.Payloader, event HookEventType, meta string) (*SlackPayload, error) {
|
||||
s := new(SlackPayload)
|
||||
|
||||
func GetSlackPayload(p api.Payloader, event HookEventType, meta string) (payload *SlackPayload, err error) {
|
||||
slack := &SlackMeta{}
|
||||
if err := json.Unmarshal([]byte(meta), &slack); err != nil {
|
||||
return s, fmt.Errorf("GetSlackPayload meta json: %v", err)
|
||||
return nil, fmt.Errorf("json.Unmarshal: %v", err)
|
||||
}
|
||||
|
||||
switch event {
|
||||
case HOOK_EVENT_CREATE:
|
||||
return getSlackCreatePayload(p.(*api.CreatePayload), slack)
|
||||
payload, err = getSlackCreatePayload(p.(*api.CreatePayload))
|
||||
case HOOK_EVENT_DELETE:
|
||||
payload, err = getSlackDeletePayload(p.(*api.DeletePayload))
|
||||
case HOOK_EVENT_FORK:
|
||||
payload, err = getSlackForkPayload(p.(*api.ForkPayload))
|
||||
case HOOK_EVENT_PUSH:
|
||||
return getSlackPushPayload(p.(*api.PushPayload), slack)
|
||||
payload, err = getSlackPushPayload(p.(*api.PushPayload), slack)
|
||||
case HOOK_EVENT_PULL_REQUEST:
|
||||
return getSlackPullRequestPayload(p.(*api.PullRequestPayload), slack)
|
||||
payload, err = getSlackPullRequestPayload(p.(*api.PullRequestPayload), slack)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("event '%s': %v", event, err)
|
||||
}
|
||||
|
||||
return s, nil
|
||||
payload.Channel = slack.Channel
|
||||
payload.Username = slack.Username
|
||||
payload.IconURL = slack.IconURL
|
||||
if len(payload.Attachments) > 0 {
|
||||
payload.Attachments[0].Color = slack.Color
|
||||
}
|
||||
|
||||
return payload, nil
|
||||
}
|
||||
|
||||
@@ -5,12 +5,9 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/Unknwon/com"
|
||||
"github.com/go-macaron/binding"
|
||||
"github.com/go-macaron/session"
|
||||
gouuid "github.com/satori/go.uuid"
|
||||
log "gopkg.in/clog.v1"
|
||||
@@ -147,130 +144,3 @@ func SignedInUser(ctx *macaron.Context, sess session.Store) (*models.User, bool)
|
||||
}
|
||||
return u, false
|
||||
}
|
||||
|
||||
type Form interface {
|
||||
binding.Validator
|
||||
}
|
||||
|
||||
func init() {
|
||||
binding.SetNameMapper(com.ToSnakeCase)
|
||||
}
|
||||
|
||||
// AssignForm assign form values back to the template data.
|
||||
func AssignForm(form interface{}, data map[string]interface{}) {
|
||||
typ := reflect.TypeOf(form)
|
||||
val := reflect.ValueOf(form)
|
||||
|
||||
if typ.Kind() == reflect.Ptr {
|
||||
typ = typ.Elem()
|
||||
val = val.Elem()
|
||||
}
|
||||
|
||||
for i := 0; i < typ.NumField(); i++ {
|
||||
field := typ.Field(i)
|
||||
|
||||
fieldName := field.Tag.Get("form")
|
||||
// Allow ignored fields in the struct
|
||||
if fieldName == "-" {
|
||||
continue
|
||||
} else if len(fieldName) == 0 {
|
||||
fieldName = com.ToSnakeCase(field.Name)
|
||||
}
|
||||
|
||||
data[fieldName] = val.Field(i).Interface()
|
||||
}
|
||||
}
|
||||
|
||||
func getRuleBody(field reflect.StructField, prefix string) string {
|
||||
for _, rule := range strings.Split(field.Tag.Get("binding"), ";") {
|
||||
if strings.HasPrefix(rule, prefix) {
|
||||
return rule[len(prefix) : len(rule)-1]
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func GetSize(field reflect.StructField) string {
|
||||
return getRuleBody(field, "Size(")
|
||||
}
|
||||
|
||||
func GetMinSize(field reflect.StructField) string {
|
||||
return getRuleBody(field, "MinSize(")
|
||||
}
|
||||
|
||||
func GetMaxSize(field reflect.StructField) string {
|
||||
return getRuleBody(field, "MaxSize(")
|
||||
}
|
||||
|
||||
func GetInclude(field reflect.StructField) string {
|
||||
return getRuleBody(field, "Include(")
|
||||
}
|
||||
|
||||
// FIXME: struct contains a struct
|
||||
func validateStruct(obj interface{}) binding.Errors {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func validate(errs binding.Errors, data map[string]interface{}, f Form, l macaron.Locale) binding.Errors {
|
||||
if errs.Len() == 0 {
|
||||
return errs
|
||||
}
|
||||
|
||||
data["HasError"] = true
|
||||
AssignForm(f, data)
|
||||
|
||||
typ := reflect.TypeOf(f)
|
||||
val := reflect.ValueOf(f)
|
||||
|
||||
if typ.Kind() == reflect.Ptr {
|
||||
typ = typ.Elem()
|
||||
val = val.Elem()
|
||||
}
|
||||
|
||||
for i := 0; i < typ.NumField(); i++ {
|
||||
field := typ.Field(i)
|
||||
|
||||
fieldName := field.Tag.Get("form")
|
||||
// Allow ignored fields in the struct
|
||||
if fieldName == "-" {
|
||||
continue
|
||||
}
|
||||
|
||||
if errs[0].FieldNames[0] == field.Name {
|
||||
data["Err_"+field.Name] = true
|
||||
|
||||
trName := field.Tag.Get("locale")
|
||||
if len(trName) == 0 {
|
||||
trName = l.Tr("form." + field.Name)
|
||||
} else {
|
||||
trName = l.Tr(trName)
|
||||
}
|
||||
|
||||
switch errs[0].Classification {
|
||||
case binding.ERR_REQUIRED:
|
||||
data["ErrorMsg"] = trName + l.Tr("form.require_error")
|
||||
case binding.ERR_ALPHA_DASH:
|
||||
data["ErrorMsg"] = trName + l.Tr("form.alpha_dash_error")
|
||||
case binding.ERR_ALPHA_DASH_DOT:
|
||||
data["ErrorMsg"] = trName + l.Tr("form.alpha_dash_dot_error")
|
||||
case binding.ERR_SIZE:
|
||||
data["ErrorMsg"] = trName + l.Tr("form.size_error", GetSize(field))
|
||||
case binding.ERR_MIN_SIZE:
|
||||
data["ErrorMsg"] = trName + l.Tr("form.min_size_error", GetMinSize(field))
|
||||
case binding.ERR_MAX_SIZE:
|
||||
data["ErrorMsg"] = trName + l.Tr("form.max_size_error", GetMaxSize(field))
|
||||
case binding.ERR_EMAIL:
|
||||
data["ErrorMsg"] = trName + l.Tr("form.email_error")
|
||||
case binding.ERR_URL:
|
||||
data["ErrorMsg"] = trName + l.Tr("form.url_error")
|
||||
case binding.ERR_INCLUDE:
|
||||
data["ErrorMsg"] = trName + l.Tr("form.include_error", GetInclude(field))
|
||||
default:
|
||||
data["ErrorMsg"] = l.Tr("form.unknown_error") + " " + errs[0].Classification
|
||||
}
|
||||
return errs
|
||||
}
|
||||
}
|
||||
return errs
|
||||
}
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
// Copyright 2014 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 auth
|
||||
|
||||
import (
|
||||
"github.com/go-macaron/binding"
|
||||
"gopkg.in/macaron.v1"
|
||||
)
|
||||
|
||||
// ________ .__ __ .__
|
||||
// \_____ \_______ _________ ____ |__|____________ _/ |_|__| ____ ____
|
||||
// / | \_ __ \/ ___\__ \ / \| \___ /\__ \\ __\ |/ _ \ / \
|
||||
// / | \ | \/ /_/ > __ \| | \ |/ / / __ \| | | ( <_> ) | \
|
||||
// \_______ /__| \___ (____ /___| /__/_____ \(____ /__| |__|\____/|___| /
|
||||
// \/ /_____/ \/ \/ \/ \/ \/
|
||||
|
||||
type CreateOrgForm struct {
|
||||
OrgName string `binding:"Required;AlphaDashDot;MaxSize(35)" locale:"org.org_name_holder"`
|
||||
}
|
||||
|
||||
func (f *CreateOrgForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
type UpdateOrgSettingForm struct {
|
||||
Name string `binding:"Required;AlphaDashDot;MaxSize(35)" locale:"org.org_name_holder"`
|
||||
FullName string `binding:"MaxSize(100)"`
|
||||
Description string `binding:"MaxSize(255)"`
|
||||
Website string `binding:"Url;MaxSize(100)"`
|
||||
Location string `binding:"MaxSize(50)"`
|
||||
MaxRepoCreation int
|
||||
}
|
||||
|
||||
func (f *UpdateOrgSettingForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
// ___________
|
||||
// \__ ___/___ _____ _____
|
||||
// | |_/ __ \\__ \ / \
|
||||
// | |\ ___/ / __ \| Y Y \
|
||||
// |____| \___ >____ /__|_| /
|
||||
// \/ \/ \/
|
||||
|
||||
type CreateTeamForm struct {
|
||||
TeamName string `binding:"Required;AlphaDashDot;MaxSize(30)"`
|
||||
Description string `binding:"MaxSize(255)"`
|
||||
Permission string
|
||||
}
|
||||
|
||||
func (f *CreateTeamForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -22,6 +22,7 @@ import (
|
||||
"github.com/gogits/gogs/models"
|
||||
"github.com/gogits/gogs/modules/auth"
|
||||
"github.com/gogits/gogs/modules/base"
|
||||
"github.com/gogits/gogs/modules/form"
|
||||
"github.com/gogits/gogs/modules/setting"
|
||||
)
|
||||
|
||||
@@ -78,9 +79,9 @@ func (ctx *Context) HTML(status int, name base.TplName) {
|
||||
}
|
||||
|
||||
// RenderWithErr used for page has form validation but need to prompt error to users.
|
||||
func (ctx *Context) RenderWithErr(msg string, tpl base.TplName, form interface{}) {
|
||||
if form != nil {
|
||||
auth.AssignForm(form, ctx.Data)
|
||||
func (ctx *Context) RenderWithErr(msg string, tpl base.TplName, f interface{}) {
|
||||
if f != nil {
|
||||
form.Assign(f, ctx.Data)
|
||||
}
|
||||
ctx.Flash.ErrorMsg = msg
|
||||
ctx.Data["Flash"] = ctx.Flash
|
||||
|
||||
@@ -2,15 +2,14 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package auth
|
||||
package form
|
||||
|
||||
import (
|
||||
"gopkg.in/macaron.v1"
|
||||
|
||||
"github.com/go-macaron/binding"
|
||||
"gopkg.in/macaron.v1"
|
||||
)
|
||||
|
||||
type AdminCrateUserForm struct {
|
||||
type AdminCrateUser struct {
|
||||
LoginType string `binding:"Required"`
|
||||
LoginName string
|
||||
UserName string `binding:"Required;AlphaDashDot;MaxSize(35)"`
|
||||
@@ -19,11 +18,11 @@ type AdminCrateUserForm struct {
|
||||
SendNotify bool
|
||||
}
|
||||
|
||||
func (f *AdminCrateUserForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
func (f *AdminCrateUser) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
type AdminEditUserForm struct {
|
||||
type AdminEditUser struct {
|
||||
LoginType string `binding:"Required"`
|
||||
LoginName string
|
||||
FullName string `binding:"MaxSize(100)"`
|
||||
@@ -39,6 +38,6 @@ type AdminEditUserForm struct {
|
||||
ProhibitLogin bool
|
||||
}
|
||||
|
||||
func (f *AdminEditUserForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
func (f *AdminEditUser) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
@@ -2,14 +2,14 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package auth
|
||||
package form
|
||||
|
||||
import (
|
||||
"github.com/go-macaron/binding"
|
||||
"gopkg.in/macaron.v1"
|
||||
)
|
||||
|
||||
type AuthenticationForm struct {
|
||||
type Authentication struct {
|
||||
ID int64
|
||||
Type int `binding:"Range(2,5)"`
|
||||
Name string `binding:"Required;MaxSize(30)"`
|
||||
@@ -37,6 +37,6 @@ type AuthenticationForm struct {
|
||||
PAMServiceName string
|
||||
}
|
||||
|
||||
func (f *AuthenticationForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
func (f *Authentication) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
155
modules/form/form.go
Normal file
155
modules/form/form.go
Normal file
@@ -0,0 +1,155 @@
|
||||
// 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 form
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/Unknwon/com"
|
||||
"github.com/go-macaron/binding"
|
||||
"gopkg.in/macaron.v1"
|
||||
)
|
||||
|
||||
const ERR_ALPHA_DASH_DOT_SLASH = "AlphaDashDotSlashError"
|
||||
|
||||
var AlphaDashDotSlashPattern = regexp.MustCompile("[^\\d\\w-_\\./]")
|
||||
|
||||
func init() {
|
||||
binding.SetNameMapper(com.ToSnakeCase)
|
||||
binding.AddRule(&binding.Rule{
|
||||
IsMatch: func(rule string) bool {
|
||||
return rule == "AlphaDashDotSlash"
|
||||
},
|
||||
IsValid: func(errs binding.Errors, name string, v interface{}) (bool, binding.Errors) {
|
||||
if AlphaDashDotSlashPattern.MatchString(fmt.Sprintf("%v", v)) {
|
||||
errs.Add([]string{name}, ERR_ALPHA_DASH_DOT_SLASH, "AlphaDashDotSlash")
|
||||
return false, errs
|
||||
}
|
||||
return true, errs
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
type Form interface {
|
||||
binding.Validator
|
||||
}
|
||||
|
||||
// Assign assign form values back to the template data.
|
||||
func Assign(form interface{}, data map[string]interface{}) {
|
||||
typ := reflect.TypeOf(form)
|
||||
val := reflect.ValueOf(form)
|
||||
|
||||
if typ.Kind() == reflect.Ptr {
|
||||
typ = typ.Elem()
|
||||
val = val.Elem()
|
||||
}
|
||||
|
||||
for i := 0; i < typ.NumField(); i++ {
|
||||
field := typ.Field(i)
|
||||
|
||||
fieldName := field.Tag.Get("form")
|
||||
// Allow ignored fields in the struct
|
||||
if fieldName == "-" {
|
||||
continue
|
||||
} else if len(fieldName) == 0 {
|
||||
fieldName = com.ToSnakeCase(field.Name)
|
||||
}
|
||||
|
||||
data[fieldName] = val.Field(i).Interface()
|
||||
}
|
||||
}
|
||||
|
||||
func getRuleBody(field reflect.StructField, prefix string) string {
|
||||
for _, rule := range strings.Split(field.Tag.Get("binding"), ";") {
|
||||
if strings.HasPrefix(rule, prefix) {
|
||||
return rule[len(prefix) : len(rule)-1]
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func getSize(field reflect.StructField) string {
|
||||
return getRuleBody(field, "Size(")
|
||||
}
|
||||
|
||||
func getMinSize(field reflect.StructField) string {
|
||||
return getRuleBody(field, "MinSize(")
|
||||
}
|
||||
|
||||
func getMaxSize(field reflect.StructField) string {
|
||||
return getRuleBody(field, "MaxSize(")
|
||||
}
|
||||
|
||||
func getInclude(field reflect.StructField) string {
|
||||
return getRuleBody(field, "Include(")
|
||||
}
|
||||
|
||||
func validate(errs binding.Errors, data map[string]interface{}, f Form, l macaron.Locale) binding.Errors {
|
||||
if errs.Len() == 0 {
|
||||
return errs
|
||||
}
|
||||
|
||||
data["HasError"] = true
|
||||
Assign(f, data)
|
||||
|
||||
typ := reflect.TypeOf(f)
|
||||
val := reflect.ValueOf(f)
|
||||
|
||||
if typ.Kind() == reflect.Ptr {
|
||||
typ = typ.Elem()
|
||||
val = val.Elem()
|
||||
}
|
||||
|
||||
for i := 0; i < typ.NumField(); i++ {
|
||||
field := typ.Field(i)
|
||||
|
||||
fieldName := field.Tag.Get("form")
|
||||
// Allow ignored fields in the struct
|
||||
if fieldName == "-" {
|
||||
continue
|
||||
}
|
||||
|
||||
if errs[0].FieldNames[0] == field.Name {
|
||||
data["Err_"+field.Name] = true
|
||||
|
||||
trName := field.Tag.Get("locale")
|
||||
if len(trName) == 0 {
|
||||
trName = l.Tr("form." + field.Name)
|
||||
} else {
|
||||
trName = l.Tr(trName)
|
||||
}
|
||||
|
||||
switch errs[0].Classification {
|
||||
case binding.ERR_REQUIRED:
|
||||
data["ErrorMsg"] = trName + l.Tr("form.require_error")
|
||||
case binding.ERR_ALPHA_DASH:
|
||||
data["ErrorMsg"] = trName + l.Tr("form.alpha_dash_error")
|
||||
case binding.ERR_ALPHA_DASH_DOT:
|
||||
data["ErrorMsg"] = trName + l.Tr("form.alpha_dash_dot_error")
|
||||
case ERR_ALPHA_DASH_DOT_SLASH:
|
||||
data["ErrorMsg"] = trName + l.Tr("form.alpha_dash_dot_slash_error")
|
||||
case binding.ERR_SIZE:
|
||||
data["ErrorMsg"] = trName + l.Tr("form.size_error", getSize(field))
|
||||
case binding.ERR_MIN_SIZE:
|
||||
data["ErrorMsg"] = trName + l.Tr("form.min_size_error", getMinSize(field))
|
||||
case binding.ERR_MAX_SIZE:
|
||||
data["ErrorMsg"] = trName + l.Tr("form.max_size_error", getMaxSize(field))
|
||||
case binding.ERR_EMAIL:
|
||||
data["ErrorMsg"] = trName + l.Tr("form.email_error")
|
||||
case binding.ERR_URL:
|
||||
data["ErrorMsg"] = trName + l.Tr("form.url_error")
|
||||
case binding.ERR_INCLUDE:
|
||||
data["ErrorMsg"] = trName + l.Tr("form.include_error", getInclude(field))
|
||||
default:
|
||||
data["ErrorMsg"] = l.Tr("form.unknown_error") + " " + errs[0].Classification
|
||||
}
|
||||
return errs
|
||||
}
|
||||
}
|
||||
return errs
|
||||
}
|
||||
41
modules/form/org.go
Normal file
41
modules/form/org.go
Normal file
@@ -0,0 +1,41 @@
|
||||
// Copyright 2014 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 form
|
||||
|
||||
import (
|
||||
"github.com/go-macaron/binding"
|
||||
"gopkg.in/macaron.v1"
|
||||
)
|
||||
|
||||
type CreateOrg struct {
|
||||
OrgName string `binding:"Required;AlphaDashDot;MaxSize(35)" locale:"org.org_name_holder"`
|
||||
}
|
||||
|
||||
func (f *CreateOrg) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
type UpdateOrgSetting struct {
|
||||
Name string `binding:"Required;AlphaDashDot;MaxSize(35)" locale:"org.org_name_holder"`
|
||||
FullName string `binding:"MaxSize(100)"`
|
||||
Description string `binding:"MaxSize(255)"`
|
||||
Website string `binding:"Url;MaxSize(100)"`
|
||||
Location string `binding:"MaxSize(50)"`
|
||||
MaxRepoCreation int
|
||||
}
|
||||
|
||||
func (f *UpdateOrgSetting) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
type CreateTeam struct {
|
||||
TeamName string `binding:"Required;AlphaDashDot;MaxSize(30)"`
|
||||
Description string `binding:"MaxSize(255)"`
|
||||
Permission string
|
||||
}
|
||||
|
||||
func (f *CreateTeam) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package auth
|
||||
package form
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
@@ -22,8 +22,8 @@ import (
|
||||
// |____|_ /_______ / |____| \_______ /_______ /|___| |____| \_______ /____|_ // ______|
|
||||
// \/ \/ \/ \/ \/ \/ \/
|
||||
|
||||
type CreateRepoForm struct {
|
||||
Uid int64 `binding:"Required"`
|
||||
type CreateRepo struct {
|
||||
UserID int64 `binding:"Required"`
|
||||
RepoName string `binding:"Required;AlphaDashDot;MaxSize(100)"`
|
||||
Private bool
|
||||
Description string `binding:"MaxSize(255)"`
|
||||
@@ -33,11 +33,11 @@ type CreateRepoForm struct {
|
||||
Readme string
|
||||
}
|
||||
|
||||
func (f *CreateRepoForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
func (f *CreateRepo) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
type MigrateRepoForm struct {
|
||||
type MigrateRepo struct {
|
||||
CloneAddr string `json:"clone_addr" binding:"Required"`
|
||||
AuthUsername string `json:"auth_username"`
|
||||
AuthPassword string `json:"auth_password"`
|
||||
@@ -48,7 +48,7 @@ type MigrateRepoForm struct {
|
||||
Description string `json:"description" binding:"MaxSize(255)"`
|
||||
}
|
||||
|
||||
func (f *MigrateRepoForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
func (f *MigrateRepo) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ func (f *MigrateRepoForm) Validate(ctx *macaron.Context, errs binding.Errors) bi
|
||||
// and returns composed URL with needed username and password.
|
||||
// It also checks if given user has permission when remote address
|
||||
// is actually a local path.
|
||||
func (f MigrateRepoForm) ParseRemoteAddr(user *models.User) (string, error) {
|
||||
func (f MigrateRepo) ParseRemoteAddr(user *models.User) (string, error) {
|
||||
remoteAddr := strings.TrimSpace(f.CloneAddr)
|
||||
|
||||
// Remote address can be HTTP/HTTPS/Git URL or local path.
|
||||
@@ -80,7 +80,7 @@ func (f MigrateRepoForm) ParseRemoteAddr(user *models.User) (string, error) {
|
||||
return remoteAddr, nil
|
||||
}
|
||||
|
||||
type RepoSettingForm struct {
|
||||
type RepoSetting struct {
|
||||
RepoName string `binding:"Required;AlphaDashDot;MaxSize(100)"`
|
||||
Description string `binding:"MaxSize(255)"`
|
||||
Website string `binding:"Url;MaxSize(100)"`
|
||||
@@ -102,7 +102,7 @@ type RepoSettingForm struct {
|
||||
EnablePulls bool
|
||||
}
|
||||
|
||||
func (f *RepoSettingForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
func (f *RepoSetting) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
@@ -113,7 +113,7 @@ func (f *RepoSettingForm) Validate(ctx *macaron.Context, errs binding.Errors) bi
|
||||
// |______ / |__| (____ /___| /\___ >___| /
|
||||
// \/ \/ \/ \/ \/
|
||||
|
||||
type ProtectBranchForm struct {
|
||||
type ProtectBranch struct {
|
||||
Protected bool
|
||||
RequirePullRequest bool
|
||||
EnableWhitelist bool
|
||||
@@ -121,7 +121,7 @@ type ProtectBranchForm struct {
|
||||
WhitelistTeams string
|
||||
}
|
||||
|
||||
func (f *ProtectBranchForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
func (f *ProtectBranch) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
@@ -132,59 +132,61 @@ func (f *ProtectBranchForm) Validate(ctx *macaron.Context, errs binding.Errors)
|
||||
// \__/\ / \___ >___ /___| /___| /\____/|__|_ \
|
||||
// \/ \/ \/ \/ \/ \/
|
||||
|
||||
type WebhookForm struct {
|
||||
type Webhook struct {
|
||||
Events string
|
||||
Create bool
|
||||
Delete bool
|
||||
Fork bool
|
||||
Push bool
|
||||
PullRequest bool
|
||||
Active bool
|
||||
}
|
||||
|
||||
func (f WebhookForm) PushOnly() bool {
|
||||
func (f Webhook) PushOnly() bool {
|
||||
return f.Events == "push_only"
|
||||
}
|
||||
|
||||
func (f WebhookForm) SendEverything() bool {
|
||||
func (f Webhook) SendEverything() bool {
|
||||
return f.Events == "send_everything"
|
||||
}
|
||||
|
||||
func (f WebhookForm) ChooseEvents() bool {
|
||||
func (f Webhook) ChooseEvents() bool {
|
||||
return f.Events == "choose_events"
|
||||
}
|
||||
|
||||
type NewWebhookForm struct {
|
||||
type NewWebhook struct {
|
||||
PayloadURL string `binding:"Required;Url"`
|
||||
ContentType int `binding:"Required"`
|
||||
Secret string
|
||||
WebhookForm
|
||||
Webhook
|
||||
}
|
||||
|
||||
func (f *NewWebhookForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
func (f *NewWebhook) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
type NewSlackHookForm struct {
|
||||
type NewSlackHook struct {
|
||||
PayloadURL string `binding:"Required;Url"`
|
||||
Channel string `binding:"Required"`
|
||||
Username string
|
||||
IconURL string
|
||||
Color string
|
||||
WebhookForm
|
||||
Webhook
|
||||
}
|
||||
|
||||
func (f *NewSlackHookForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
func (f *NewSlackHook) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
type NewDiscordHookForm struct {
|
||||
type NewDiscordHook struct {
|
||||
PayloadURL string `binding:"Required;Url"`
|
||||
Username string
|
||||
IconURL string
|
||||
Color string
|
||||
WebhookForm
|
||||
Webhook
|
||||
}
|
||||
|
||||
func (f *NewDiscordHookForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
func (f *NewDiscordHook) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
@@ -195,7 +197,7 @@ func (f *NewDiscordHookForm) Validate(ctx *macaron.Context, errs binding.Errors)
|
||||
// |___/____ >____ >____/ \___ >
|
||||
// \/ \/ \/
|
||||
|
||||
type CreateIssueForm struct {
|
||||
type CreateIssue struct {
|
||||
Title string `binding:"Required;MaxSize(255)"`
|
||||
LabelIDs string `form:"label_ids"`
|
||||
MilestoneID int64
|
||||
@@ -204,17 +206,17 @@ type CreateIssueForm struct {
|
||||
Files []string
|
||||
}
|
||||
|
||||
func (f *CreateIssueForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
func (f *CreateIssue) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
type CreateCommentForm struct {
|
||||
type CreateComment struct {
|
||||
Content string
|
||||
Status string `binding:"OmitEmpty;In(reopen,close)"`
|
||||
Files []string
|
||||
}
|
||||
|
||||
func (f *CreateCommentForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
func (f *CreateComment) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
@@ -225,13 +227,13 @@ func (f *CreateCommentForm) Validate(ctx *macaron.Context, errs binding.Errors)
|
||||
// \____|__ /__|____/\___ >____ > |__| \____/|___| /\___ >
|
||||
// \/ \/ \/ \/ \/
|
||||
|
||||
type CreateMilestoneForm struct {
|
||||
type CreateMilestone struct {
|
||||
Title string `binding:"Required;MaxSize(50)"`
|
||||
Content string
|
||||
Deadline string
|
||||
}
|
||||
|
||||
func (f *CreateMilestoneForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
func (f *CreateMilestone) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
@@ -242,21 +244,21 @@ func (f *CreateMilestoneForm) Validate(ctx *macaron.Context, errs binding.Errors
|
||||
// |_______ (____ /___ /\___ >____/
|
||||
// \/ \/ \/ \/
|
||||
|
||||
type CreateLabelForm struct {
|
||||
type CreateLabel struct {
|
||||
ID int64
|
||||
Title string `binding:"Required;MaxSize(50)" locale:"repo.issues.label_name"`
|
||||
Color string `binding:"Required;Size(7)" locale:"repo.issues.label_color"`
|
||||
}
|
||||
|
||||
func (f *CreateLabelForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
func (f *CreateLabel) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
type InitializeLabelsForm struct {
|
||||
type InitializeLabels struct {
|
||||
TemplateName string `binding:"Required"`
|
||||
}
|
||||
|
||||
func (f *InitializeLabelsForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
func (f *InitializeLabels) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
@@ -267,7 +269,7 @@ func (f *InitializeLabelsForm) Validate(ctx *macaron.Context, errs binding.Error
|
||||
// |____|_ /\___ >____/\___ >____ /____ >\___ >
|
||||
// \/ \/ \/ \/ \/ \/
|
||||
|
||||
type NewReleaseForm struct {
|
||||
type NewRelease struct {
|
||||
TagName string `binding:"Required"`
|
||||
Target string `form:"tag_target" binding:"Required"`
|
||||
Title string `binding:"Required"`
|
||||
@@ -276,18 +278,18 @@ type NewReleaseForm struct {
|
||||
Prerelease bool
|
||||
}
|
||||
|
||||
func (f *NewReleaseForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
func (f *NewRelease) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
type EditReleaseForm struct {
|
||||
Title string `form:"title" binding:"Required"`
|
||||
Content string `form:"content"`
|
||||
Draft string `form:"draft"`
|
||||
Prerelease bool `form:"prerelease"`
|
||||
type EditRelease struct {
|
||||
Title string `binding:"Required"`
|
||||
Content string
|
||||
Draft string
|
||||
Prerelease bool
|
||||
}
|
||||
|
||||
func (f *EditReleaseForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
func (f *EditRelease) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
@@ -298,7 +300,7 @@ func (f *EditReleaseForm) Validate(ctx *macaron.Context, errs binding.Errors) bi
|
||||
// \__/\ / |__|__|_ \__|
|
||||
// \/ \/
|
||||
|
||||
type NewWikiForm struct {
|
||||
type NewWiki struct {
|
||||
OldTitle string
|
||||
Title string `binding:"Required"`
|
||||
Content string `binding:"Required"`
|
||||
@@ -306,7 +308,7 @@ type NewWikiForm struct {
|
||||
}
|
||||
|
||||
// FIXME: use code generation to generate this method.
|
||||
func (f *NewWikiForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
func (f *NewWiki) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
@@ -317,29 +319,29 @@ func (f *NewWikiForm) Validate(ctx *macaron.Context, errs binding.Errors) bindin
|
||||
// /_______ /\____ | |__||__|
|
||||
// \/ \/
|
||||
|
||||
type EditRepoFileForm struct {
|
||||
type EditRepoFile struct {
|
||||
TreePath string `binding:"Required;MaxSize(500)"`
|
||||
Content string `binding:"Required"`
|
||||
CommitSummary string `binding:"MaxSize(100)`
|
||||
CommitMessage string
|
||||
CommitChoice string `binding:"Required;MaxSize(50)"`
|
||||
NewBranchName string `binding:"AlphaDashDot;MaxSize(100)"`
|
||||
NewBranchName string `binding:"AlphaDashDotSlash;MaxSize(100)"`
|
||||
LastCommit string
|
||||
}
|
||||
|
||||
func (f *EditRepoFileForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
func (f *EditRepoFile) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
func (f *EditRepoFileForm) IsNewBrnach() bool {
|
||||
func (f *EditRepoFile) IsNewBrnach() bool {
|
||||
return f.CommitChoice == "commit-to-new-branch"
|
||||
}
|
||||
|
||||
type EditPreviewDiffForm struct {
|
||||
type EditPreviewDiff struct {
|
||||
Content string
|
||||
}
|
||||
|
||||
func (f *EditPreviewDiffForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
func (f *EditPreviewDiff) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
@@ -351,7 +353,7 @@ func (f *EditPreviewDiffForm) Validate(ctx *macaron.Context, errs binding.Errors
|
||||
// |__| \/ \/
|
||||
//
|
||||
|
||||
type UploadRepoFileForm struct {
|
||||
type UploadRepoFile struct {
|
||||
TreePath string `binding:MaxSize(500)"`
|
||||
CommitSummary string `binding:"MaxSize(100)`
|
||||
CommitMessage string
|
||||
@@ -360,19 +362,19 @@ type UploadRepoFileForm struct {
|
||||
Files []string
|
||||
}
|
||||
|
||||
func (f *UploadRepoFileForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
func (f *UploadRepoFile) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
func (f *UploadRepoFileForm) IsNewBrnach() bool {
|
||||
func (f *UploadRepoFile) IsNewBrnach() bool {
|
||||
return f.CommitChoice == "commit-to-new-branch"
|
||||
}
|
||||
|
||||
type RemoveUploadFileForm struct {
|
||||
type RemoveUploadFile struct {
|
||||
File string `binding:"Required;MaxSize(50)"`
|
||||
}
|
||||
|
||||
func (f *RemoveUploadFileForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
func (f *RemoveUploadFile) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
@@ -383,17 +385,17 @@ func (f *RemoveUploadFileForm) Validate(ctx *macaron.Context, errs binding.Error
|
||||
// /_______ /\___ >____/\___ >__| \___ >
|
||||
// \/ \/ \/ \/
|
||||
|
||||
type DeleteRepoFileForm struct {
|
||||
type DeleteRepoFile struct {
|
||||
CommitSummary string `binding:"MaxSize(100)`
|
||||
CommitMessage string
|
||||
CommitChoice string `binding:"Required;MaxSize(50)"`
|
||||
NewBranchName string `binding:"AlphaDashDot;MaxSize(100)"`
|
||||
}
|
||||
|
||||
func (f *DeleteRepoFileForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
func (f *DeleteRepoFile) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
func (f *DeleteRepoFileForm) IsNewBrnach() bool {
|
||||
func (f *DeleteRepoFile) IsNewBrnach() bool {
|
||||
return f.CommitChoice == "commit-to-new-branch"
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package auth
|
||||
package form
|
||||
|
||||
import (
|
||||
"mime/multipart"
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
"gopkg.in/macaron.v1"
|
||||
)
|
||||
|
||||
type InstallForm struct {
|
||||
type Install struct {
|
||||
DbType string `binding:"Required"`
|
||||
DbHost string
|
||||
DbUser string
|
||||
@@ -50,7 +50,7 @@ type InstallForm struct {
|
||||
AdminEmail string `binding:"OmitEmpty;MinSize(3);MaxSize(254);Include(@)" locale:"install.admin_email"`
|
||||
}
|
||||
|
||||
func (f *InstallForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
func (f *Install) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
@@ -61,24 +61,24 @@ func (f *InstallForm) Validate(ctx *macaron.Context, errs binding.Errors) bindin
|
||||
// \____|__ /______/ |____| \___|_ /
|
||||
// \/ \/
|
||||
|
||||
type RegisterForm struct {
|
||||
type Register struct {
|
||||
UserName string `binding:"Required;AlphaDashDot;MaxSize(35)"`
|
||||
Email string `binding:"Required;Email;MaxSize(254)"`
|
||||
Password string `binding:"Required;MaxSize(255)"`
|
||||
Retype string
|
||||
}
|
||||
|
||||
func (f *RegisterForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
func (f *Register) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
type SignInForm struct {
|
||||
type SignIn struct {
|
||||
UserName string `binding:"Required;MaxSize(254)"`
|
||||
Password string `binding:"Required;MaxSize(255)"`
|
||||
Remember bool
|
||||
}
|
||||
|
||||
func (f *SignInForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
func (f *SignIn) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
@@ -89,15 +89,15 @@ func (f *SignInForm) Validate(ctx *macaron.Context, errs binding.Errors) binding
|
||||
// /_______ //_______ / |____| |____| |___\____|__ /\______ /_______ /
|
||||
// \/ \/ \/ \/ \/
|
||||
|
||||
type UpdateProfileForm struct {
|
||||
Name string `binding:"OmitEmpty;MaxSize(35)"`
|
||||
type UpdateProfile struct {
|
||||
Name string `binding:"Required;AlphaDashDot;MaxSize(35)"`
|
||||
FullName string `binding:"MaxSize(100)"`
|
||||
Email string `binding:"Required;Email;MaxSize(254)"`
|
||||
Website string `binding:"Url;MaxSize(100)"`
|
||||
Location string `binding:"MaxSize(50)"`
|
||||
}
|
||||
|
||||
func (f *UpdateProfileForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
func (f *UpdateProfile) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
@@ -106,48 +106,48 @@ const (
|
||||
AVATAR_BYMAIL string = "bymail"
|
||||
)
|
||||
|
||||
type AvatarForm struct {
|
||||
type Avatar struct {
|
||||
Source string
|
||||
Avatar *multipart.FileHeader
|
||||
Gravatar string `binding:"OmitEmpty;Email;MaxSize(254)"`
|
||||
Federavatar bool
|
||||
}
|
||||
|
||||
func (f *AvatarForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
func (f *Avatar) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
type AddEmailForm struct {
|
||||
type AddEmail struct {
|
||||
Email string `binding:"Required;Email;MaxSize(254)"`
|
||||
}
|
||||
|
||||
func (f *AddEmailForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
func (f *AddEmail) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
type ChangePasswordForm struct {
|
||||
OldPassword string `form:"old_password" binding:"Required;MinSize(1);MaxSize(255)"`
|
||||
Password string `form:"password" binding:"Required;MaxSize(255)"`
|
||||
Retype string `form:"retype"`
|
||||
type ChangePassword struct {
|
||||
OldPassword string `binding:"Required;MinSize(1);MaxSize(255)"`
|
||||
Password string `binding:"Required;MaxSize(255)"`
|
||||
Retype string
|
||||
}
|
||||
|
||||
func (f *ChangePasswordForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
func (f *ChangePassword) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
type AddSSHKeyForm struct {
|
||||
type AddSSHKey struct {
|
||||
Title string `binding:"Required;MaxSize(50)"`
|
||||
Content string `binding:"Required"`
|
||||
}
|
||||
|
||||
func (f *AddSSHKeyForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
func (f *AddSSHKey) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
type NewAccessTokenForm struct {
|
||||
type NewAccessToken struct {
|
||||
Name string `binding:"Required"`
|
||||
}
|
||||
|
||||
func (f *NewAccessTokenForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
func (f *NewAccessToken) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
@@ -36,16 +36,18 @@ func NewMessageFrom(to []string, from, subject, htmlBody string) *Message {
|
||||
msg.SetHeader("Subject", subject)
|
||||
msg.SetDateHeader("Date", time.Now())
|
||||
|
||||
body, err := html2text.FromString(htmlBody)
|
||||
if err != nil {
|
||||
log.Error(4, "html2text.FromString: %v", err)
|
||||
msg.SetBody("text/html", htmlBody)
|
||||
} else {
|
||||
msg.SetBody("text/plain", body)
|
||||
if setting.MailService.EnableHTMLAlternative {
|
||||
msg.AddAlternative("text/html", htmlBody)
|
||||
contentType := "text/html"
|
||||
body := htmlBody
|
||||
if setting.MailService.UsePlainText {
|
||||
plainBody, err := html2text.FromString(htmlBody)
|
||||
if err != nil {
|
||||
log.Error(2, "html2text.FromString: %v", err)
|
||||
} else {
|
||||
contentType = "text/plain"
|
||||
body = plainBody
|
||||
}
|
||||
}
|
||||
msg.SetBody(contentType, body)
|
||||
|
||||
return &Message{
|
||||
Message: msg,
|
||||
|
||||
@@ -192,42 +192,11 @@ func (options *Renderer) ListItem(out *bytes.Buffer, text []byte, flags int) {
|
||||
// Note: this section is for purpose of increase performance and
|
||||
// reduce memory allocation at runtime since they are constant literals.
|
||||
var (
|
||||
svgSuffix = []byte(".svg")
|
||||
svgSuffixWithMark = []byte(".svg?")
|
||||
spaceBytes = []byte(" ")
|
||||
spaceEncodedBytes = []byte("%20")
|
||||
pound = []byte("#")
|
||||
space = " "
|
||||
spaceEncoded = "%20"
|
||||
pound = []byte("#")
|
||||
space = " "
|
||||
spaceEncoded = "%20"
|
||||
)
|
||||
|
||||
// Image defines how images should be processed to produce corresponding HTML elements.
|
||||
func (r *Renderer) Image(out *bytes.Buffer, link []byte, title []byte, alt []byte) {
|
||||
prefix := strings.Replace(r.urlPrefix, "/src/", "/raw/", 1)
|
||||
if len(link) > 0 {
|
||||
if isLink(link) {
|
||||
// External link with .svg suffix usually means CI status.
|
||||
// TODO: define a keyword to allow non-svg images render as external link.
|
||||
if bytes.HasSuffix(link, svgSuffix) || bytes.Contains(link, svgSuffixWithMark) {
|
||||
r.Renderer.Image(out, link, title, alt)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
if link[0] != '/' {
|
||||
prefix += "/"
|
||||
}
|
||||
link = bytes.Replace([]byte((prefix + string(link))), spaceBytes, spaceEncodedBytes, -1)
|
||||
fmt.Println(333, string(link))
|
||||
}
|
||||
}
|
||||
|
||||
out.WriteString(`<a href="`)
|
||||
out.Write(link)
|
||||
out.WriteString(`">`)
|
||||
r.Renderer.Image(out, link, title, alt)
|
||||
out.WriteString("</a>")
|
||||
}
|
||||
|
||||
// cutoutVerbosePrefix cutouts URL prefix including sub-path to
|
||||
// return a clean unified string of request URL path.
|
||||
func cutoutVerbosePrefix(prefix string) string {
|
||||
@@ -353,14 +322,72 @@ var (
|
||||
rightAngleBracket = []byte(">")
|
||||
)
|
||||
|
||||
var noEndTags = []string{"img", "input", "br", "hr"}
|
||||
var noEndTags = []string{"input", "br", "hr", "img"}
|
||||
|
||||
// wrapImgWithLink warps link to standalone <img> tags.
|
||||
func wrapImgWithLink(urlPrefix string, buf *bytes.Buffer, token html.Token) {
|
||||
var src, alt string
|
||||
// Extract "src" and "alt" attributes
|
||||
for i := range token.Attr {
|
||||
switch token.Attr[i].Key {
|
||||
case "src":
|
||||
src = token.Attr[i].Val
|
||||
case "alt":
|
||||
alt = token.Attr[i].Val
|
||||
}
|
||||
}
|
||||
|
||||
// Skip in case the "src" is empty
|
||||
if len(src) == 0 {
|
||||
buf.WriteString(token.String())
|
||||
return
|
||||
}
|
||||
|
||||
// Prepend repository base URL for internal links
|
||||
needPrepend := !isLink([]byte(src))
|
||||
if needPrepend {
|
||||
urlPrefix = strings.Replace(urlPrefix, "/src/", "/raw/", 1)
|
||||
if src[0] != '/' {
|
||||
urlPrefix += "/"
|
||||
}
|
||||
}
|
||||
|
||||
buf.WriteString(`<a href="`)
|
||||
if needPrepend {
|
||||
buf.WriteString(urlPrefix)
|
||||
buf.WriteString(src)
|
||||
} else {
|
||||
buf.WriteString(src)
|
||||
}
|
||||
buf.WriteString(`">`)
|
||||
|
||||
if needPrepend {
|
||||
src = strings.Replace(urlPrefix+string(src), " ", "%20", -1)
|
||||
buf.WriteString(`<img src="`)
|
||||
buf.WriteString(src)
|
||||
buf.WriteString(`"`)
|
||||
|
||||
if len(alt) > 0 {
|
||||
buf.WriteString(` alt="`)
|
||||
buf.WriteString(alt)
|
||||
buf.WriteString(`"`)
|
||||
}
|
||||
|
||||
buf.WriteString(`>`)
|
||||
|
||||
} else {
|
||||
buf.WriteString(token.String())
|
||||
}
|
||||
|
||||
buf.WriteString(`</a>`)
|
||||
}
|
||||
|
||||
// PostProcess treats different types of HTML differently,
|
||||
// and only renders special links for plain text blocks.
|
||||
func PostProcess(rawHtml []byte, urlPrefix string, metas map[string]string) []byte {
|
||||
func PostProcess(rawHTML []byte, urlPrefix string, metas map[string]string) []byte {
|
||||
startTags := make([]string, 0, 5)
|
||||
var buf bytes.Buffer
|
||||
tokenizer := html.NewTokenizer(bytes.NewReader(rawHtml))
|
||||
buf := bytes.NewBuffer(nil)
|
||||
tokenizer := html.NewTokenizer(bytes.NewReader(rawHTML))
|
||||
|
||||
OUTER_LOOP:
|
||||
for html.ErrorToken != tokenizer.Next() {
|
||||
@@ -370,8 +397,14 @@ OUTER_LOOP:
|
||||
buf.Write(RenderSpecialLink([]byte(token.String()), urlPrefix, metas))
|
||||
|
||||
case html.StartTagToken:
|
||||
buf.WriteString(token.String())
|
||||
tagName := token.Data
|
||||
|
||||
if tagName == "img" {
|
||||
wrapImgWithLink(urlPrefix, buf, token)
|
||||
continue OUTER_LOOP
|
||||
}
|
||||
|
||||
buf.WriteString(token.String())
|
||||
// If this is an excluded tag, we skip processing all output until a close tag is encountered.
|
||||
if strings.EqualFold("a", tagName) || strings.EqualFold("code", tagName) || strings.EqualFold("pre", tagName) {
|
||||
stackNum := 1
|
||||
@@ -381,14 +414,14 @@ OUTER_LOOP:
|
||||
// Copy the token to the output verbatim
|
||||
buf.WriteString(token.String())
|
||||
|
||||
if token.Type == html.StartTagToken {
|
||||
// Stack number doesn't increate for tags without end tags.
|
||||
if token.Type == html.StartTagToken && !com.IsSliceContainsStr(noEndTags, token.Data) {
|
||||
stackNum++
|
||||
}
|
||||
|
||||
// If this is the close tag to the outer-most, we are done
|
||||
if token.Type == html.EndTagToken {
|
||||
stackNum--
|
||||
|
||||
if stackNum <= 0 && strings.EqualFold(tagName, token.Data) {
|
||||
break
|
||||
}
|
||||
@@ -397,8 +430,8 @@ OUTER_LOOP:
|
||||
continue OUTER_LOOP
|
||||
}
|
||||
|
||||
if !com.IsSliceContainsStr(noEndTags, token.Data) {
|
||||
startTags = append(startTags, token.Data)
|
||||
if !com.IsSliceContainsStr(noEndTags, tagName) {
|
||||
startTags = append(startTags, tagName)
|
||||
}
|
||||
|
||||
case html.EndTagToken:
|
||||
@@ -422,7 +455,7 @@ OUTER_LOOP:
|
||||
|
||||
// If we are not at the end of the input, then some other parsing error has occurred,
|
||||
// so return the input verbatim.
|
||||
return rawHtml
|
||||
return rawHTML
|
||||
}
|
||||
|
||||
// Render renders Markdown to HTML with special links.
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
package setting
|
||||
|
||||
import (
|
||||
_ "github.com/kardianos/minwinsvc"
|
||||
_ "github.com/gogits/minwinsvc"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
||||
@@ -142,7 +142,7 @@ var (
|
||||
Types []string
|
||||
QueueLength int
|
||||
DeliverTimeout int
|
||||
SkipTLSVerify bool
|
||||
SkipTLSVerify bool `ini:"SKIP_TLS_VERIFY"`
|
||||
PagingNum int
|
||||
}
|
||||
|
||||
@@ -751,18 +751,18 @@ func newSessionService() {
|
||||
|
||||
// Mailer represents mail service.
|
||||
type Mailer struct {
|
||||
QueueLength int
|
||||
Name string
|
||||
Host string
|
||||
From string
|
||||
FromEmail string
|
||||
User, Passwd string
|
||||
DisableHelo bool
|
||||
HeloHostname string
|
||||
SkipVerify bool
|
||||
UseCertificate bool
|
||||
CertFile, KeyFile string
|
||||
EnableHTMLAlternative bool
|
||||
QueueLength int
|
||||
Subject string
|
||||
Host string
|
||||
From string
|
||||
FromEmail string
|
||||
User, Passwd string
|
||||
DisableHelo bool
|
||||
HeloHostname string
|
||||
SkipVerify bool
|
||||
UseCertificate bool
|
||||
CertFile, KeyFile string
|
||||
UsePlainText bool
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -777,18 +777,18 @@ func newMailService() {
|
||||
}
|
||||
|
||||
MailService = &Mailer{
|
||||
QueueLength: sec.Key("SEND_BUFFER_LEN").MustInt(100),
|
||||
Name: sec.Key("NAME").MustString(AppName),
|
||||
Host: sec.Key("HOST").String(),
|
||||
User: sec.Key("USER").String(),
|
||||
Passwd: sec.Key("PASSWD").String(),
|
||||
DisableHelo: sec.Key("DISABLE_HELO").MustBool(),
|
||||
HeloHostname: sec.Key("HELO_HOSTNAME").String(),
|
||||
SkipVerify: sec.Key("SKIP_VERIFY").MustBool(),
|
||||
UseCertificate: sec.Key("USE_CERTIFICATE").MustBool(),
|
||||
CertFile: sec.Key("CERT_FILE").String(),
|
||||
KeyFile: sec.Key("KEY_FILE").String(),
|
||||
EnableHTMLAlternative: sec.Key("ENABLE_HTML_ALTERNATIVE").MustBool(),
|
||||
QueueLength: sec.Key("SEND_BUFFER_LEN").MustInt(100),
|
||||
Subject: sec.Key("SUBJECT").MustString(AppName),
|
||||
Host: sec.Key("HOST").String(),
|
||||
User: sec.Key("USER").String(),
|
||||
Passwd: sec.Key("PASSWD").String(),
|
||||
DisableHelo: sec.Key("DISABLE_HELO").MustBool(),
|
||||
HeloHostname: sec.Key("HELO_HOSTNAME").String(),
|
||||
SkipVerify: sec.Key("SKIP_VERIFY").MustBool(),
|
||||
UseCertificate: sec.Key("USE_CERTIFICATE").MustBool(),
|
||||
CertFile: sec.Key("CERT_FILE").String(),
|
||||
KeyFile: sec.Key("KEY_FILE").String(),
|
||||
UsePlainText: sec.Key("USE_PLAIN_TEXT").MustBool(),
|
||||
}
|
||||
MailService.From = sec.Key("FROM").MustString(MailService.User)
|
||||
|
||||
|
||||
@@ -242,12 +242,14 @@ func ActionIcon(opType int) string {
|
||||
switch opType {
|
||||
case 1, 8: // Create and transfer repository
|
||||
return "repo"
|
||||
case 5, 9: // Commit repository
|
||||
case 5: // Commit repository
|
||||
return "git-commit"
|
||||
case 6: // Create issue
|
||||
return "issue-opened"
|
||||
case 7: // New pull request
|
||||
return "git-pull-request"
|
||||
case 9: // Push tag
|
||||
return "tag"
|
||||
case 10: // Comment issue
|
||||
return "comment-discussion"
|
||||
case 11: // Merge pull request
|
||||
@@ -256,6 +258,12 @@ func ActionIcon(opType int) string {
|
||||
return "issue-closed"
|
||||
case 13, 15: // Reopen issue or pull request
|
||||
return "issue-reopened"
|
||||
case 16: // Create branch
|
||||
return "git-branch"
|
||||
case 17, 18: // Delete branch or tag
|
||||
return "alert"
|
||||
case 19: // Fork a repository
|
||||
return "repo-forked"
|
||||
default:
|
||||
return "invalid type"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"CodeKitInfo": "This is a CodeKit 2.x project configuration file. It is designed to sync project settings across multiple machines. MODIFYING THE CONTENTS OF THIS FILE IS A POOR LIFE DECISION. If you do so, you will likely cause CodeKit to crash. This file is not useful unless accompanied by the project that created it in CodeKit 2. This file is not backwards-compatible with CodeKit 1.x. For more information, see: http:\/\/incident57.com\/codekit",
|
||||
"creatorBuild": "19127",
|
||||
"creatorBuild": "19115",
|
||||
"files": {
|
||||
"\/css\/github.min.css": {
|
||||
"fileType": 16,
|
||||
@@ -20,11 +20,11 @@
|
||||
"outputPathIsOutsideProject": 0,
|
||||
"outputPathIsSetByUser": 0
|
||||
},
|
||||
"\/css\/semantic-2.2.9.min.css": {
|
||||
"\/css\/semantic-2.2.7.min.css": {
|
||||
"fileType": 16,
|
||||
"ignore": 1,
|
||||
"ignoreWasSetByUser": 1,
|
||||
"inputAbbreviatedPath": "\/css\/semantic-2.2.9.min.css",
|
||||
"ignore": 0,
|
||||
"ignoreWasSetByUser": 0,
|
||||
"inputAbbreviatedPath": "\/css\/semantic-2.2.7.min.css",
|
||||
"outputAbbreviatedPath": "No Output Path",
|
||||
"outputPathIsOutsideProject": 0,
|
||||
"outputPathIsSetByUser": 0
|
||||
@@ -66,7 +66,7 @@
|
||||
"fileType": 32768,
|
||||
"ignore": 0,
|
||||
"ignoreWasSetByUser": 0,
|
||||
"initialSize": 514087,
|
||||
"initialSize": 4048,
|
||||
"inputAbbreviatedPath": "\/img\/avatar_default.png",
|
||||
"outputAbbreviatedPath": "\/img\/avatar_default.png",
|
||||
"outputPathIsOutsideProject": 0,
|
||||
@@ -161,12 +161,12 @@
|
||||
"outputStyle": 1,
|
||||
"syntaxCheckerStyle": 1
|
||||
},
|
||||
"\/js\/semantic-2.2.9.min.js": {
|
||||
"\/js\/semantic-2.2.7.min.js": {
|
||||
"fileType": 64,
|
||||
"ignore": 1,
|
||||
"ignoreWasSetByUser": 1,
|
||||
"inputAbbreviatedPath": "\/js\/semantic-2.2.9.min.js",
|
||||
"outputAbbreviatedPath": "\/js\/min\/semantic-2.2.9.min-min.js",
|
||||
"ignore": 0,
|
||||
"ignoreWasSetByUser": 0,
|
||||
"inputAbbreviatedPath": "\/js\/semantic-2.2.7.min.js",
|
||||
"outputAbbreviatedPath": "\/js\/min\/semantic-2.2.7.min-min.js",
|
||||
"outputPathIsOutsideProject": 0,
|
||||
"outputPathIsSetByUser": 0,
|
||||
"outputStyle": 1,
|
||||
|
||||
@@ -2921,7 +2921,7 @@ footer .ui.language .menu {
|
||||
font-family: Consolas, monospace;
|
||||
}
|
||||
.feeds .news code {
|
||||
padding: 1px;
|
||||
padding: 3px;
|
||||
font-size: 85%;
|
||||
background-color: rgba(0, 0, 0, 0.04);
|
||||
border-radius: 3px;
|
||||
@@ -3019,6 +3019,19 @@ footer .ui.language .menu {
|
||||
.admin.config #test-mail-btn {
|
||||
margin-left: 5px;
|
||||
}
|
||||
.admin.config table tbody tr td:first-child {
|
||||
font-weight: bold;
|
||||
}
|
||||
.admin.config pre {
|
||||
background-color: #f7f7f7;
|
||||
padding: 5px;
|
||||
}
|
||||
.admin.config .log-config table tbody tr td:first-child {
|
||||
width: 100px;
|
||||
}
|
||||
.admin.config .log-config table tbody tr td:not(first-child) {
|
||||
max-width: 0;
|
||||
}
|
||||
.explore {
|
||||
padding-top: 15px;
|
||||
padding-bottom: 80px;
|
||||
|
||||
@@ -62,5 +62,22 @@
|
||||
#test-mail-btn {
|
||||
margin-left: 5px;
|
||||
}
|
||||
table tbody tr td:first-child {
|
||||
font-weight: bold;
|
||||
}
|
||||
pre {
|
||||
background-color: #f7f7f7;
|
||||
padding: 5px;
|
||||
}
|
||||
.log-config {
|
||||
table tbody tr td {
|
||||
&:first-child {
|
||||
width: 100px;
|
||||
}
|
||||
&:not(first-child) {
|
||||
max-width: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@
|
||||
font-family: Consolas, monospace;
|
||||
}
|
||||
code {
|
||||
padding: 1px;
|
||||
padding: 3px;
|
||||
font-size: 85%;
|
||||
background-color: rgba(0, 0, 0, 0.04);
|
||||
border-radius: 3px;
|
||||
|
||||
@@ -240,7 +240,7 @@ func Config(ctx *context.Context) {
|
||||
Mode: strings.Title(setting.LogModes[i]),
|
||||
}
|
||||
|
||||
result, _ := json.Marshal(setting.LogConfigs[i])
|
||||
result, _ := json.MarshalIndent(setting.LogConfigs[i], "", " ")
|
||||
loggers[i].Config = string(result)
|
||||
}
|
||||
ctx.Data["Loggers"] = loggers
|
||||
|
||||
@@ -12,10 +12,10 @@ import (
|
||||
log "gopkg.in/clog.v1"
|
||||
|
||||
"github.com/gogits/gogs/models"
|
||||
"github.com/gogits/gogs/modules/auth"
|
||||
"github.com/gogits/gogs/modules/auth/ldap"
|
||||
"github.com/gogits/gogs/modules/base"
|
||||
"github.com/gogits/gogs/modules/context"
|
||||
"github.com/gogits/gogs/modules/form"
|
||||
"github.com/gogits/gogs/modules/setting"
|
||||
)
|
||||
|
||||
@@ -76,64 +76,64 @@ func NewAuthSource(ctx *context.Context) {
|
||||
ctx.HTML(200, AUTH_NEW)
|
||||
}
|
||||
|
||||
func parseLDAPConfig(form auth.AuthenticationForm) *models.LDAPConfig {
|
||||
func parseLDAPConfig(f form.Authentication) *models.LDAPConfig {
|
||||
return &models.LDAPConfig{
|
||||
Source: &ldap.Source{
|
||||
Name: form.Name,
|
||||
Host: form.Host,
|
||||
Port: form.Port,
|
||||
SecurityProtocol: ldap.SecurityProtocol(form.SecurityProtocol),
|
||||
SkipVerify: form.SkipVerify,
|
||||
BindDN: form.BindDN,
|
||||
UserDN: form.UserDN,
|
||||
BindPassword: form.BindPassword,
|
||||
UserBase: form.UserBase,
|
||||
AttributeUsername: form.AttributeUsername,
|
||||
AttributeName: form.AttributeName,
|
||||
AttributeSurname: form.AttributeSurname,
|
||||
AttributeMail: form.AttributeMail,
|
||||
AttributesInBind: form.AttributesInBind,
|
||||
Filter: form.Filter,
|
||||
AdminFilter: form.AdminFilter,
|
||||
Name: f.Name,
|
||||
Host: f.Host,
|
||||
Port: f.Port,
|
||||
SecurityProtocol: ldap.SecurityProtocol(f.SecurityProtocol),
|
||||
SkipVerify: f.SkipVerify,
|
||||
BindDN: f.BindDN,
|
||||
UserDN: f.UserDN,
|
||||
BindPassword: f.BindPassword,
|
||||
UserBase: f.UserBase,
|
||||
AttributeUsername: f.AttributeUsername,
|
||||
AttributeName: f.AttributeName,
|
||||
AttributeSurname: f.AttributeSurname,
|
||||
AttributeMail: f.AttributeMail,
|
||||
AttributesInBind: f.AttributesInBind,
|
||||
Filter: f.Filter,
|
||||
AdminFilter: f.AdminFilter,
|
||||
Enabled: true,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func parseSMTPConfig(form auth.AuthenticationForm) *models.SMTPConfig {
|
||||
func parseSMTPConfig(f form.Authentication) *models.SMTPConfig {
|
||||
return &models.SMTPConfig{
|
||||
Auth: form.SMTPAuth,
|
||||
Host: form.SMTPHost,
|
||||
Port: form.SMTPPort,
|
||||
AllowedDomains: form.AllowedDomains,
|
||||
TLS: form.TLS,
|
||||
SkipVerify: form.SkipVerify,
|
||||
Auth: f.SMTPAuth,
|
||||
Host: f.SMTPHost,
|
||||
Port: f.SMTPPort,
|
||||
AllowedDomains: f.AllowedDomains,
|
||||
TLS: f.TLS,
|
||||
SkipVerify: f.SkipVerify,
|
||||
}
|
||||
}
|
||||
|
||||
func NewAuthSourcePost(ctx *context.Context, form auth.AuthenticationForm) {
|
||||
func NewAuthSourcePost(ctx *context.Context, f form.Authentication) {
|
||||
ctx.Data["Title"] = ctx.Tr("admin.auths.new")
|
||||
ctx.Data["PageIsAdmin"] = true
|
||||
ctx.Data["PageIsAdminAuthentications"] = true
|
||||
|
||||
ctx.Data["CurrentTypeName"] = models.LoginNames[models.LoginType(form.Type)]
|
||||
ctx.Data["CurrentSecurityProtocol"] = models.SecurityProtocolNames[ldap.SecurityProtocol(form.SecurityProtocol)]
|
||||
ctx.Data["CurrentTypeName"] = models.LoginNames[models.LoginType(f.Type)]
|
||||
ctx.Data["CurrentSecurityProtocol"] = models.SecurityProtocolNames[ldap.SecurityProtocol(f.SecurityProtocol)]
|
||||
ctx.Data["AuthSources"] = authSources
|
||||
ctx.Data["SecurityProtocols"] = securityProtocols
|
||||
ctx.Data["SMTPAuths"] = models.SMTPAuths
|
||||
|
||||
hasTLS := false
|
||||
var config core.Conversion
|
||||
switch models.LoginType(form.Type) {
|
||||
switch models.LoginType(f.Type) {
|
||||
case models.LOGIN_LDAP, models.LOGIN_DLDAP:
|
||||
config = parseLDAPConfig(form)
|
||||
hasTLS = ldap.SecurityProtocol(form.SecurityProtocol) > ldap.SECURITY_PROTOCOL_UNENCRYPTED
|
||||
config = parseLDAPConfig(f)
|
||||
hasTLS = ldap.SecurityProtocol(f.SecurityProtocol) > ldap.SECURITY_PROTOCOL_UNENCRYPTED
|
||||
case models.LOGIN_SMTP:
|
||||
config = parseSMTPConfig(form)
|
||||
config = parseSMTPConfig(f)
|
||||
hasTLS = true
|
||||
case models.LOGIN_PAM:
|
||||
config = &models.PAMConfig{
|
||||
ServiceName: form.PAMServiceName,
|
||||
ServiceName: f.PAMServiceName,
|
||||
}
|
||||
default:
|
||||
ctx.Error(400)
|
||||
@@ -147,23 +147,23 @@ func NewAuthSourcePost(ctx *context.Context, form auth.AuthenticationForm) {
|
||||
}
|
||||
|
||||
if err := models.CreateLoginSource(&models.LoginSource{
|
||||
Type: models.LoginType(form.Type),
|
||||
Name: form.Name,
|
||||
IsActived: form.IsActive,
|
||||
Type: models.LoginType(f.Type),
|
||||
Name: f.Name,
|
||||
IsActived: f.IsActive,
|
||||
Cfg: config,
|
||||
}); err != nil {
|
||||
if models.IsErrLoginSourceAlreadyExist(err) {
|
||||
ctx.Data["Err_Name"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("admin.auths.login_source_exist", err.(models.ErrLoginSourceAlreadyExist).Name), AUTH_NEW, form)
|
||||
ctx.RenderWithErr(ctx.Tr("admin.auths.login_source_exist", err.(models.ErrLoginSourceAlreadyExist).Name), AUTH_NEW, f)
|
||||
} else {
|
||||
ctx.Handle(500, "CreateSource", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
log.Trace("Authentication created by admin(%s): %s", ctx.User.Name, form.Name)
|
||||
log.Trace("Authentication created by admin(%s): %s", ctx.User.Name, f.Name)
|
||||
|
||||
ctx.Flash.Success(ctx.Tr("admin.auths.new_success", form.Name))
|
||||
ctx.Flash.Success(ctx.Tr("admin.auths.new_success", f.Name))
|
||||
ctx.Redirect(setting.AppSubUrl + "/admin/auths")
|
||||
}
|
||||
|
||||
@@ -186,7 +186,7 @@ func EditAuthSource(ctx *context.Context) {
|
||||
ctx.HTML(200, AUTH_EDIT)
|
||||
}
|
||||
|
||||
func EditAuthSourcePost(ctx *context.Context, form auth.AuthenticationForm) {
|
||||
func EditAuthSourcePost(ctx *context.Context, f form.Authentication) {
|
||||
ctx.Data["Title"] = ctx.Tr("admin.auths.edit")
|
||||
ctx.Data["PageIsAdmin"] = true
|
||||
ctx.Data["PageIsAdminAuthentications"] = true
|
||||
@@ -207,22 +207,22 @@ func EditAuthSourcePost(ctx *context.Context, form auth.AuthenticationForm) {
|
||||
}
|
||||
|
||||
var config core.Conversion
|
||||
switch models.LoginType(form.Type) {
|
||||
switch models.LoginType(f.Type) {
|
||||
case models.LOGIN_LDAP, models.LOGIN_DLDAP:
|
||||
config = parseLDAPConfig(form)
|
||||
config = parseLDAPConfig(f)
|
||||
case models.LOGIN_SMTP:
|
||||
config = parseSMTPConfig(form)
|
||||
config = parseSMTPConfig(f)
|
||||
case models.LOGIN_PAM:
|
||||
config = &models.PAMConfig{
|
||||
ServiceName: form.PAMServiceName,
|
||||
ServiceName: f.PAMServiceName,
|
||||
}
|
||||
default:
|
||||
ctx.Error(400)
|
||||
return
|
||||
}
|
||||
|
||||
source.Name = form.Name
|
||||
source.IsActived = form.IsActive
|
||||
source.Name = f.Name
|
||||
source.IsActived = f.IsActive
|
||||
source.Cfg = config
|
||||
if err := models.UpdateSource(source); err != nil {
|
||||
ctx.Handle(500, "UpdateSource", err)
|
||||
@@ -231,7 +231,7 @@ func EditAuthSourcePost(ctx *context.Context, form auth.AuthenticationForm) {
|
||||
log.Trace("Authentication changed by admin(%s): %d", ctx.User.Name, source.ID)
|
||||
|
||||
ctx.Flash.Success(ctx.Tr("admin.auths.update_success"))
|
||||
ctx.Redirect(setting.AppSubUrl + "/admin/auths/" + com.ToStr(form.ID))
|
||||
ctx.Redirect(setting.AppSubUrl + "/admin/auths/" + com.ToStr(f.ID))
|
||||
}
|
||||
|
||||
func DeleteAuthSource(ctx *context.Context) {
|
||||
|
||||
@@ -11,9 +11,9 @@ import (
|
||||
log "gopkg.in/clog.v1"
|
||||
|
||||
"github.com/gogits/gogs/models"
|
||||
"github.com/gogits/gogs/modules/auth"
|
||||
"github.com/gogits/gogs/modules/base"
|
||||
"github.com/gogits/gogs/modules/context"
|
||||
"github.com/gogits/gogs/modules/form"
|
||||
"github.com/gogits/gogs/modules/mailer"
|
||||
"github.com/gogits/gogs/modules/setting"
|
||||
"github.com/gogits/gogs/routers"
|
||||
@@ -58,7 +58,7 @@ func NewUser(ctx *context.Context) {
|
||||
ctx.HTML(200, USER_NEW)
|
||||
}
|
||||
|
||||
func NewUserPost(ctx *context.Context, form auth.AdminCrateUserForm) {
|
||||
func NewUserPost(ctx *context.Context, f form.AdminCrateUser) {
|
||||
ctx.Data["Title"] = ctx.Tr("admin.users.new_account")
|
||||
ctx.Data["PageIsAdmin"] = true
|
||||
ctx.Data["PageIsAdminUsers"] = true
|
||||
@@ -78,19 +78,19 @@ func NewUserPost(ctx *context.Context, form auth.AdminCrateUserForm) {
|
||||
}
|
||||
|
||||
u := &models.User{
|
||||
Name: form.UserName,
|
||||
Email: form.Email,
|
||||
Passwd: form.Password,
|
||||
Name: f.UserName,
|
||||
Email: f.Email,
|
||||
Passwd: f.Password,
|
||||
IsActive: true,
|
||||
LoginType: models.LOGIN_PLAIN,
|
||||
}
|
||||
|
||||
if len(form.LoginType) > 0 {
|
||||
fields := strings.Split(form.LoginType, "-")
|
||||
if len(f.LoginType) > 0 {
|
||||
fields := strings.Split(f.LoginType, "-")
|
||||
if len(fields) == 2 {
|
||||
u.LoginType = models.LoginType(com.StrTo(fields[0]).MustInt())
|
||||
u.LoginSource = com.StrTo(fields[1]).MustInt64()
|
||||
u.LoginName = form.LoginName
|
||||
u.LoginName = f.LoginName
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,16 +98,16 @@ func NewUserPost(ctx *context.Context, form auth.AdminCrateUserForm) {
|
||||
switch {
|
||||
case models.IsErrUserAlreadyExist(err):
|
||||
ctx.Data["Err_UserName"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("form.username_been_taken"), USER_NEW, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("form.username_been_taken"), USER_NEW, &f)
|
||||
case models.IsErrEmailAlreadyUsed(err):
|
||||
ctx.Data["Err_Email"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("form.email_been_used"), USER_NEW, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("form.email_been_used"), USER_NEW, &f)
|
||||
case models.IsErrNameReserved(err):
|
||||
ctx.Data["Err_UserName"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("user.form.name_reserved", err.(models.ErrNameReserved).Name), USER_NEW, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("user.form.name_reserved", err.(models.ErrNameReserved).Name), USER_NEW, &f)
|
||||
case models.IsErrNamePatternNotAllowed(err):
|
||||
ctx.Data["Err_UserName"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("user.form.name_pattern_not_allowed", err.(models.ErrNamePatternNotAllowed).Pattern), USER_NEW, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("user.form.name_pattern_not_allowed", err.(models.ErrNamePatternNotAllowed).Pattern), USER_NEW, &f)
|
||||
default:
|
||||
ctx.Handle(500, "CreateUser", err)
|
||||
}
|
||||
@@ -116,7 +116,7 @@ func NewUserPost(ctx *context.Context, form auth.AdminCrateUserForm) {
|
||||
log.Trace("Account created by admin (%s): %s", ctx.User.Name, u.Name)
|
||||
|
||||
// Send email notification.
|
||||
if form.SendNotify && setting.MailService != nil {
|
||||
if f.SendNotify && setting.MailService != nil {
|
||||
mailer.SendRegisterNotifyMail(ctx.Context, models.NewMailerUser(u))
|
||||
}
|
||||
|
||||
@@ -166,7 +166,7 @@ func EditUser(ctx *context.Context) {
|
||||
ctx.HTML(200, USER_EDIT)
|
||||
}
|
||||
|
||||
func EditUserPost(ctx *context.Context, form auth.AdminEditUserForm) {
|
||||
func EditUserPost(ctx *context.Context, f form.AdminEditUser) {
|
||||
ctx.Data["Title"] = ctx.Tr("admin.users.edit_account")
|
||||
ctx.Data["PageIsAdmin"] = true
|
||||
ctx.Data["PageIsAdminUsers"] = true
|
||||
@@ -182,7 +182,7 @@ func EditUserPost(ctx *context.Context, form auth.AdminEditUserForm) {
|
||||
return
|
||||
}
|
||||
|
||||
fields := strings.Split(form.LoginType, "-")
|
||||
fields := strings.Split(f.LoginType, "-")
|
||||
if len(fields) == 2 {
|
||||
loginType := models.LoginType(com.StrTo(fields[0]).MustInt())
|
||||
loginSource := com.StrTo(fields[1]).MustInt64()
|
||||
@@ -193,8 +193,8 @@ func EditUserPost(ctx *context.Context, form auth.AdminEditUserForm) {
|
||||
}
|
||||
}
|
||||
|
||||
if len(form.Password) > 0 {
|
||||
u.Passwd = form.Password
|
||||
if len(f.Password) > 0 {
|
||||
u.Passwd = f.Password
|
||||
var err error
|
||||
if u.Salt, err = models.GetUserSalt(); err != nil {
|
||||
ctx.Handle(500, "UpdateUser", err)
|
||||
@@ -203,22 +203,22 @@ func EditUserPost(ctx *context.Context, form auth.AdminEditUserForm) {
|
||||
u.EncodePasswd()
|
||||
}
|
||||
|
||||
u.LoginName = form.LoginName
|
||||
u.FullName = form.FullName
|
||||
u.Email = form.Email
|
||||
u.Website = form.Website
|
||||
u.Location = form.Location
|
||||
u.MaxRepoCreation = form.MaxRepoCreation
|
||||
u.IsActive = form.Active
|
||||
u.IsAdmin = form.Admin
|
||||
u.AllowGitHook = form.AllowGitHook
|
||||
u.AllowImportLocal = form.AllowImportLocal
|
||||
u.ProhibitLogin = form.ProhibitLogin
|
||||
u.LoginName = f.LoginName
|
||||
u.FullName = f.FullName
|
||||
u.Email = f.Email
|
||||
u.Website = f.Website
|
||||
u.Location = f.Location
|
||||
u.MaxRepoCreation = f.MaxRepoCreation
|
||||
u.IsActive = f.Active
|
||||
u.IsAdmin = f.Admin
|
||||
u.AllowGitHook = f.AllowGitHook
|
||||
u.AllowImportLocal = f.AllowImportLocal
|
||||
u.ProhibitLogin = f.ProhibitLogin
|
||||
|
||||
if err := models.UpdateUser(u); err != nil {
|
||||
if models.IsErrEmailAlreadyUsed(err) {
|
||||
ctx.Data["Err_Email"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("form.email_been_used"), USER_EDIT, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("form.email_been_used"), USER_EDIT, &f)
|
||||
} else {
|
||||
ctx.Handle(500, "UpdateUser", err)
|
||||
}
|
||||
|
||||
@@ -13,8 +13,8 @@ import (
|
||||
api "github.com/gogits/go-gogs-client"
|
||||
|
||||
"github.com/gogits/gogs/models"
|
||||
"github.com/gogits/gogs/modules/auth"
|
||||
"github.com/gogits/gogs/modules/context"
|
||||
"github.com/gogits/gogs/modules/form"
|
||||
"github.com/gogits/gogs/routers/api/v1/admin"
|
||||
"github.com/gogits/gogs/routers/api/v1/misc"
|
||||
"github.com/gogits/gogs/routers/api/v1/org"
|
||||
@@ -237,7 +237,7 @@ func RegisterRoutes(m *macaron.Macaron) {
|
||||
})
|
||||
|
||||
m.Group("/repos", func() {
|
||||
m.Post("/migrate", bind(auth.MigrateRepoForm{}), repo.Migrate)
|
||||
m.Post("/migrate", bind(form.MigrateRepo{}), repo.Migrate)
|
||||
m.Combo("/:username/:reponame").Get(repo.Get).
|
||||
Delete(repo.Delete)
|
||||
|
||||
|
||||
@@ -12,8 +12,8 @@ import (
|
||||
api "github.com/gogits/go-gogs-client"
|
||||
|
||||
"github.com/gogits/gogs/models"
|
||||
"github.com/gogits/gogs/modules/auth"
|
||||
"github.com/gogits/gogs/modules/context"
|
||||
"github.com/gogits/gogs/modules/form"
|
||||
"github.com/gogits/gogs/modules/setting"
|
||||
"github.com/gogits/gogs/routers/api/v1/convert"
|
||||
)
|
||||
@@ -149,7 +149,7 @@ func ListOrgRepositories(ctx *context.APIContext) {
|
||||
}
|
||||
|
||||
func CreateUserRepo(ctx *context.APIContext, owner *models.User, opt api.CreateRepoOption) {
|
||||
repo, err := models.CreateRepository(owner, models.CreateRepoOptions{
|
||||
repo, err := models.CreateRepository(ctx.User, owner, models.CreateRepoOptions{
|
||||
Name: opt.Name,
|
||||
Description: opt.Description,
|
||||
Gitignores: opt.Gitignores,
|
||||
@@ -206,12 +206,12 @@ func CreateOrgRepo(ctx *context.APIContext, opt api.CreateRepoOption) {
|
||||
}
|
||||
|
||||
// https://github.com/gogits/go-gogs-client/wiki/Repositories#migrate
|
||||
func Migrate(ctx *context.APIContext, form auth.MigrateRepoForm) {
|
||||
func Migrate(ctx *context.APIContext, f form.MigrateRepo) {
|
||||
ctxUser := ctx.User
|
||||
// Not equal means context user is an organization,
|
||||
// or is another user/organization if current user is admin.
|
||||
if form.Uid != ctxUser.ID {
|
||||
org, err := models.GetUserByID(form.Uid)
|
||||
if f.Uid != ctxUser.ID {
|
||||
org, err := models.GetUserByID(f.Uid)
|
||||
if err != nil {
|
||||
if models.IsErrUserNotExist(err) {
|
||||
ctx.Error(422, "", err)
|
||||
@@ -236,7 +236,7 @@ func Migrate(ctx *context.APIContext, form auth.MigrateRepoForm) {
|
||||
}
|
||||
}
|
||||
|
||||
remoteAddr, err := form.ParseRemoteAddr(ctx.User)
|
||||
remoteAddr, err := f.ParseRemoteAddr(ctx.User)
|
||||
if err != nil {
|
||||
if models.IsErrInvalidCloneAddr(err) {
|
||||
addrErr := err.(models.ErrInvalidCloneAddr)
|
||||
@@ -256,11 +256,11 @@ func Migrate(ctx *context.APIContext, form auth.MigrateRepoForm) {
|
||||
return
|
||||
}
|
||||
|
||||
repo, err := models.MigrateRepository(ctxUser, models.MigrateRepoOptions{
|
||||
Name: form.RepoName,
|
||||
Description: form.Description,
|
||||
IsPrivate: form.Private || setting.Repository.ForcePrivate,
|
||||
IsMirror: form.Mirror,
|
||||
repo, err := models.MigrateRepository(ctx.User, ctxUser, models.MigrateRepoOptions{
|
||||
Name: f.RepoName,
|
||||
Description: f.Description,
|
||||
IsPrivate: f.Private || setting.Repository.ForcePrivate,
|
||||
IsMirror: f.Mirror,
|
||||
RemoteAddr: remoteAddr,
|
||||
})
|
||||
if err != nil {
|
||||
@@ -273,7 +273,7 @@ func Migrate(ctx *context.APIContext, form auth.MigrateRepoForm) {
|
||||
return
|
||||
}
|
||||
|
||||
log.Trace("Repository migrated: %s/%s", ctxUser.Name, form.RepoName)
|
||||
log.Trace("Repository migrated: %s/%s", ctxUser.Name, f.RepoName)
|
||||
ctx.JSON(201, repo.APIFormat(&api.Permission{true, true, true}))
|
||||
}
|
||||
|
||||
|
||||
@@ -21,10 +21,10 @@ import (
|
||||
"github.com/gogits/git-module"
|
||||
|
||||
"github.com/gogits/gogs/models"
|
||||
"github.com/gogits/gogs/modules/auth"
|
||||
"github.com/gogits/gogs/modules/base"
|
||||
"github.com/gogits/gogs/modules/context"
|
||||
"github.com/gogits/gogs/modules/cron"
|
||||
"github.com/gogits/gogs/modules/form"
|
||||
"github.com/gogits/gogs/modules/mailer"
|
||||
"github.com/gogits/gogs/modules/markdown"
|
||||
"github.com/gogits/gogs/modules/setting"
|
||||
@@ -109,13 +109,13 @@ func InstallInit(ctx *context.Context) {
|
||||
}
|
||||
|
||||
func Install(ctx *context.Context) {
|
||||
form := auth.InstallForm{}
|
||||
f := form.Install{}
|
||||
|
||||
// Database settings
|
||||
form.DbHost = models.DbCfg.Host
|
||||
form.DbUser = models.DbCfg.User
|
||||
form.DbName = models.DbCfg.Name
|
||||
form.DbPath = models.DbCfg.Path
|
||||
f.DbHost = models.DbCfg.Host
|
||||
f.DbUser = models.DbCfg.User
|
||||
f.DbName = models.DbCfg.Name
|
||||
f.DbPath = models.DbCfg.Path
|
||||
|
||||
ctx.Data["CurDbOption"] = "MySQL"
|
||||
switch models.DbCfg.Type {
|
||||
@@ -130,47 +130,47 @@ func Install(ctx *context.Context) {
|
||||
}
|
||||
|
||||
// Application general settings
|
||||
form.AppName = setting.AppName
|
||||
form.RepoRootPath = setting.RepoRootPath
|
||||
f.AppName = setting.AppName
|
||||
f.RepoRootPath = setting.RepoRootPath
|
||||
|
||||
// Note(unknwon): it's hard for Windows users change a running user,
|
||||
// so just use current one if config says default.
|
||||
if setting.IsWindows && setting.RunUser == "git" {
|
||||
form.RunUser = user.CurrentUsername()
|
||||
f.RunUser = user.CurrentUsername()
|
||||
} else {
|
||||
form.RunUser = setting.RunUser
|
||||
f.RunUser = setting.RunUser
|
||||
}
|
||||
|
||||
form.Domain = setting.Domain
|
||||
form.SSHPort = setting.SSH.Port
|
||||
form.UseBuiltinSSHServer = setting.SSH.StartBuiltinServer
|
||||
form.HTTPPort = setting.HTTPPort
|
||||
form.AppUrl = setting.AppUrl
|
||||
form.LogRootPath = setting.LogRootPath
|
||||
f.Domain = setting.Domain
|
||||
f.SSHPort = setting.SSH.Port
|
||||
f.UseBuiltinSSHServer = setting.SSH.StartBuiltinServer
|
||||
f.HTTPPort = setting.HTTPPort
|
||||
f.AppUrl = setting.AppUrl
|
||||
f.LogRootPath = setting.LogRootPath
|
||||
|
||||
// E-mail service settings
|
||||
if setting.MailService != nil {
|
||||
form.SMTPHost = setting.MailService.Host
|
||||
form.SMTPFrom = setting.MailService.From
|
||||
form.SMTPUser = setting.MailService.User
|
||||
f.SMTPHost = setting.MailService.Host
|
||||
f.SMTPFrom = setting.MailService.From
|
||||
f.SMTPUser = setting.MailService.User
|
||||
}
|
||||
form.RegisterConfirm = setting.Service.RegisterEmailConfirm
|
||||
form.MailNotify = setting.Service.EnableNotifyMail
|
||||
f.RegisterConfirm = setting.Service.RegisterEmailConfirm
|
||||
f.MailNotify = setting.Service.EnableNotifyMail
|
||||
|
||||
// Server and other services settings
|
||||
form.OfflineMode = setting.OfflineMode
|
||||
form.DisableGravatar = setting.DisableGravatar
|
||||
form.EnableFederatedAvatar = setting.EnableFederatedAvatar
|
||||
form.DisableRegistration = setting.Service.DisableRegistration
|
||||
form.EnableCaptcha = setting.Service.EnableCaptcha
|
||||
form.RequireSignInView = setting.Service.RequireSignInView
|
||||
f.OfflineMode = setting.OfflineMode
|
||||
f.DisableGravatar = setting.DisableGravatar
|
||||
f.EnableFederatedAvatar = setting.EnableFederatedAvatar
|
||||
f.DisableRegistration = setting.Service.DisableRegistration
|
||||
f.EnableCaptcha = setting.Service.EnableCaptcha
|
||||
f.RequireSignInView = setting.Service.RequireSignInView
|
||||
|
||||
auth.AssignForm(form, ctx.Data)
|
||||
form.Assign(f, ctx.Data)
|
||||
ctx.HTML(200, INSTALL)
|
||||
}
|
||||
|
||||
func InstallPost(ctx *context.Context, form auth.InstallForm) {
|
||||
ctx.Data["CurDbOption"] = form.DbType
|
||||
func InstallPost(ctx *context.Context, f form.Install) {
|
||||
ctx.Data["CurDbOption"] = f.DbType
|
||||
|
||||
if ctx.HasError() {
|
||||
if ctx.HasValue("Err_SMTPEmail") {
|
||||
@@ -187,24 +187,24 @@ func InstallPost(ctx *context.Context, form auth.InstallForm) {
|
||||
}
|
||||
|
||||
if _, err := exec.LookPath("git"); err != nil {
|
||||
ctx.RenderWithErr(ctx.Tr("install.test_git_failed", err), INSTALL, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("install.test_git_failed", err), INSTALL, &f)
|
||||
return
|
||||
}
|
||||
|
||||
// Pass basic check, now test configuration.
|
||||
// Test database setting.
|
||||
dbTypes := map[string]string{"MySQL": "mysql", "PostgreSQL": "postgres", "MSSQL": "mssql", "SQLite3": "sqlite3", "TiDB": "tidb"}
|
||||
models.DbCfg.Type = dbTypes[form.DbType]
|
||||
models.DbCfg.Host = form.DbHost
|
||||
models.DbCfg.User = form.DbUser
|
||||
models.DbCfg.Passwd = form.DbPasswd
|
||||
models.DbCfg.Name = form.DbName
|
||||
models.DbCfg.SSLMode = form.SSLMode
|
||||
models.DbCfg.Path = form.DbPath
|
||||
models.DbCfg.Type = dbTypes[f.DbType]
|
||||
models.DbCfg.Host = f.DbHost
|
||||
models.DbCfg.User = f.DbUser
|
||||
models.DbCfg.Passwd = f.DbPasswd
|
||||
models.DbCfg.Name = f.DbName
|
||||
models.DbCfg.SSLMode = f.SSLMode
|
||||
models.DbCfg.Path = f.DbPath
|
||||
|
||||
if models.DbCfg.Type == "sqlite3" && len(models.DbCfg.Path) == 0 {
|
||||
ctx.Data["Err_DbPath"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("install.err_empty_db_path"), INSTALL, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("install.err_empty_db_path"), INSTALL, &f)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -213,72 +213,72 @@ func InstallPost(ctx *context.Context, form auth.InstallForm) {
|
||||
if err := models.NewTestEngine(x); err != nil {
|
||||
if strings.Contains(err.Error(), `Unknown database type: sqlite3`) {
|
||||
ctx.Data["Err_DbType"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("install.sqlite3_not_available", "https://gogs.io/docs/installation/install_from_binary.html"), INSTALL, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("install.sqlite3_not_available", "https://gogs.io/docs/installation/install_from_binary.html"), INSTALL, &f)
|
||||
} else {
|
||||
ctx.Data["Err_DbSetting"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("install.invalid_db_setting", err), INSTALL, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("install.invalid_db_setting", err), INSTALL, &f)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Test repository root path.
|
||||
form.RepoRootPath = strings.Replace(form.RepoRootPath, "\\", "/", -1)
|
||||
if err := os.MkdirAll(form.RepoRootPath, os.ModePerm); err != nil {
|
||||
f.RepoRootPath = strings.Replace(f.RepoRootPath, "\\", "/", -1)
|
||||
if err := os.MkdirAll(f.RepoRootPath, os.ModePerm); err != nil {
|
||||
ctx.Data["Err_RepoRootPath"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("install.invalid_repo_path", err), INSTALL, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("install.invalid_repo_path", err), INSTALL, &f)
|
||||
return
|
||||
}
|
||||
|
||||
// Test log root path.
|
||||
form.LogRootPath = strings.Replace(form.LogRootPath, "\\", "/", -1)
|
||||
if err := os.MkdirAll(form.LogRootPath, os.ModePerm); err != nil {
|
||||
f.LogRootPath = strings.Replace(f.LogRootPath, "\\", "/", -1)
|
||||
if err := os.MkdirAll(f.LogRootPath, os.ModePerm); err != nil {
|
||||
ctx.Data["Err_LogRootPath"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("install.invalid_log_root_path", err), INSTALL, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("install.invalid_log_root_path", err), INSTALL, &f)
|
||||
return
|
||||
}
|
||||
|
||||
currentUser, match := setting.IsRunUserMatchCurrentUser(form.RunUser)
|
||||
currentUser, match := setting.IsRunUserMatchCurrentUser(f.RunUser)
|
||||
if !match {
|
||||
ctx.Data["Err_RunUser"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("install.run_user_not_match", form.RunUser, currentUser), INSTALL, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("install.run_user_not_match", f.RunUser, currentUser), INSTALL, &f)
|
||||
return
|
||||
}
|
||||
|
||||
// Make sure FROM field is valid
|
||||
if len(form.SMTPFrom) > 0 {
|
||||
_, err := mail.ParseAddress(form.SMTPFrom)
|
||||
if len(f.SMTPFrom) > 0 {
|
||||
_, err := mail.ParseAddress(f.SMTPFrom)
|
||||
if err != nil {
|
||||
ctx.Data["Err_SMTP"] = true
|
||||
ctx.Data["Err_SMTPFrom"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("install.invalid_smtp_from", err), INSTALL, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("install.invalid_smtp_from", err), INSTALL, &f)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Check logic loophole between disable self-registration and no admin account.
|
||||
if form.DisableRegistration && len(form.AdminName) == 0 {
|
||||
if f.DisableRegistration && len(f.AdminName) == 0 {
|
||||
ctx.Data["Err_Services"] = true
|
||||
ctx.Data["Err_Admin"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("install.no_admin_and_disable_registration"), INSTALL, form)
|
||||
ctx.RenderWithErr(ctx.Tr("install.no_admin_and_disable_registration"), INSTALL, f)
|
||||
return
|
||||
}
|
||||
|
||||
// Check admin password.
|
||||
if len(form.AdminName) > 0 && len(form.AdminPasswd) == 0 {
|
||||
if len(f.AdminName) > 0 && len(f.AdminPasswd) == 0 {
|
||||
ctx.Data["Err_Admin"] = true
|
||||
ctx.Data["Err_AdminPasswd"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("install.err_empty_admin_password"), INSTALL, form)
|
||||
ctx.RenderWithErr(ctx.Tr("install.err_empty_admin_password"), INSTALL, f)
|
||||
return
|
||||
}
|
||||
if form.AdminPasswd != form.AdminConfirmPasswd {
|
||||
if f.AdminPasswd != f.AdminConfirmPasswd {
|
||||
ctx.Data["Err_Admin"] = true
|
||||
ctx.Data["Err_AdminPasswd"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("form.password_not_match"), INSTALL, form)
|
||||
ctx.RenderWithErr(ctx.Tr("form.password_not_match"), INSTALL, f)
|
||||
return
|
||||
}
|
||||
|
||||
if form.AppUrl[len(form.AppUrl)-1] != '/' {
|
||||
form.AppUrl += "/"
|
||||
if f.AppUrl[len(f.AppUrl)-1] != '/' {
|
||||
f.AppUrl += "/"
|
||||
}
|
||||
|
||||
// Save settings.
|
||||
@@ -297,39 +297,39 @@ func InstallPost(ctx *context.Context, form auth.InstallForm) {
|
||||
cfg.Section("database").Key("SSL_MODE").SetValue(models.DbCfg.SSLMode)
|
||||
cfg.Section("database").Key("PATH").SetValue(models.DbCfg.Path)
|
||||
|
||||
cfg.Section("").Key("APP_NAME").SetValue(form.AppName)
|
||||
cfg.Section("repository").Key("ROOT").SetValue(form.RepoRootPath)
|
||||
cfg.Section("").Key("RUN_USER").SetValue(form.RunUser)
|
||||
cfg.Section("server").Key("DOMAIN").SetValue(form.Domain)
|
||||
cfg.Section("server").Key("HTTP_PORT").SetValue(form.HTTPPort)
|
||||
cfg.Section("server").Key("ROOT_URL").SetValue(form.AppUrl)
|
||||
cfg.Section("").Key("APP_NAME").SetValue(f.AppName)
|
||||
cfg.Section("repository").Key("ROOT").SetValue(f.RepoRootPath)
|
||||
cfg.Section("").Key("RUN_USER").SetValue(f.RunUser)
|
||||
cfg.Section("server").Key("DOMAIN").SetValue(f.Domain)
|
||||
cfg.Section("server").Key("HTTP_PORT").SetValue(f.HTTPPort)
|
||||
cfg.Section("server").Key("ROOT_URL").SetValue(f.AppUrl)
|
||||
|
||||
if form.SSHPort == 0 {
|
||||
if f.SSHPort == 0 {
|
||||
cfg.Section("server").Key("DISABLE_SSH").SetValue("true")
|
||||
} else {
|
||||
cfg.Section("server").Key("DISABLE_SSH").SetValue("false")
|
||||
cfg.Section("server").Key("SSH_PORT").SetValue(com.ToStr(form.SSHPort))
|
||||
cfg.Section("server").Key("START_SSH_SERVER").SetValue(com.ToStr(form.UseBuiltinSSHServer))
|
||||
cfg.Section("server").Key("SSH_PORT").SetValue(com.ToStr(f.SSHPort))
|
||||
cfg.Section("server").Key("START_SSH_SERVER").SetValue(com.ToStr(f.UseBuiltinSSHServer))
|
||||
}
|
||||
|
||||
if len(strings.TrimSpace(form.SMTPHost)) > 0 {
|
||||
if len(strings.TrimSpace(f.SMTPHost)) > 0 {
|
||||
cfg.Section("mailer").Key("ENABLED").SetValue("true")
|
||||
cfg.Section("mailer").Key("HOST").SetValue(form.SMTPHost)
|
||||
cfg.Section("mailer").Key("FROM").SetValue(form.SMTPFrom)
|
||||
cfg.Section("mailer").Key("USER").SetValue(form.SMTPUser)
|
||||
cfg.Section("mailer").Key("PASSWD").SetValue(form.SMTPPasswd)
|
||||
cfg.Section("mailer").Key("HOST").SetValue(f.SMTPHost)
|
||||
cfg.Section("mailer").Key("FROM").SetValue(f.SMTPFrom)
|
||||
cfg.Section("mailer").Key("USER").SetValue(f.SMTPUser)
|
||||
cfg.Section("mailer").Key("PASSWD").SetValue(f.SMTPPasswd)
|
||||
} else {
|
||||
cfg.Section("mailer").Key("ENABLED").SetValue("false")
|
||||
}
|
||||
cfg.Section("service").Key("REGISTER_EMAIL_CONFIRM").SetValue(com.ToStr(form.RegisterConfirm))
|
||||
cfg.Section("service").Key("ENABLE_NOTIFY_MAIL").SetValue(com.ToStr(form.MailNotify))
|
||||
cfg.Section("service").Key("REGISTER_EMAIL_CONFIRM").SetValue(com.ToStr(f.RegisterConfirm))
|
||||
cfg.Section("service").Key("ENABLE_NOTIFY_MAIL").SetValue(com.ToStr(f.MailNotify))
|
||||
|
||||
cfg.Section("server").Key("OFFLINE_MODE").SetValue(com.ToStr(form.OfflineMode))
|
||||
cfg.Section("picture").Key("DISABLE_GRAVATAR").SetValue(com.ToStr(form.DisableGravatar))
|
||||
cfg.Section("picture").Key("ENABLE_FEDERATED_AVATAR").SetValue(com.ToStr(form.EnableFederatedAvatar))
|
||||
cfg.Section("service").Key("DISABLE_REGISTRATION").SetValue(com.ToStr(form.DisableRegistration))
|
||||
cfg.Section("service").Key("ENABLE_CAPTCHA").SetValue(com.ToStr(form.EnableCaptcha))
|
||||
cfg.Section("service").Key("REQUIRE_SIGNIN_VIEW").SetValue(com.ToStr(form.RequireSignInView))
|
||||
cfg.Section("server").Key("OFFLINE_MODE").SetValue(com.ToStr(f.OfflineMode))
|
||||
cfg.Section("picture").Key("DISABLE_GRAVATAR").SetValue(com.ToStr(f.DisableGravatar))
|
||||
cfg.Section("picture").Key("ENABLE_FEDERATED_AVATAR").SetValue(com.ToStr(f.EnableFederatedAvatar))
|
||||
cfg.Section("service").Key("DISABLE_REGISTRATION").SetValue(com.ToStr(f.DisableRegistration))
|
||||
cfg.Section("service").Key("ENABLE_CAPTCHA").SetValue(com.ToStr(f.EnableCaptcha))
|
||||
cfg.Section("service").Key("REQUIRE_SIGNIN_VIEW").SetValue(com.ToStr(f.RequireSignInView))
|
||||
|
||||
cfg.Section("").Key("RUN_MODE").SetValue("prod")
|
||||
|
||||
@@ -337,30 +337,30 @@ func InstallPost(ctx *context.Context, form auth.InstallForm) {
|
||||
|
||||
cfg.Section("log").Key("MODE").SetValue("file")
|
||||
cfg.Section("log").Key("LEVEL").SetValue("Info")
|
||||
cfg.Section("log").Key("ROOT_PATH").SetValue(form.LogRootPath)
|
||||
cfg.Section("log").Key("ROOT_PATH").SetValue(f.LogRootPath)
|
||||
|
||||
cfg.Section("security").Key("INSTALL_LOCK").SetValue("true")
|
||||
secretKey, err := base.GetRandomString(15)
|
||||
if err != nil {
|
||||
ctx.RenderWithErr(ctx.Tr("install.secret_key_failed", err), INSTALL, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("install.secret_key_failed", err), INSTALL, &f)
|
||||
return
|
||||
}
|
||||
cfg.Section("security").Key("SECRET_KEY").SetValue(secretKey)
|
||||
|
||||
os.MkdirAll(filepath.Dir(setting.CustomConf), os.ModePerm)
|
||||
if err := cfg.SaveTo(setting.CustomConf); err != nil {
|
||||
ctx.RenderWithErr(ctx.Tr("install.save_config_failed", err), INSTALL, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("install.save_config_failed", err), INSTALL, &f)
|
||||
return
|
||||
}
|
||||
|
||||
GlobalInit()
|
||||
|
||||
// Create admin account
|
||||
if len(form.AdminName) > 0 {
|
||||
if len(f.AdminName) > 0 {
|
||||
u := &models.User{
|
||||
Name: form.AdminName,
|
||||
Email: form.AdminEmail,
|
||||
Passwd: form.AdminPasswd,
|
||||
Name: f.AdminName,
|
||||
Email: f.AdminEmail,
|
||||
Passwd: f.AdminPasswd,
|
||||
IsAdmin: true,
|
||||
IsActive: true,
|
||||
}
|
||||
@@ -369,7 +369,7 @@ func InstallPost(ctx *context.Context, form auth.InstallForm) {
|
||||
setting.InstallLock = false
|
||||
ctx.Data["Err_AdminName"] = true
|
||||
ctx.Data["Err_AdminEmail"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("install.invalid_admin_setting", err), INSTALL, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("install.invalid_admin_setting", err), INSTALL, &f)
|
||||
return
|
||||
}
|
||||
log.Info("Admin account already exist")
|
||||
@@ -383,5 +383,5 @@ func InstallPost(ctx *context.Context, form auth.InstallForm) {
|
||||
|
||||
log.Info("First-time run install finished!")
|
||||
ctx.Flash.Success(ctx.Tr("install.install_success"))
|
||||
ctx.Redirect(form.AppUrl + "user/login")
|
||||
ctx.Redirect(f.AppUrl + "user/login")
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
log "gopkg.in/clog.v1"
|
||||
|
||||
"github.com/gogits/gogs/models"
|
||||
"github.com/gogits/gogs/modules/auth"
|
||||
"github.com/gogits/gogs/modules/form"
|
||||
"github.com/gogits/gogs/modules/base"
|
||||
"github.com/gogits/gogs/modules/context"
|
||||
"github.com/gogits/gogs/modules/setting"
|
||||
@@ -23,7 +23,7 @@ func Create(ctx *context.Context) {
|
||||
ctx.HTML(200, CREATE)
|
||||
}
|
||||
|
||||
func CreatePost(ctx *context.Context, form auth.CreateOrgForm) {
|
||||
func CreatePost(ctx *context.Context, f form.CreateOrg) {
|
||||
ctx.Data["Title"] = ctx.Tr("new_org")
|
||||
|
||||
if ctx.HasError() {
|
||||
@@ -32,7 +32,7 @@ func CreatePost(ctx *context.Context, form auth.CreateOrgForm) {
|
||||
}
|
||||
|
||||
org := &models.User{
|
||||
Name: form.OrgName,
|
||||
Name: f.OrgName,
|
||||
IsActive: true,
|
||||
Type: models.USER_TYPE_ORGANIZATION,
|
||||
}
|
||||
@@ -41,11 +41,11 @@ func CreatePost(ctx *context.Context, form auth.CreateOrgForm) {
|
||||
ctx.Data["Err_OrgName"] = true
|
||||
switch {
|
||||
case models.IsErrUserAlreadyExist(err):
|
||||
ctx.RenderWithErr(ctx.Tr("form.org_name_been_taken"), CREATE, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("form.org_name_been_taken"), CREATE, &f)
|
||||
case models.IsErrNameReserved(err):
|
||||
ctx.RenderWithErr(ctx.Tr("org.form.name_reserved", err.(models.ErrNameReserved).Name), CREATE, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("org.form.name_reserved", err.(models.ErrNameReserved).Name), CREATE, &f)
|
||||
case models.IsErrNamePatternNotAllowed(err):
|
||||
ctx.RenderWithErr(ctx.Tr("org.form.name_pattern_not_allowed", err.(models.ErrNamePatternNotAllowed).Pattern), CREATE, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("org.form.name_pattern_not_allowed", err.(models.ErrNamePatternNotAllowed).Pattern), CREATE, &f)
|
||||
default:
|
||||
ctx.Handle(500, "CreateOrganization", err)
|
||||
}
|
||||
@@ -53,5 +53,5 @@ func CreatePost(ctx *context.Context, form auth.CreateOrgForm) {
|
||||
}
|
||||
log.Trace("Organization created: %s", org.Name)
|
||||
|
||||
ctx.Redirect(setting.AppSubUrl + "/org/" + form.OrgName + "/dashboard")
|
||||
ctx.Redirect(setting.AppSubUrl + "/org/" + f.OrgName + "/dashboard")
|
||||
}
|
||||
|
||||
@@ -10,9 +10,9 @@ import (
|
||||
log "gopkg.in/clog.v1"
|
||||
|
||||
"github.com/gogits/gogs/models"
|
||||
"github.com/gogits/gogs/modules/auth"
|
||||
"github.com/gogits/gogs/modules/base"
|
||||
"github.com/gogits/gogs/modules/context"
|
||||
"github.com/gogits/gogs/modules/form"
|
||||
"github.com/gogits/gogs/modules/setting"
|
||||
"github.com/gogits/gogs/routers/user"
|
||||
)
|
||||
@@ -29,7 +29,7 @@ func Settings(ctx *context.Context) {
|
||||
ctx.HTML(200, SETTINGS_OPTIONS)
|
||||
}
|
||||
|
||||
func SettingsPost(ctx *context.Context, form auth.UpdateOrgSettingForm) {
|
||||
func SettingsPost(ctx *context.Context, f form.UpdateOrgSetting) {
|
||||
ctx.Data["Title"] = ctx.Tr("org.settings")
|
||||
ctx.Data["PageIsSettingsOptions"] = true
|
||||
|
||||
@@ -41,40 +41,40 @@ func SettingsPost(ctx *context.Context, form auth.UpdateOrgSettingForm) {
|
||||
org := ctx.Org.Organization
|
||||
|
||||
// Check if organization name has been changed.
|
||||
if org.LowerName != strings.ToLower(form.Name) {
|
||||
isExist, err := models.IsUserExist(org.ID, form.Name)
|
||||
if org.LowerName != strings.ToLower(f.Name) {
|
||||
isExist, err := models.IsUserExist(org.ID, f.Name)
|
||||
if err != nil {
|
||||
ctx.Handle(500, "IsUserExist", err)
|
||||
return
|
||||
} else if isExist {
|
||||
ctx.Data["OrgName"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("form.username_been_taken"), SETTINGS_OPTIONS, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("form.username_been_taken"), SETTINGS_OPTIONS, &f)
|
||||
return
|
||||
} else if err = models.ChangeUserName(org, form.Name); err != nil {
|
||||
} else if err = models.ChangeUserName(org, f.Name); err != nil {
|
||||
if err == models.ErrUserNameIllegal {
|
||||
ctx.Data["OrgName"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("form.illegal_username"), SETTINGS_OPTIONS, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("form.illegal_username"), SETTINGS_OPTIONS, &f)
|
||||
} else {
|
||||
ctx.Handle(500, "ChangeUserName", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
// reset ctx.org.OrgLink with new name
|
||||
ctx.Org.OrgLink = setting.AppSubUrl + "/org/" + form.Name
|
||||
log.Trace("Organization name changed: %s -> %s", org.Name, form.Name)
|
||||
ctx.Org.OrgLink = setting.AppSubUrl + "/org/" + f.Name
|
||||
log.Trace("Organization name changed: %s -> %s", org.Name, f.Name)
|
||||
}
|
||||
// In case it's just a case change.
|
||||
org.Name = form.Name
|
||||
org.LowerName = strings.ToLower(form.Name)
|
||||
org.Name = f.Name
|
||||
org.LowerName = strings.ToLower(f.Name)
|
||||
|
||||
if ctx.User.IsAdmin {
|
||||
org.MaxRepoCreation = form.MaxRepoCreation
|
||||
org.MaxRepoCreation = f.MaxRepoCreation
|
||||
}
|
||||
|
||||
org.FullName = form.FullName
|
||||
org.Description = form.Description
|
||||
org.Website = form.Website
|
||||
org.Location = form.Location
|
||||
org.FullName = f.FullName
|
||||
org.Description = f.Description
|
||||
org.Website = f.Website
|
||||
org.Location = f.Location
|
||||
if err := models.UpdateUser(org); err != nil {
|
||||
ctx.Handle(500, "UpdateUser", err)
|
||||
return
|
||||
@@ -84,9 +84,9 @@ func SettingsPost(ctx *context.Context, form auth.UpdateOrgSettingForm) {
|
||||
ctx.Redirect(ctx.Org.OrgLink + "/settings")
|
||||
}
|
||||
|
||||
func SettingsAvatar(ctx *context.Context, form auth.AvatarForm) {
|
||||
form.Source = auth.AVATAR_LOCAL
|
||||
if err := user.UpdateAvatarSetting(ctx, form, ctx.Org.Organization); err != nil {
|
||||
func SettingsAvatar(ctx *context.Context, f form.Avatar) {
|
||||
f.Source = form.AVATAR_LOCAL
|
||||
if err := user.UpdateAvatarSetting(ctx, f, ctx.Org.Organization); err != nil {
|
||||
ctx.Flash.Error(err.Error())
|
||||
} else {
|
||||
ctx.Flash.Success(ctx.Tr("org.settings.update_avatar_success"))
|
||||
|
||||
@@ -11,9 +11,9 @@ import (
|
||||
log "gopkg.in/clog.v1"
|
||||
|
||||
"github.com/gogits/gogs/models"
|
||||
"github.com/gogits/gogs/modules/auth"
|
||||
"github.com/gogits/gogs/modules/base"
|
||||
"github.com/gogits/gogs/modules/context"
|
||||
"github.com/gogits/gogs/modules/form"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -149,16 +149,16 @@ func NewTeam(ctx *context.Context) {
|
||||
ctx.HTML(200, TEAM_NEW)
|
||||
}
|
||||
|
||||
func NewTeamPost(ctx *context.Context, form auth.CreateTeamForm) {
|
||||
func NewTeamPost(ctx *context.Context, f form.CreateTeam) {
|
||||
ctx.Data["Title"] = ctx.Org.Organization.FullName
|
||||
ctx.Data["PageIsOrgTeams"] = true
|
||||
ctx.Data["PageIsOrgTeamsNew"] = true
|
||||
|
||||
t := &models.Team{
|
||||
OrgID: ctx.Org.Organization.ID,
|
||||
Name: form.TeamName,
|
||||
Description: form.Description,
|
||||
Authorize: models.ParseAccessMode(form.Permission),
|
||||
Name: f.TeamName,
|
||||
Description: f.Description,
|
||||
Authorize: models.ParseAccessMode(f.Permission),
|
||||
}
|
||||
ctx.Data["Team"] = t
|
||||
|
||||
@@ -171,9 +171,9 @@ func NewTeamPost(ctx *context.Context, form auth.CreateTeamForm) {
|
||||
ctx.Data["Err_TeamName"] = true
|
||||
switch {
|
||||
case models.IsErrTeamAlreadyExist(err):
|
||||
ctx.RenderWithErr(ctx.Tr("form.team_name_been_taken"), TEAM_NEW, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("form.team_name_been_taken"), TEAM_NEW, &f)
|
||||
case models.IsErrNameReserved(err):
|
||||
ctx.RenderWithErr(ctx.Tr("org.form.team_name_reserved", err.(models.ErrNameReserved).Name), TEAM_NEW, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("org.form.team_name_reserved", err.(models.ErrNameReserved).Name), TEAM_NEW, &f)
|
||||
default:
|
||||
ctx.Handle(500, "NewTeam", err)
|
||||
}
|
||||
@@ -211,7 +211,7 @@ func EditTeam(ctx *context.Context) {
|
||||
ctx.HTML(200, TEAM_NEW)
|
||||
}
|
||||
|
||||
func EditTeamPost(ctx *context.Context, form auth.CreateTeamForm) {
|
||||
func EditTeamPost(ctx *context.Context, f form.CreateTeam) {
|
||||
t := ctx.Org.Team
|
||||
ctx.Data["Title"] = ctx.Org.Organization.FullName
|
||||
ctx.Data["PageIsOrgTeams"] = true
|
||||
@@ -226,7 +226,7 @@ func EditTeamPost(ctx *context.Context, form auth.CreateTeamForm) {
|
||||
if !t.IsOwnerTeam() {
|
||||
// Validate permission level.
|
||||
var auth models.AccessMode
|
||||
switch form.Permission {
|
||||
switch f.Permission {
|
||||
case "read":
|
||||
auth = models.ACCESS_MODE_READ
|
||||
case "write":
|
||||
@@ -238,18 +238,18 @@ func EditTeamPost(ctx *context.Context, form auth.CreateTeamForm) {
|
||||
return
|
||||
}
|
||||
|
||||
t.Name = form.TeamName
|
||||
t.Name = f.TeamName
|
||||
if t.Authorize != auth {
|
||||
isAuthChanged = true
|
||||
t.Authorize = auth
|
||||
}
|
||||
}
|
||||
t.Description = form.Description
|
||||
t.Description = f.Description
|
||||
if err := models.UpdateTeam(t, isAuthChanged); err != nil {
|
||||
ctx.Data["Err_TeamName"] = true
|
||||
switch {
|
||||
case models.IsErrTeamAlreadyExist(err):
|
||||
ctx.RenderWithErr(ctx.Tr("form.team_name_been_taken"), TEAM_NEW, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("form.team_name_been_taken"), TEAM_NEW, &f)
|
||||
default:
|
||||
ctx.Handle(500, "UpdateTeam", err)
|
||||
}
|
||||
|
||||
@@ -15,9 +15,9 @@ import (
|
||||
|
||||
"github.com/gogits/git-module"
|
||||
"github.com/gogits/gogs/models"
|
||||
"github.com/gogits/gogs/modules/auth"
|
||||
"github.com/gogits/gogs/modules/base"
|
||||
"github.com/gogits/gogs/modules/context"
|
||||
"github.com/gogits/gogs/modules/form"
|
||||
"github.com/gogits/gogs/modules/setting"
|
||||
"github.com/gogits/gogs/modules/template"
|
||||
)
|
||||
@@ -123,7 +123,7 @@ func NewFile(ctx *context.Context) {
|
||||
editFile(ctx, true)
|
||||
}
|
||||
|
||||
func editFilePost(ctx *context.Context, form auth.EditRepoFileForm, isNewFile bool) {
|
||||
func editFilePost(ctx *context.Context, f form.EditRepoFile, isNewFile bool) {
|
||||
ctx.Data["PageIsEdit"] = true
|
||||
ctx.Data["IsNewFile"] = isNewFile
|
||||
ctx.Data["RequireHighlightJS"] = true
|
||||
@@ -132,26 +132,26 @@ func editFilePost(ctx *context.Context, form auth.EditRepoFileForm, isNewFile bo
|
||||
oldBranchName := ctx.Repo.BranchName
|
||||
branchName := oldBranchName
|
||||
oldTreePath := ctx.Repo.TreePath
|
||||
lastCommit := form.LastCommit
|
||||
form.LastCommit = ctx.Repo.Commit.ID.String()
|
||||
lastCommit := f.LastCommit
|
||||
f.LastCommit = ctx.Repo.Commit.ID.String()
|
||||
|
||||
if form.IsNewBrnach() {
|
||||
branchName = form.NewBranchName
|
||||
if f.IsNewBrnach() {
|
||||
branchName = f.NewBranchName
|
||||
}
|
||||
|
||||
form.TreePath = strings.Trim(form.TreePath, " /")
|
||||
treeNames, treePaths := getParentTreeFields(form.TreePath)
|
||||
f.TreePath = strings.Trim(f.TreePath, " /")
|
||||
treeNames, treePaths := getParentTreeFields(f.TreePath)
|
||||
|
||||
ctx.Data["TreePath"] = form.TreePath
|
||||
ctx.Data["TreePath"] = f.TreePath
|
||||
ctx.Data["TreeNames"] = treeNames
|
||||
ctx.Data["TreePaths"] = treePaths
|
||||
ctx.Data["BranchLink"] = ctx.Repo.RepoLink + "/src/" + branchName
|
||||
ctx.Data["FileContent"] = form.Content
|
||||
ctx.Data["commit_summary"] = form.CommitSummary
|
||||
ctx.Data["commit_message"] = form.CommitMessage
|
||||
ctx.Data["commit_choice"] = form.CommitChoice
|
||||
ctx.Data["FileContent"] = f.Content
|
||||
ctx.Data["commit_summary"] = f.CommitSummary
|
||||
ctx.Data["commit_message"] = f.CommitMessage
|
||||
ctx.Data["commit_choice"] = f.CommitChoice
|
||||
ctx.Data["new_branch_name"] = branchName
|
||||
ctx.Data["last_commit"] = form.LastCommit
|
||||
ctx.Data["last_commit"] = f.LastCommit
|
||||
ctx.Data["MarkdownFileExts"] = strings.Join(setting.Markdown.FileExtensions, ",")
|
||||
ctx.Data["LineWrapExtensions"] = strings.Join(setting.Repository.Editor.LineWrapExtensions, ",")
|
||||
ctx.Data["PreviewableFileModes"] = strings.Join(setting.Repository.Editor.PreviewableFileModes, ",")
|
||||
@@ -161,16 +161,16 @@ func editFilePost(ctx *context.Context, form auth.EditRepoFileForm, isNewFile bo
|
||||
return
|
||||
}
|
||||
|
||||
if len(form.TreePath) == 0 {
|
||||
if len(f.TreePath) == 0 {
|
||||
ctx.Data["Err_TreePath"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("repo.editor.filename_cannot_be_empty"), EDIT_FILE, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("repo.editor.filename_cannot_be_empty"), EDIT_FILE, &f)
|
||||
return
|
||||
}
|
||||
|
||||
if oldBranchName != branchName {
|
||||
if _, err := ctx.Repo.Repository.GetBranch(branchName); err == nil {
|
||||
ctx.Data["Err_NewBranchName"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("repo.editor.branch_already_exists", branchName), EDIT_FILE, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("repo.editor.branch_already_exists", branchName), EDIT_FILE, &f)
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -191,17 +191,17 @@ func editFilePost(ctx *context.Context, form auth.EditRepoFileForm, isNewFile bo
|
||||
if index != len(treeNames)-1 {
|
||||
if !entry.IsDir() {
|
||||
ctx.Data["Err_TreePath"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("repo.editor.directory_is_a_file", part), EDIT_FILE, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("repo.editor.directory_is_a_file", part), EDIT_FILE, &f)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
if entry.IsLink() {
|
||||
ctx.Data["Err_TreePath"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("repo.editor.file_is_a_symlink", part), EDIT_FILE, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("repo.editor.file_is_a_symlink", part), EDIT_FILE, &f)
|
||||
return
|
||||
} else if entry.IsDir() {
|
||||
ctx.Data["Err_TreePath"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("repo.editor.filename_is_a_directory", part), EDIT_FILE, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("repo.editor.filename_is_a_directory", part), EDIT_FILE, &f)
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -212,7 +212,7 @@ func editFilePost(ctx *context.Context, form auth.EditRepoFileForm, isNewFile bo
|
||||
if err != nil {
|
||||
if git.IsErrNotExist(err) {
|
||||
ctx.Data["Err_TreePath"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("repo.editor.file_editing_no_longer_exists", oldTreePath), EDIT_FILE, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("repo.editor.file_editing_no_longer_exists", oldTreePath), EDIT_FILE, &f)
|
||||
} else {
|
||||
ctx.Handle(500, "GetTreeEntryByPath", err)
|
||||
}
|
||||
@@ -226,17 +226,17 @@ func editFilePost(ctx *context.Context, form auth.EditRepoFileForm, isNewFile bo
|
||||
}
|
||||
|
||||
for _, file := range files {
|
||||
if file == form.TreePath {
|
||||
ctx.RenderWithErr(ctx.Tr("repo.editor.file_changed_while_editing", ctx.Repo.RepoLink+"/compare/"+lastCommit+"..."+ctx.Repo.CommitID), EDIT_FILE, &form)
|
||||
if file == f.TreePath {
|
||||
ctx.RenderWithErr(ctx.Tr("repo.editor.file_changed_while_editing", ctx.Repo.RepoLink+"/compare/"+lastCommit+"..."+ctx.Repo.CommitID), EDIT_FILE, &f)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if oldTreePath != form.TreePath {
|
||||
if oldTreePath != f.TreePath {
|
||||
// We have a new filename (rename or completely new file) so we need to make sure it doesn't already exist, can't clobber.
|
||||
entry, err := ctx.Repo.Commit.GetTreeEntryByPath(form.TreePath)
|
||||
entry, err := ctx.Repo.Commit.GetTreeEntryByPath(f.TreePath)
|
||||
if err != nil {
|
||||
if !git.IsErrNotExist(err) {
|
||||
ctx.Handle(500, "GetTreeEntryByPath", err)
|
||||
@@ -245,23 +245,23 @@ func editFilePost(ctx *context.Context, form auth.EditRepoFileForm, isNewFile bo
|
||||
}
|
||||
if entry != nil {
|
||||
ctx.Data["Err_TreePath"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("repo.editor.file_already_exists", form.TreePath), EDIT_FILE, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("repo.editor.file_already_exists", f.TreePath), EDIT_FILE, &f)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
message := strings.TrimSpace(form.CommitSummary)
|
||||
message := strings.TrimSpace(f.CommitSummary)
|
||||
if len(message) == 0 {
|
||||
if isNewFile {
|
||||
message = ctx.Tr("repo.editor.add", form.TreePath)
|
||||
message = ctx.Tr("repo.editor.add", f.TreePath)
|
||||
} else {
|
||||
message = ctx.Tr("repo.editor.update", form.TreePath)
|
||||
message = ctx.Tr("repo.editor.update", f.TreePath)
|
||||
}
|
||||
}
|
||||
|
||||
form.CommitMessage = strings.TrimSpace(form.CommitMessage)
|
||||
if len(form.CommitMessage) > 0 {
|
||||
message += "\n\n" + form.CommitMessage
|
||||
f.CommitMessage = strings.TrimSpace(f.CommitMessage)
|
||||
if len(f.CommitMessage) > 0 {
|
||||
message += "\n\n" + f.CommitMessage
|
||||
}
|
||||
|
||||
if err := ctx.Repo.Repository.UpdateRepoFile(ctx.User, models.UpdateRepoFileOptions{
|
||||
@@ -269,32 +269,32 @@ func editFilePost(ctx *context.Context, form auth.EditRepoFileForm, isNewFile bo
|
||||
OldBranch: oldBranchName,
|
||||
NewBranch: branchName,
|
||||
OldTreeName: oldTreePath,
|
||||
NewTreeName: form.TreePath,
|
||||
NewTreeName: f.TreePath,
|
||||
Message: message,
|
||||
Content: strings.Replace(form.Content, "\r", "", -1),
|
||||
Content: strings.Replace(f.Content, "\r", "", -1),
|
||||
IsNewFile: isNewFile,
|
||||
}); err != nil {
|
||||
ctx.Data["Err_TreePath"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("repo.editor.fail_to_update_file", form.TreePath, err), EDIT_FILE, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("repo.editor.fail_to_update_file", f.TreePath, err), EDIT_FILE, &f)
|
||||
return
|
||||
}
|
||||
|
||||
if form.IsNewBrnach() && ctx.Repo.PullRequest.Allowed {
|
||||
ctx.Redirect(ctx.Repo.PullRequestURL(oldBranchName, form.NewBranchName))
|
||||
if f.IsNewBrnach() && ctx.Repo.PullRequest.Allowed {
|
||||
ctx.Redirect(ctx.Repo.PullRequestURL(oldBranchName, f.NewBranchName))
|
||||
} else {
|
||||
ctx.Redirect(ctx.Repo.RepoLink + "/src/" + branchName + "/" + template.EscapePound(form.TreePath))
|
||||
ctx.Redirect(ctx.Repo.RepoLink + "/src/" + branchName + "/" + template.EscapePound(f.TreePath))
|
||||
}
|
||||
}
|
||||
|
||||
func EditFilePost(ctx *context.Context, form auth.EditRepoFileForm) {
|
||||
editFilePost(ctx, form, false)
|
||||
func EditFilePost(ctx *context.Context, f form.EditRepoFile) {
|
||||
editFilePost(ctx, f, false)
|
||||
}
|
||||
|
||||
func NewFilePost(ctx *context.Context, form auth.EditRepoFileForm) {
|
||||
editFilePost(ctx, form, true)
|
||||
func NewFilePost(ctx *context.Context, f form.EditRepoFile) {
|
||||
editFilePost(ctx, f, true)
|
||||
}
|
||||
|
||||
func DiffPreviewPost(ctx *context.Context, form auth.EditPreviewDiffForm) {
|
||||
func DiffPreviewPost(ctx *context.Context, f form.EditPreviewDiff) {
|
||||
treePath := ctx.Repo.TreePath
|
||||
|
||||
entry, err := ctx.Repo.Commit.GetTreeEntryByPath(treePath)
|
||||
@@ -306,7 +306,7 @@ func DiffPreviewPost(ctx *context.Context, form auth.EditPreviewDiffForm) {
|
||||
return
|
||||
}
|
||||
|
||||
diff, err := ctx.Repo.Repository.GetDiffPreview(ctx.Repo.BranchName, treePath, form.Content)
|
||||
diff, err := ctx.Repo.Repository.GetDiffPreview(ctx.Repo.BranchName, treePath, f.Content)
|
||||
if err != nil {
|
||||
ctx.Error(500, "GetDiffPreview: "+err.Error())
|
||||
return
|
||||
@@ -332,7 +332,7 @@ func DeleteFile(ctx *context.Context) {
|
||||
ctx.HTML(200, DELETE_FILE)
|
||||
}
|
||||
|
||||
func DeleteFilePost(ctx *context.Context, form auth.DeleteRepoFileForm) {
|
||||
func DeleteFilePost(ctx *context.Context, f form.DeleteRepoFile) {
|
||||
ctx.Data["PageIsDelete"] = true
|
||||
ctx.Data["BranchLink"] = ctx.Repo.RepoLink + "/src/" + ctx.Repo.BranchName
|
||||
ctx.Data["TreePath"] = ctx.Repo.TreePath
|
||||
@@ -340,12 +340,12 @@ func DeleteFilePost(ctx *context.Context, form auth.DeleteRepoFileForm) {
|
||||
oldBranchName := ctx.Repo.BranchName
|
||||
branchName := oldBranchName
|
||||
|
||||
if form.IsNewBrnach() {
|
||||
branchName = form.NewBranchName
|
||||
if f.IsNewBrnach() {
|
||||
branchName = f.NewBranchName
|
||||
}
|
||||
ctx.Data["commit_summary"] = form.CommitSummary
|
||||
ctx.Data["commit_message"] = form.CommitMessage
|
||||
ctx.Data["commit_choice"] = form.CommitChoice
|
||||
ctx.Data["commit_summary"] = f.CommitSummary
|
||||
ctx.Data["commit_message"] = f.CommitMessage
|
||||
ctx.Data["commit_choice"] = f.CommitChoice
|
||||
ctx.Data["new_branch_name"] = branchName
|
||||
|
||||
if ctx.HasError() {
|
||||
@@ -356,19 +356,19 @@ func DeleteFilePost(ctx *context.Context, form auth.DeleteRepoFileForm) {
|
||||
if oldBranchName != branchName {
|
||||
if _, err := ctx.Repo.Repository.GetBranch(branchName); err == nil {
|
||||
ctx.Data["Err_NewBranchName"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("repo.editor.branch_already_exists", branchName), DELETE_FILE, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("repo.editor.branch_already_exists", branchName), DELETE_FILE, &f)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
message := strings.TrimSpace(form.CommitSummary)
|
||||
message := strings.TrimSpace(f.CommitSummary)
|
||||
if len(message) == 0 {
|
||||
message = ctx.Tr("repo.editor.delete", ctx.Repo.TreePath)
|
||||
}
|
||||
|
||||
form.CommitMessage = strings.TrimSpace(form.CommitMessage)
|
||||
if len(form.CommitMessage) > 0 {
|
||||
message += "\n\n" + form.CommitMessage
|
||||
f.CommitMessage = strings.TrimSpace(f.CommitMessage)
|
||||
if len(f.CommitMessage) > 0 {
|
||||
message += "\n\n" + f.CommitMessage
|
||||
}
|
||||
|
||||
if err := ctx.Repo.Repository.DeleteRepoFile(ctx.User, models.DeleteRepoFileOptions{
|
||||
@@ -382,8 +382,8 @@ func DeleteFilePost(ctx *context.Context, form auth.DeleteRepoFileForm) {
|
||||
return
|
||||
}
|
||||
|
||||
if form.IsNewBrnach() && ctx.Repo.PullRequest.Allowed {
|
||||
ctx.Redirect(ctx.Repo.PullRequestURL(oldBranchName, form.NewBranchName))
|
||||
if f.IsNewBrnach() && ctx.Repo.PullRequest.Allowed {
|
||||
ctx.Redirect(ctx.Repo.PullRequestURL(oldBranchName, f.NewBranchName))
|
||||
} else {
|
||||
ctx.Flash.Success(ctx.Tr("repo.editor.file_delete_success", ctx.Repo.TreePath))
|
||||
ctx.Redirect(ctx.Repo.RepoLink + "/src/" + branchName)
|
||||
@@ -418,31 +418,31 @@ func UploadFile(ctx *context.Context) {
|
||||
ctx.HTML(200, UPLOAD_FILE)
|
||||
}
|
||||
|
||||
func UploadFilePost(ctx *context.Context, form auth.UploadRepoFileForm) {
|
||||
func UploadFilePost(ctx *context.Context, f form.UploadRepoFile) {
|
||||
ctx.Data["PageIsUpload"] = true
|
||||
renderUploadSettings(ctx)
|
||||
|
||||
oldBranchName := ctx.Repo.BranchName
|
||||
branchName := oldBranchName
|
||||
|
||||
if form.IsNewBrnach() {
|
||||
branchName = form.NewBranchName
|
||||
if f.IsNewBrnach() {
|
||||
branchName = f.NewBranchName
|
||||
}
|
||||
|
||||
form.TreePath = strings.Trim(form.TreePath, " /")
|
||||
treeNames, treePaths := getParentTreeFields(form.TreePath)
|
||||
f.TreePath = strings.Trim(f.TreePath, " /")
|
||||
treeNames, treePaths := getParentTreeFields(f.TreePath)
|
||||
if len(treeNames) == 0 {
|
||||
// We must at least have one element for user to input.
|
||||
treeNames = []string{""}
|
||||
}
|
||||
|
||||
ctx.Data["TreePath"] = form.TreePath
|
||||
ctx.Data["TreePath"] = f.TreePath
|
||||
ctx.Data["TreeNames"] = treeNames
|
||||
ctx.Data["TreePaths"] = treePaths
|
||||
ctx.Data["BranchLink"] = ctx.Repo.RepoLink + "/src/" + branchName
|
||||
ctx.Data["commit_summary"] = form.CommitSummary
|
||||
ctx.Data["commit_message"] = form.CommitMessage
|
||||
ctx.Data["commit_choice"] = form.CommitChoice
|
||||
ctx.Data["commit_summary"] = f.CommitSummary
|
||||
ctx.Data["commit_message"] = f.CommitMessage
|
||||
ctx.Data["commit_choice"] = f.CommitChoice
|
||||
ctx.Data["new_branch_name"] = branchName
|
||||
|
||||
if ctx.HasError() {
|
||||
@@ -453,7 +453,7 @@ func UploadFilePost(ctx *context.Context, form auth.UploadRepoFileForm) {
|
||||
if oldBranchName != branchName {
|
||||
if _, err := ctx.Repo.Repository.GetBranch(branchName); err == nil {
|
||||
ctx.Data["Err_NewBranchName"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("repo.editor.branch_already_exists", branchName), UPLOAD_FILE, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("repo.editor.branch_already_exists", branchName), UPLOAD_FILE, &f)
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -475,38 +475,38 @@ func UploadFilePost(ctx *context.Context, form auth.UploadRepoFileForm) {
|
||||
// User can only upload files to a directory.
|
||||
if !entry.IsDir() {
|
||||
ctx.Data["Err_TreePath"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("repo.editor.directory_is_a_file", part), UPLOAD_FILE, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("repo.editor.directory_is_a_file", part), UPLOAD_FILE, &f)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
message := strings.TrimSpace(form.CommitSummary)
|
||||
message := strings.TrimSpace(f.CommitSummary)
|
||||
if len(message) == 0 {
|
||||
message = ctx.Tr("repo.editor.upload_files_to_dir", form.TreePath)
|
||||
message = ctx.Tr("repo.editor.upload_files_to_dir", f.TreePath)
|
||||
}
|
||||
|
||||
form.CommitMessage = strings.TrimSpace(form.CommitMessage)
|
||||
if len(form.CommitMessage) > 0 {
|
||||
message += "\n\n" + form.CommitMessage
|
||||
f.CommitMessage = strings.TrimSpace(f.CommitMessage)
|
||||
if len(f.CommitMessage) > 0 {
|
||||
message += "\n\n" + f.CommitMessage
|
||||
}
|
||||
|
||||
if err := ctx.Repo.Repository.UploadRepoFiles(ctx.User, models.UploadRepoFileOptions{
|
||||
LastCommitID: ctx.Repo.CommitID,
|
||||
OldBranch: oldBranchName,
|
||||
NewBranch: branchName,
|
||||
TreePath: form.TreePath,
|
||||
TreePath: f.TreePath,
|
||||
Message: message,
|
||||
Files: form.Files,
|
||||
Files: f.Files,
|
||||
}); err != nil {
|
||||
ctx.Data["Err_TreePath"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("repo.editor.unable_to_upload_files", form.TreePath, err), UPLOAD_FILE, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("repo.editor.unable_to_upload_files", f.TreePath, err), UPLOAD_FILE, &f)
|
||||
return
|
||||
}
|
||||
|
||||
if form.IsNewBrnach() && ctx.Repo.PullRequest.Allowed {
|
||||
ctx.Redirect(ctx.Repo.PullRequestURL(oldBranchName, form.NewBranchName))
|
||||
if f.IsNewBrnach() && ctx.Repo.PullRequest.Allowed {
|
||||
ctx.Redirect(ctx.Repo.PullRequestURL(oldBranchName, f.NewBranchName))
|
||||
} else {
|
||||
ctx.Redirect(ctx.Repo.RepoLink + "/src/" + branchName + "/" + form.TreePath)
|
||||
ctx.Redirect(ctx.Repo.RepoLink + "/src/" + branchName + "/" + f.TreePath)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -553,17 +553,17 @@ func UploadFileToServer(ctx *context.Context) {
|
||||
})
|
||||
}
|
||||
|
||||
func RemoveUploadFileFromServer(ctx *context.Context, form auth.RemoveUploadFileForm) {
|
||||
if len(form.File) == 0 {
|
||||
func RemoveUploadFileFromServer(ctx *context.Context, f form.RemoveUploadFile) {
|
||||
if len(f.File) == 0 {
|
||||
ctx.Status(204)
|
||||
return
|
||||
}
|
||||
|
||||
if err := models.DeleteUploadByUUID(form.File); err != nil {
|
||||
if err := models.DeleteUploadByUUID(f.File); err != nil {
|
||||
ctx.Error(500, fmt.Sprintf("DeleteUploadByUUID: %v", err))
|
||||
return
|
||||
}
|
||||
|
||||
log.Trace("Upload file removed: %s", form.File)
|
||||
log.Trace("Upload file removed: %s", f.File)
|
||||
ctx.Status(204)
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ import (
|
||||
const (
|
||||
ENV_AUTH_USER_ID = "GOGS_AUTH_USER_ID"
|
||||
ENV_AUTH_USER_NAME = "GOGS_AUTH_USER_NAME"
|
||||
ENV_AUTH_USER_EMAIL = "GOGS_AUTH_USER_EMAIL"
|
||||
ENV_REPO_OWNER_NAME = "GOGS_REPO_OWNER_NAME"
|
||||
ENV_REPO_OWNER_SALT_MD5 = "GOGS_REPO_OWNER_SALT_MD5"
|
||||
ENV_REPO_ID = "GOGS_REPO_ID"
|
||||
@@ -76,6 +77,16 @@ func HTTPContexter() macaron.Handler {
|
||||
return
|
||||
}
|
||||
|
||||
// In case user requested a wrong URL and not intended to access Git objects.
|
||||
action := ctx.Params("*")
|
||||
if !strings.Contains(action, "git-") &&
|
||||
!strings.Contains(action, "info/") &&
|
||||
!strings.Contains(action, "HEAD") &&
|
||||
!strings.Contains(action, "objects/") {
|
||||
ctx.NotFound()
|
||||
return
|
||||
}
|
||||
|
||||
// Handle HTTP Basic Authentication
|
||||
authHead := ctx.Req.Header.Get("Authorization")
|
||||
if len(authHead) == 0 {
|
||||
@@ -207,6 +218,7 @@ func ComposeHookEnvs(opts ComposeHookEnvsOptions) []string {
|
||||
"SSH_ORIGINAL_COMMAND=1",
|
||||
ENV_AUTH_USER_ID + "=" + com.ToStr(opts.AuthUser.ID),
|
||||
ENV_AUTH_USER_NAME + "=" + opts.AuthUser.Name,
|
||||
ENV_AUTH_USER_EMAIL + "=" + opts.AuthUser.Email,
|
||||
ENV_REPO_OWNER_NAME + "=" + opts.OwnerName,
|
||||
ENV_REPO_OWNER_SALT_MD5 + "=" + base.EncodeMD5(opts.OwnerSalt),
|
||||
ENV_REPO_ID + "=" + com.ToStr(opts.RepoID),
|
||||
|
||||
@@ -19,9 +19,9 @@ import (
|
||||
log "gopkg.in/clog.v1"
|
||||
|
||||
"github.com/gogits/gogs/models"
|
||||
"github.com/gogits/gogs/modules/auth"
|
||||
"github.com/gogits/gogs/modules/base"
|
||||
"github.com/gogits/gogs/modules/context"
|
||||
"github.com/gogits/gogs/modules/form"
|
||||
"github.com/gogits/gogs/modules/markdown"
|
||||
"github.com/gogits/gogs/modules/setting"
|
||||
)
|
||||
@@ -348,7 +348,7 @@ func NewIssue(ctx *context.Context) {
|
||||
ctx.HTML(200, ISSUE_NEW)
|
||||
}
|
||||
|
||||
func ValidateRepoMetas(ctx *context.Context, form auth.CreateIssueForm) ([]int64, int64, int64) {
|
||||
func ValidateRepoMetas(ctx *context.Context, f form.CreateIssue) ([]int64, int64, int64) {
|
||||
var (
|
||||
repo = ctx.Repo.Repository
|
||||
err error
|
||||
@@ -364,7 +364,7 @@ func ValidateRepoMetas(ctx *context.Context, form auth.CreateIssueForm) ([]int64
|
||||
}
|
||||
|
||||
// Check labels.
|
||||
labelIDs := base.StringsToInt64s(strings.Split(form.LabelIDs, ","))
|
||||
labelIDs := base.StringsToInt64s(strings.Split(f.LabelIDs, ","))
|
||||
labelIDMark := base.Int64sToMap(labelIDs)
|
||||
hasSelected := false
|
||||
for i := range labels {
|
||||
@@ -374,11 +374,11 @@ func ValidateRepoMetas(ctx *context.Context, form auth.CreateIssueForm) ([]int64
|
||||
}
|
||||
}
|
||||
ctx.Data["HasSelectedLabel"] = hasSelected
|
||||
ctx.Data["label_ids"] = form.LabelIDs
|
||||
ctx.Data["label_ids"] = f.LabelIDs
|
||||
ctx.Data["Labels"] = labels
|
||||
|
||||
// Check milestone.
|
||||
milestoneID := form.MilestoneID
|
||||
milestoneID := f.MilestoneID
|
||||
if milestoneID > 0 {
|
||||
ctx.Data["Milestone"], err = repo.GetMilestoneByID(milestoneID)
|
||||
if err != nil {
|
||||
@@ -389,7 +389,7 @@ func ValidateRepoMetas(ctx *context.Context, form auth.CreateIssueForm) ([]int64
|
||||
}
|
||||
|
||||
// Check assignee.
|
||||
assigneeID := form.AssigneeID
|
||||
assigneeID := f.AssigneeID
|
||||
if assigneeID > 0 {
|
||||
ctx.Data["Assignee"], err = repo.GetAssigneeByID(assigneeID)
|
||||
if err != nil {
|
||||
@@ -402,7 +402,7 @@ func ValidateRepoMetas(ctx *context.Context, form auth.CreateIssueForm) ([]int64
|
||||
return labelIDs, milestoneID, assigneeID
|
||||
}
|
||||
|
||||
func NewIssuePost(ctx *context.Context, form auth.CreateIssueForm) {
|
||||
func NewIssuePost(ctx *context.Context, f form.CreateIssue) {
|
||||
ctx.Data["Title"] = ctx.Tr("repo.issues.new")
|
||||
ctx.Data["PageIsIssueList"] = true
|
||||
ctx.Data["RequireHighlightJS"] = true
|
||||
@@ -414,13 +414,13 @@ func NewIssuePost(ctx *context.Context, form auth.CreateIssueForm) {
|
||||
attachments []string
|
||||
)
|
||||
|
||||
labelIDs, milestoneID, assigneeID := ValidateRepoMetas(ctx, form)
|
||||
labelIDs, milestoneID, assigneeID := ValidateRepoMetas(ctx, f)
|
||||
if ctx.Written() {
|
||||
return
|
||||
}
|
||||
|
||||
if setting.AttachmentEnabled {
|
||||
attachments = form.Files
|
||||
attachments = f.Files
|
||||
}
|
||||
|
||||
if ctx.HasError() {
|
||||
@@ -430,12 +430,12 @@ func NewIssuePost(ctx *context.Context, form auth.CreateIssueForm) {
|
||||
|
||||
issue := &models.Issue{
|
||||
RepoID: repo.ID,
|
||||
Title: form.Title,
|
||||
Title: f.Title,
|
||||
PosterID: ctx.User.ID,
|
||||
Poster: ctx.User,
|
||||
MilestoneID: milestoneID,
|
||||
AssigneeID: assigneeID,
|
||||
Content: form.Content,
|
||||
Content: f.Content,
|
||||
}
|
||||
if err := models.NewIssue(repo, issue, labelIDs, attachments); err != nil {
|
||||
ctx.Handle(500, "NewIssue", err)
|
||||
@@ -805,7 +805,7 @@ func UpdateIssueAssignee(ctx *context.Context) {
|
||||
})
|
||||
}
|
||||
|
||||
func NewComment(ctx *context.Context, form auth.CreateCommentForm) {
|
||||
func NewComment(ctx *context.Context, f form.CreateComment) {
|
||||
issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index"))
|
||||
if err != nil {
|
||||
ctx.NotFoundOrServerError("GetIssueByIndex", models.IsErrIssueNotExist, err)
|
||||
@@ -814,7 +814,7 @@ func NewComment(ctx *context.Context, form auth.CreateCommentForm) {
|
||||
|
||||
var attachments []string
|
||||
if setting.AttachmentEnabled {
|
||||
attachments = form.Files
|
||||
attachments = f.Files
|
||||
}
|
||||
|
||||
if ctx.HasError() {
|
||||
@@ -827,13 +827,13 @@ func NewComment(ctx *context.Context, form auth.CreateCommentForm) {
|
||||
defer func() {
|
||||
// Check if issue admin/poster changes the status of issue.
|
||||
if (ctx.Repo.IsWriter() || (ctx.IsSigned && issue.IsPoster(ctx.User.ID))) &&
|
||||
(form.Status == "reopen" || form.Status == "close") &&
|
||||
(f.Status == "reopen" || f.Status == "close") &&
|
||||
!(issue.IsPull && issue.PullRequest.HasMerged) {
|
||||
|
||||
// Duplication and conflict check should apply to reopen pull request.
|
||||
var pr *models.PullRequest
|
||||
|
||||
if form.Status == "reopen" && issue.IsPull {
|
||||
if f.Status == "reopen" && issue.IsPull {
|
||||
pull := issue.PullRequest
|
||||
pr, err = models.GetUnmergedPullRequest(pull.HeadRepoID, pull.BaseRepoID, pull.HeadBranch, pull.BaseBranch)
|
||||
if err != nil {
|
||||
@@ -857,7 +857,7 @@ func NewComment(ctx *context.Context, form auth.CreateCommentForm) {
|
||||
if pr != nil {
|
||||
ctx.Flash.Info(ctx.Tr("repo.pulls.open_unmerged_pull_exists", pr.Index))
|
||||
} else {
|
||||
if err = issue.ChangeStatus(ctx.User, ctx.Repo.Repository, form.Status == "close"); err != nil {
|
||||
if err = issue.ChangeStatus(ctx.User, ctx.Repo.Repository, f.Status == "close"); err != nil {
|
||||
log.Error(4, "ChangeStatus: %v", err)
|
||||
} else {
|
||||
log.Trace("Issue [%d] status changed to closed: %v", issue.ID, issue.IsClosed)
|
||||
@@ -878,11 +878,11 @@ func NewComment(ctx *context.Context, form auth.CreateCommentForm) {
|
||||
}()
|
||||
|
||||
// Fix #321: Allow empty comments, as long as we have attachments.
|
||||
if len(form.Content) == 0 && len(attachments) == 0 {
|
||||
if len(f.Content) == 0 && len(attachments) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
comment, err = models.CreateIssueComment(ctx.User, ctx.Repo.Repository, issue, form.Content, attachments)
|
||||
comment, err = models.CreateIssueComment(ctx.User, ctx.Repo.Repository, issue, f.Content, attachments)
|
||||
if err != nil {
|
||||
ctx.Handle(500, "CreateIssueComment", err)
|
||||
return
|
||||
@@ -955,14 +955,14 @@ func Labels(ctx *context.Context) {
|
||||
ctx.HTML(200, LABELS)
|
||||
}
|
||||
|
||||
func InitializeLabels(ctx *context.Context, form auth.InitializeLabelsForm) {
|
||||
func InitializeLabels(ctx *context.Context, f form.InitializeLabels) {
|
||||
if ctx.HasError() {
|
||||
ctx.Redirect(ctx.Repo.RepoLink + "/labels")
|
||||
return
|
||||
}
|
||||
list, err := models.GetLabelTemplateFile(form.TemplateName)
|
||||
list, err := models.GetLabelTemplateFile(f.TemplateName)
|
||||
if err != nil {
|
||||
ctx.Flash.Error(ctx.Tr("repo.issues.label_templates.fail_to_load_file", form.TemplateName, err))
|
||||
ctx.Flash.Error(ctx.Tr("repo.issues.label_templates.fail_to_load_file", f.TemplateName, err))
|
||||
ctx.Redirect(ctx.Repo.RepoLink + "/labels")
|
||||
return
|
||||
}
|
||||
@@ -982,7 +982,7 @@ func InitializeLabels(ctx *context.Context, form auth.InitializeLabelsForm) {
|
||||
ctx.Redirect(ctx.Repo.RepoLink + "/labels")
|
||||
}
|
||||
|
||||
func NewLabel(ctx *context.Context, form auth.CreateLabelForm) {
|
||||
func NewLabel(ctx *context.Context, f form.CreateLabel) {
|
||||
ctx.Data["Title"] = ctx.Tr("repo.labels")
|
||||
ctx.Data["PageIsLabels"] = true
|
||||
|
||||
@@ -994,8 +994,8 @@ func NewLabel(ctx *context.Context, form auth.CreateLabelForm) {
|
||||
|
||||
l := &models.Label{
|
||||
RepoID: ctx.Repo.Repository.ID,
|
||||
Name: form.Title,
|
||||
Color: form.Color,
|
||||
Name: f.Title,
|
||||
Color: f.Color,
|
||||
}
|
||||
if err := models.NewLabels(l); err != nil {
|
||||
ctx.Handle(500, "NewLabel", err)
|
||||
@@ -1004,8 +1004,8 @@ func NewLabel(ctx *context.Context, form auth.CreateLabelForm) {
|
||||
ctx.Redirect(ctx.Repo.RepoLink + "/labels")
|
||||
}
|
||||
|
||||
func UpdateLabel(ctx *context.Context, form auth.CreateLabelForm) {
|
||||
l, err := models.GetLabelByID(form.ID)
|
||||
func UpdateLabel(ctx *context.Context, f form.CreateLabel) {
|
||||
l, err := models.GetLabelByID(f.ID)
|
||||
if err != nil {
|
||||
switch {
|
||||
case models.IsErrLabelNotExist(err):
|
||||
@@ -1016,8 +1016,8 @@ func UpdateLabel(ctx *context.Context, form auth.CreateLabelForm) {
|
||||
return
|
||||
}
|
||||
|
||||
l.Name = form.Title
|
||||
l.Color = form.Color
|
||||
l.Name = f.Title
|
||||
l.Color = f.Color
|
||||
if err := models.UpdateLabel(l); err != nil {
|
||||
ctx.Handle(500, "UpdateLabel", err)
|
||||
return
|
||||
@@ -1090,7 +1090,7 @@ func NewMilestone(ctx *context.Context) {
|
||||
ctx.HTML(200, MILESTONE_NEW)
|
||||
}
|
||||
|
||||
func NewMilestonePost(ctx *context.Context, form auth.CreateMilestoneForm) {
|
||||
func NewMilestonePost(ctx *context.Context, f form.CreateMilestone) {
|
||||
ctx.Data["Title"] = ctx.Tr("repo.milestones.new")
|
||||
ctx.Data["PageIsIssueList"] = true
|
||||
ctx.Data["PageIsMilestones"] = true
|
||||
@@ -1102,27 +1102,27 @@ func NewMilestonePost(ctx *context.Context, form auth.CreateMilestoneForm) {
|
||||
return
|
||||
}
|
||||
|
||||
if len(form.Deadline) == 0 {
|
||||
form.Deadline = "9999-12-31"
|
||||
if len(f.Deadline) == 0 {
|
||||
f.Deadline = "9999-12-31"
|
||||
}
|
||||
deadline, err := time.ParseInLocation("2006-01-02", form.Deadline, time.Local)
|
||||
deadline, err := time.ParseInLocation("2006-01-02", f.Deadline, time.Local)
|
||||
if err != nil {
|
||||
ctx.Data["Err_Deadline"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("repo.milestones.invalid_due_date_format"), MILESTONE_NEW, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("repo.milestones.invalid_due_date_format"), MILESTONE_NEW, &f)
|
||||
return
|
||||
}
|
||||
|
||||
if err = models.NewMilestone(&models.Milestone{
|
||||
RepoID: ctx.Repo.Repository.ID,
|
||||
Name: form.Title,
|
||||
Content: form.Content,
|
||||
Name: f.Title,
|
||||
Content: f.Content,
|
||||
Deadline: deadline,
|
||||
}); err != nil {
|
||||
ctx.Handle(500, "NewMilestone", err)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Flash.Success(ctx.Tr("repo.milestones.create_success", form.Title))
|
||||
ctx.Flash.Success(ctx.Tr("repo.milestones.create_success", f.Title))
|
||||
ctx.Redirect(ctx.Repo.RepoLink + "/milestones")
|
||||
}
|
||||
|
||||
@@ -1150,7 +1150,7 @@ func EditMilestone(ctx *context.Context) {
|
||||
ctx.HTML(200, MILESTONE_NEW)
|
||||
}
|
||||
|
||||
func EditMilestonePost(ctx *context.Context, form auth.CreateMilestoneForm) {
|
||||
func EditMilestonePost(ctx *context.Context, f form.CreateMilestone) {
|
||||
ctx.Data["Title"] = ctx.Tr("repo.milestones.edit")
|
||||
ctx.Data["PageIsMilestones"] = true
|
||||
ctx.Data["PageIsEditMilestone"] = true
|
||||
@@ -1162,13 +1162,13 @@ func EditMilestonePost(ctx *context.Context, form auth.CreateMilestoneForm) {
|
||||
return
|
||||
}
|
||||
|
||||
if len(form.Deadline) == 0 {
|
||||
form.Deadline = "9999-12-31"
|
||||
if len(f.Deadline) == 0 {
|
||||
f.Deadline = "9999-12-31"
|
||||
}
|
||||
deadline, err := time.ParseInLocation("2006-01-02", form.Deadline, time.Local)
|
||||
deadline, err := time.ParseInLocation("2006-01-02", f.Deadline, time.Local)
|
||||
if err != nil {
|
||||
ctx.Data["Err_Deadline"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("repo.milestones.invalid_due_date_format"), MILESTONE_NEW, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("repo.milestones.invalid_due_date_format"), MILESTONE_NEW, &f)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1181,8 +1181,8 @@ func EditMilestonePost(ctx *context.Context, form auth.CreateMilestoneForm) {
|
||||
}
|
||||
return
|
||||
}
|
||||
m.Name = form.Title
|
||||
m.Content = form.Content
|
||||
m.Name = f.Title
|
||||
m.Content = f.Content
|
||||
m.Deadline = deadline
|
||||
if err = models.UpdateMilestone(m); err != nil {
|
||||
ctx.Handle(500, "UpdateMilestone", err)
|
||||
|
||||
@@ -15,9 +15,9 @@ import (
|
||||
"github.com/gogits/git-module"
|
||||
|
||||
"github.com/gogits/gogs/models"
|
||||
"github.com/gogits/gogs/modules/auth"
|
||||
"github.com/gogits/gogs/modules/base"
|
||||
"github.com/gogits/gogs/modules/context"
|
||||
"github.com/gogits/gogs/modules/form"
|
||||
"github.com/gogits/gogs/modules/setting"
|
||||
)
|
||||
|
||||
@@ -38,31 +38,27 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
func getForkRepository(ctx *context.Context) *models.Repository {
|
||||
forkRepo, err := models.GetRepositoryByID(ctx.ParamsInt64(":repoid"))
|
||||
func parseBaseRepository(ctx *context.Context) *models.Repository {
|
||||
baseRepo, err := models.GetRepositoryByID(ctx.ParamsInt64(":repoid"))
|
||||
if err != nil {
|
||||
if models.IsErrRepoNotExist(err) {
|
||||
ctx.Handle(404, "GetRepositoryByID", nil)
|
||||
} else {
|
||||
ctx.Handle(500, "GetRepositoryByID", err)
|
||||
}
|
||||
ctx.NotFoundOrServerError("GetRepositoryByID", models.IsErrRepoNotExist, err)
|
||||
return nil
|
||||
}
|
||||
|
||||
if !forkRepo.CanBeForked() || !forkRepo.HasAccess(ctx.User.ID) {
|
||||
ctx.Handle(404, "getForkRepository", nil)
|
||||
if !baseRepo.CanBeForked() || !baseRepo.HasAccess(ctx.User.ID) {
|
||||
ctx.NotFound()
|
||||
return nil
|
||||
}
|
||||
|
||||
ctx.Data["repo_name"] = forkRepo.Name
|
||||
ctx.Data["description"] = forkRepo.Description
|
||||
ctx.Data["IsPrivate"] = forkRepo.IsPrivate
|
||||
ctx.Data["repo_name"] = baseRepo.Name
|
||||
ctx.Data["description"] = baseRepo.Description
|
||||
ctx.Data["IsPrivate"] = baseRepo.IsPrivate
|
||||
|
||||
if err = forkRepo.GetOwner(); err != nil {
|
||||
if err = baseRepo.GetOwner(); err != nil {
|
||||
ctx.Handle(500, "GetOwner", err)
|
||||
return nil
|
||||
}
|
||||
ctx.Data["ForkFrom"] = forkRepo.Owner.Name + "/" + forkRepo.Name
|
||||
ctx.Data["ForkFrom"] = baseRepo.Owner.Name + "/" + baseRepo.Name
|
||||
|
||||
if err := ctx.User.GetOrganizations(true); err != nil {
|
||||
ctx.Handle(500, "GetOrganizations", err)
|
||||
@@ -70,13 +66,13 @@ func getForkRepository(ctx *context.Context) *models.Repository {
|
||||
}
|
||||
ctx.Data["Orgs"] = ctx.User.Orgs
|
||||
|
||||
return forkRepo
|
||||
return baseRepo
|
||||
}
|
||||
|
||||
func Fork(ctx *context.Context) {
|
||||
ctx.Data["Title"] = ctx.Tr("new_fork")
|
||||
|
||||
getForkRepository(ctx)
|
||||
parseBaseRepository(ctx)
|
||||
if ctx.Written() {
|
||||
return
|
||||
}
|
||||
@@ -85,15 +81,15 @@ func Fork(ctx *context.Context) {
|
||||
ctx.HTML(200, FORK)
|
||||
}
|
||||
|
||||
func ForkPost(ctx *context.Context, form auth.CreateRepoForm) {
|
||||
func ForkPost(ctx *context.Context, f form.CreateRepo) {
|
||||
ctx.Data["Title"] = ctx.Tr("new_fork")
|
||||
|
||||
forkRepo := getForkRepository(ctx)
|
||||
baseRepo := parseBaseRepository(ctx)
|
||||
if ctx.Written() {
|
||||
return
|
||||
}
|
||||
|
||||
ctxUser := checkContextUser(ctx, form.Uid)
|
||||
ctxUser := checkContextUser(ctx, f.UserID)
|
||||
if ctx.Written() {
|
||||
return
|
||||
}
|
||||
@@ -104,44 +100,42 @@ func ForkPost(ctx *context.Context, form auth.CreateRepoForm) {
|
||||
return
|
||||
}
|
||||
|
||||
repo, has := models.HasForkedRepo(ctxUser.ID, forkRepo.ID)
|
||||
repo, has := models.HasForkedRepo(ctxUser.ID, baseRepo.ID)
|
||||
if has {
|
||||
ctx.Redirect(setting.AppSubUrl + "/" + ctxUser.Name + "/" + repo.Name)
|
||||
ctx.Redirect(repo.Link())
|
||||
return
|
||||
}
|
||||
|
||||
// Check ownership of organization.
|
||||
if ctxUser.IsOrganization() {
|
||||
if !ctxUser.IsOwnedBy(ctx.User.ID) {
|
||||
ctx.Error(403)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Cannot fork to same owner
|
||||
if ctxUser.ID == forkRepo.OwnerID {
|
||||
ctx.RenderWithErr(ctx.Tr("repo.settings.cannot_fork_to_same_owner"), FORK, &form)
|
||||
if ctxUser.IsOrganization() && !ctxUser.IsOwnedBy(ctx.User.ID) {
|
||||
ctx.Error(403)
|
||||
return
|
||||
}
|
||||
|
||||
repo, err := models.ForkRepository(ctxUser, forkRepo, form.RepoName, form.Description)
|
||||
// Cannot fork to same owner
|
||||
if ctxUser.ID == baseRepo.OwnerID {
|
||||
ctx.RenderWithErr(ctx.Tr("repo.settings.cannot_fork_to_same_owner"), FORK, &f)
|
||||
return
|
||||
}
|
||||
|
||||
repo, err := models.ForkRepository(ctx.User, ctxUser, baseRepo, f.RepoName, f.Description)
|
||||
if err != nil {
|
||||
ctx.Data["Err_RepoName"] = true
|
||||
switch {
|
||||
case models.IsErrRepoAlreadyExist(err):
|
||||
ctx.RenderWithErr(ctx.Tr("repo.settings.new_owner_has_same_repo"), FORK, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("repo.settings.new_owner_has_same_repo"), FORK, &f)
|
||||
case models.IsErrNameReserved(err):
|
||||
ctx.RenderWithErr(ctx.Tr("repo.form.name_reserved", err.(models.ErrNameReserved).Name), FORK, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("repo.form.name_reserved", err.(models.ErrNameReserved).Name), FORK, &f)
|
||||
case models.IsErrNamePatternNotAllowed(err):
|
||||
ctx.RenderWithErr(ctx.Tr("repo.form.name_pattern_not_allowed", err.(models.ErrNamePatternNotAllowed).Pattern), FORK, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("repo.form.name_pattern_not_allowed", err.(models.ErrNamePatternNotAllowed).Pattern), FORK, &f)
|
||||
default:
|
||||
ctx.Handle(500, "ForkPost", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
log.Trace("Repository forked[%d]: %s/%s", forkRepo.ID, ctxUser.Name, repo.Name)
|
||||
ctx.Redirect(setting.AppSubUrl + "/" + ctxUser.Name + "/" + repo.Name)
|
||||
log.Trace("Repository forked from '%s' -> '%s'", baseRepo.FullName(), repo.FullName())
|
||||
ctx.Redirect(repo.Link())
|
||||
}
|
||||
|
||||
func checkPullInfo(ctx *context.Context) *models.Issue {
|
||||
@@ -636,7 +630,7 @@ func CompareAndPullRequest(ctx *context.Context) {
|
||||
ctx.HTML(200, COMPARE_PULL)
|
||||
}
|
||||
|
||||
func CompareAndPullRequestPost(ctx *context.Context, form auth.CreateIssueForm) {
|
||||
func CompareAndPullRequestPost(ctx *context.Context, f form.CreateIssue) {
|
||||
ctx.Data["Title"] = ctx.Tr("repo.pulls.compare_changes")
|
||||
ctx.Data["PageIsComparePull"] = true
|
||||
ctx.Data["IsDiffCompare"] = true
|
||||
@@ -653,17 +647,17 @@ func CompareAndPullRequestPost(ctx *context.Context, form auth.CreateIssueForm)
|
||||
return
|
||||
}
|
||||
|
||||
labelIDs, milestoneID, assigneeID := ValidateRepoMetas(ctx, form)
|
||||
labelIDs, milestoneID, assigneeID := ValidateRepoMetas(ctx, f)
|
||||
if ctx.Written() {
|
||||
return
|
||||
}
|
||||
|
||||
if setting.AttachmentEnabled {
|
||||
attachments = form.Files
|
||||
attachments = f.Files
|
||||
}
|
||||
|
||||
if ctx.HasError() {
|
||||
auth.AssignForm(form, ctx.Data)
|
||||
form.Assign(f, ctx.Data)
|
||||
|
||||
// This stage is already stop creating new pull request, so it does not matter if it has
|
||||
// something to compare or not.
|
||||
@@ -685,13 +679,13 @@ func CompareAndPullRequestPost(ctx *context.Context, form auth.CreateIssueForm)
|
||||
pullIssue := &models.Issue{
|
||||
RepoID: repo.ID,
|
||||
Index: repo.NextIssueIndex(),
|
||||
Title: form.Title,
|
||||
Title: f.Title,
|
||||
PosterID: ctx.User.ID,
|
||||
Poster: ctx.User,
|
||||
MilestoneID: milestoneID,
|
||||
AssigneeID: assigneeID,
|
||||
IsPull: true,
|
||||
Content: form.Content,
|
||||
Content: f.Content,
|
||||
}
|
||||
pullRequest := &models.PullRequest{
|
||||
HeadRepoID: headRepo.ID,
|
||||
|
||||
@@ -10,9 +10,9 @@ import (
|
||||
log "gopkg.in/clog.v1"
|
||||
|
||||
"github.com/gogits/gogs/models"
|
||||
"github.com/gogits/gogs/modules/auth"
|
||||
"github.com/gogits/gogs/modules/base"
|
||||
"github.com/gogits/gogs/modules/context"
|
||||
"github.com/gogits/gogs/modules/form"
|
||||
"github.com/gogits/gogs/modules/markdown"
|
||||
)
|
||||
|
||||
@@ -150,7 +150,7 @@ func NewRelease(ctx *context.Context) {
|
||||
ctx.HTML(200, RELEASE_NEW)
|
||||
}
|
||||
|
||||
func NewReleasePost(ctx *context.Context, form auth.NewReleaseForm) {
|
||||
func NewReleasePost(ctx *context.Context, f form.NewRelease) {
|
||||
ctx.Data["Title"] = ctx.Tr("repo.release.new_release")
|
||||
ctx.Data["PageIsReleaseList"] = true
|
||||
|
||||
@@ -159,13 +159,13 @@ func NewReleasePost(ctx *context.Context, form auth.NewReleaseForm) {
|
||||
return
|
||||
}
|
||||
|
||||
if !ctx.Repo.GitRepo.IsBranchExist(form.Target) {
|
||||
ctx.RenderWithErr(ctx.Tr("form.target_branch_not_exist"), RELEASE_NEW, &form)
|
||||
if !ctx.Repo.GitRepo.IsBranchExist(f.Target) {
|
||||
ctx.RenderWithErr(ctx.Tr("form.target_branch_not_exist"), RELEASE_NEW, &f)
|
||||
return
|
||||
}
|
||||
|
||||
var tagCreatedUnix int64
|
||||
tag, err := ctx.Repo.GitRepo.GetTag(form.TagName)
|
||||
tag, err := ctx.Repo.GitRepo.GetTag(f.TagName)
|
||||
if err == nil {
|
||||
commit, err := tag.Commit()
|
||||
if err == nil {
|
||||
@@ -173,7 +173,7 @@ func NewReleasePost(ctx *context.Context, form auth.NewReleaseForm) {
|
||||
}
|
||||
}
|
||||
|
||||
commit, err := ctx.Repo.GitRepo.GetBranchCommit(form.Target)
|
||||
commit, err := ctx.Repo.GitRepo.GetBranchCommit(f.Target)
|
||||
if err != nil {
|
||||
ctx.Handle(500, "GetBranchCommit", err)
|
||||
return
|
||||
@@ -188,14 +188,14 @@ func NewReleasePost(ctx *context.Context, form auth.NewReleaseForm) {
|
||||
rel := &models.Release{
|
||||
RepoID: ctx.Repo.Repository.ID,
|
||||
PublisherID: ctx.User.ID,
|
||||
Title: form.Title,
|
||||
TagName: form.TagName,
|
||||
Target: form.Target,
|
||||
Title: f.Title,
|
||||
TagName: f.TagName,
|
||||
Target: f.Target,
|
||||
Sha1: commit.ID.String(),
|
||||
NumCommits: commitsCount,
|
||||
Note: form.Content,
|
||||
IsDraft: len(form.Draft) > 0,
|
||||
IsPrerelease: form.Prerelease,
|
||||
Note: f.Content,
|
||||
IsDraft: len(f.Draft) > 0,
|
||||
IsPrerelease: f.Prerelease,
|
||||
CreatedUnix: tagCreatedUnix,
|
||||
}
|
||||
|
||||
@@ -203,15 +203,15 @@ func NewReleasePost(ctx *context.Context, form auth.NewReleaseForm) {
|
||||
ctx.Data["Err_TagName"] = true
|
||||
switch {
|
||||
case models.IsErrReleaseAlreadyExist(err):
|
||||
ctx.RenderWithErr(ctx.Tr("repo.release.tag_name_already_exist"), RELEASE_NEW, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("repo.release.tag_name_already_exist"), RELEASE_NEW, &f)
|
||||
case models.IsErrInvalidTagName(err):
|
||||
ctx.RenderWithErr(ctx.Tr("repo.release.tag_name_invalid"), RELEASE_NEW, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("repo.release.tag_name_invalid"), RELEASE_NEW, &f)
|
||||
default:
|
||||
ctx.Handle(500, "CreateRelease", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
log.Trace("Release created: %s/%s:%s", ctx.User.LowerName, ctx.Repo.Repository.Name, form.TagName)
|
||||
log.Trace("Release created: %s/%s:%s", ctx.User.LowerName, ctx.Repo.Repository.Name, f.TagName)
|
||||
|
||||
ctx.Redirect(ctx.Repo.RepoLink + "/releases")
|
||||
}
|
||||
@@ -242,7 +242,7 @@ func EditRelease(ctx *context.Context) {
|
||||
ctx.HTML(200, RELEASE_NEW)
|
||||
}
|
||||
|
||||
func EditReleasePost(ctx *context.Context, form auth.EditReleaseForm) {
|
||||
func EditReleasePost(ctx *context.Context, f form.EditRelease) {
|
||||
ctx.Data["Title"] = ctx.Tr("repo.release.edit_release")
|
||||
ctx.Data["PageIsReleaseList"] = true
|
||||
ctx.Data["PageIsEditRelease"] = true
|
||||
@@ -269,10 +269,10 @@ func EditReleasePost(ctx *context.Context, form auth.EditReleaseForm) {
|
||||
return
|
||||
}
|
||||
|
||||
rel.Title = form.Title
|
||||
rel.Note = form.Content
|
||||
rel.IsDraft = len(form.Draft) > 0
|
||||
rel.IsPrerelease = form.Prerelease
|
||||
rel.Title = f.Title
|
||||
rel.Note = f.Content
|
||||
rel.IsDraft = len(f.Draft) > 0
|
||||
rel.IsPrerelease = f.Prerelease
|
||||
if err = models.UpdateRelease(ctx.Repo.GitRepo, rel); err != nil {
|
||||
ctx.Handle(500, "UpdateRelease", err)
|
||||
return
|
||||
|
||||
@@ -16,9 +16,9 @@ import (
|
||||
"github.com/gogits/git-module"
|
||||
|
||||
"github.com/gogits/gogs/models"
|
||||
"github.com/gogits/gogs/modules/auth"
|
||||
"github.com/gogits/gogs/modules/base"
|
||||
"github.com/gogits/gogs/modules/context"
|
||||
"github.com/gogits/gogs/modules/form"
|
||||
"github.com/gogits/gogs/modules/setting"
|
||||
)
|
||||
|
||||
@@ -102,14 +102,14 @@ func handleCreateError(ctx *context.Context, owner *models.User, err error, name
|
||||
}
|
||||
}
|
||||
|
||||
func CreatePost(ctx *context.Context, form auth.CreateRepoForm) {
|
||||
func CreatePost(ctx *context.Context, f form.CreateRepo) {
|
||||
ctx.Data["Title"] = ctx.Tr("new_repo")
|
||||
|
||||
ctx.Data["Gitignores"] = models.Gitignores
|
||||
ctx.Data["Licenses"] = models.Licenses
|
||||
ctx.Data["Readmes"] = models.Readmes
|
||||
|
||||
ctxUser := checkContextUser(ctx, form.Uid)
|
||||
ctxUser := checkContextUser(ctx, f.UserID)
|
||||
if ctx.Written() {
|
||||
return
|
||||
}
|
||||
@@ -120,14 +120,14 @@ func CreatePost(ctx *context.Context, form auth.CreateRepoForm) {
|
||||
return
|
||||
}
|
||||
|
||||
repo, err := models.CreateRepository(ctxUser, models.CreateRepoOptions{
|
||||
Name: form.RepoName,
|
||||
Description: form.Description,
|
||||
Gitignores: form.Gitignores,
|
||||
License: form.License,
|
||||
Readme: form.Readme,
|
||||
IsPrivate: form.Private || setting.Repository.ForcePrivate,
|
||||
AutoInit: form.AutoInit,
|
||||
repo, err := models.CreateRepository(ctx.User, ctxUser, models.CreateRepoOptions{
|
||||
Name: f.RepoName,
|
||||
Description: f.Description,
|
||||
Gitignores: f.Gitignores,
|
||||
License: f.License,
|
||||
Readme: f.Readme,
|
||||
IsPrivate: f.Private || setting.Repository.ForcePrivate,
|
||||
AutoInit: f.AutoInit,
|
||||
})
|
||||
if err == nil {
|
||||
log.Trace("Repository created [%d]: %s/%s", repo.ID, ctxUser.Name, repo.Name)
|
||||
@@ -141,7 +141,7 @@ func CreatePost(ctx *context.Context, form auth.CreateRepoForm) {
|
||||
}
|
||||
}
|
||||
|
||||
handleCreateError(ctx, ctxUser, err, "CreatePost", CREATE, &form)
|
||||
handleCreateError(ctx, ctxUser, err, "CreatePost", CREATE, &f)
|
||||
}
|
||||
|
||||
func Migrate(ctx *context.Context) {
|
||||
@@ -159,10 +159,10 @@ func Migrate(ctx *context.Context) {
|
||||
ctx.HTML(200, MIGRATE)
|
||||
}
|
||||
|
||||
func MigratePost(ctx *context.Context, form auth.MigrateRepoForm) {
|
||||
func MigratePost(ctx *context.Context, f form.MigrateRepo) {
|
||||
ctx.Data["Title"] = ctx.Tr("new_migrate")
|
||||
|
||||
ctxUser := checkContextUser(ctx, form.Uid)
|
||||
ctxUser := checkContextUser(ctx, f.Uid)
|
||||
if ctx.Written() {
|
||||
return
|
||||
}
|
||||
@@ -173,18 +173,18 @@ func MigratePost(ctx *context.Context, form auth.MigrateRepoForm) {
|
||||
return
|
||||
}
|
||||
|
||||
remoteAddr, err := form.ParseRemoteAddr(ctx.User)
|
||||
remoteAddr, err := f.ParseRemoteAddr(ctx.User)
|
||||
if err != nil {
|
||||
if models.IsErrInvalidCloneAddr(err) {
|
||||
ctx.Data["Err_CloneAddr"] = true
|
||||
addrErr := err.(models.ErrInvalidCloneAddr)
|
||||
switch {
|
||||
case addrErr.IsURLError:
|
||||
ctx.RenderWithErr(ctx.Tr("form.url_error"), MIGRATE, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("form.url_error"), MIGRATE, &f)
|
||||
case addrErr.IsPermissionDenied:
|
||||
ctx.RenderWithErr(ctx.Tr("repo.migrate.permission_denied"), MIGRATE, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("repo.migrate.permission_denied"), MIGRATE, &f)
|
||||
case addrErr.IsInvalidPath:
|
||||
ctx.RenderWithErr(ctx.Tr("repo.migrate.invalid_local_path"), MIGRATE, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("repo.migrate.invalid_local_path"), MIGRATE, &f)
|
||||
default:
|
||||
ctx.Handle(500, "Unknown error", err)
|
||||
}
|
||||
@@ -194,16 +194,16 @@ func MigratePost(ctx *context.Context, form auth.MigrateRepoForm) {
|
||||
return
|
||||
}
|
||||
|
||||
repo, err := models.MigrateRepository(ctxUser, models.MigrateRepoOptions{
|
||||
Name: form.RepoName,
|
||||
Description: form.Description,
|
||||
IsPrivate: form.Private || setting.Repository.ForcePrivate,
|
||||
IsMirror: form.Mirror,
|
||||
repo, err := models.MigrateRepository(ctx.User, ctxUser, models.MigrateRepoOptions{
|
||||
Name: f.RepoName,
|
||||
Description: f.Description,
|
||||
IsPrivate: f.Private || setting.Repository.ForcePrivate,
|
||||
IsMirror: f.Mirror,
|
||||
RemoteAddr: remoteAddr,
|
||||
})
|
||||
if err == nil {
|
||||
log.Trace("Repository migrated [%d]: %s/%s", repo.ID, ctxUser.Name, form.RepoName)
|
||||
ctx.Redirect(setting.AppSubUrl + "/" + ctxUser.Name + "/" + form.RepoName)
|
||||
log.Trace("Repository migrated [%d]: %s/%s", repo.ID, ctxUser.Name, f.RepoName)
|
||||
ctx.Redirect(setting.AppSubUrl + "/" + ctxUser.Name + "/" + f.RepoName)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -216,15 +216,15 @@ func MigratePost(ctx *context.Context, form auth.MigrateRepoForm) {
|
||||
if strings.Contains(err.Error(), "Authentication failed") ||
|
||||
strings.Contains(err.Error(), "could not read Username") {
|
||||
ctx.Data["Err_Auth"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("form.auth_failed", models.HandleCloneUserCredentials(err.Error(), true)), MIGRATE, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("form.auth_failed", models.HandleCloneUserCredentials(err.Error(), true)), MIGRATE, &f)
|
||||
return
|
||||
} else if strings.Contains(err.Error(), "fatal:") {
|
||||
ctx.Data["Err_CloneAddr"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("repo.migrate.failed", models.HandleCloneUserCredentials(err.Error(), true)), MIGRATE, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("repo.migrate.failed", models.HandleCloneUserCredentials(err.Error(), true)), MIGRATE, &f)
|
||||
return
|
||||
}
|
||||
|
||||
handleCreateError(ctx, ctxUser, err, "MigratePost", MIGRATE, &form)
|
||||
handleCreateError(ctx, ctxUser, err, "MigratePost", MIGRATE, &f)
|
||||
}
|
||||
|
||||
func Action(ctx *context.Context) {
|
||||
|
||||
@@ -14,9 +14,9 @@ import (
|
||||
"github.com/gogits/git-module"
|
||||
|
||||
"github.com/gogits/gogs/models"
|
||||
"github.com/gogits/gogs/modules/auth"
|
||||
"github.com/gogits/gogs/modules/base"
|
||||
"github.com/gogits/gogs/modules/context"
|
||||
"github.com/gogits/gogs/modules/form"
|
||||
"github.com/gogits/gogs/modules/mailer"
|
||||
"github.com/gogits/gogs/modules/setting"
|
||||
)
|
||||
@@ -37,7 +37,7 @@ func Settings(ctx *context.Context) {
|
||||
ctx.HTML(200, SETTINGS_OPTIONS)
|
||||
}
|
||||
|
||||
func SettingsPost(ctx *context.Context, form auth.RepoSettingForm) {
|
||||
func SettingsPost(ctx *context.Context, f form.RepoSetting) {
|
||||
ctx.Data["Title"] = ctx.Tr("repo.settings")
|
||||
ctx.Data["PageIsSettingsOptions"] = true
|
||||
|
||||
@@ -52,7 +52,7 @@ func SettingsPost(ctx *context.Context, form auth.RepoSettingForm) {
|
||||
|
||||
isNameChanged := false
|
||||
oldRepoName := repo.Name
|
||||
newRepoName := form.RepoName
|
||||
newRepoName := f.RepoName
|
||||
// Check if repository name has been changed.
|
||||
if repo.LowerName != strings.ToLower(newRepoName) {
|
||||
isNameChanged = true
|
||||
@@ -60,11 +60,11 @@ func SettingsPost(ctx *context.Context, form auth.RepoSettingForm) {
|
||||
ctx.Data["Err_RepoName"] = true
|
||||
switch {
|
||||
case models.IsErrRepoAlreadyExist(err):
|
||||
ctx.RenderWithErr(ctx.Tr("form.repo_name_been_taken"), SETTINGS_OPTIONS, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("form.repo_name_been_taken"), SETTINGS_OPTIONS, &f)
|
||||
case models.IsErrNameReserved(err):
|
||||
ctx.RenderWithErr(ctx.Tr("repo.form.name_reserved", err.(models.ErrNameReserved).Name), SETTINGS_OPTIONS, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("repo.form.name_reserved", err.(models.ErrNameReserved).Name), SETTINGS_OPTIONS, &f)
|
||||
case models.IsErrNamePatternNotAllowed(err):
|
||||
ctx.RenderWithErr(ctx.Tr("repo.form.name_pattern_not_allowed", err.(models.ErrNamePatternNotAllowed).Pattern), SETTINGS_OPTIONS, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("repo.form.name_pattern_not_allowed", err.(models.ErrNamePatternNotAllowed).Pattern), SETTINGS_OPTIONS, &f)
|
||||
default:
|
||||
ctx.Handle(500, "ChangeRepositoryName", err)
|
||||
}
|
||||
@@ -77,16 +77,16 @@ func SettingsPost(ctx *context.Context, form auth.RepoSettingForm) {
|
||||
repo.Name = newRepoName
|
||||
repo.LowerName = strings.ToLower(newRepoName)
|
||||
|
||||
repo.Description = form.Description
|
||||
repo.Website = form.Website
|
||||
repo.Description = f.Description
|
||||
repo.Website = f.Website
|
||||
|
||||
// Visibility of forked repository is forced sync with base repository.
|
||||
if repo.IsFork {
|
||||
form.Private = repo.BaseRepo.IsPrivate
|
||||
f.Private = repo.BaseRepo.IsPrivate
|
||||
}
|
||||
|
||||
visibilityChanged := repo.IsPrivate != form.Private
|
||||
repo.IsPrivate = form.Private
|
||||
visibilityChanged := repo.IsPrivate != f.Private
|
||||
repo.IsPrivate = f.Private
|
||||
if err := models.UpdateRepository(repo, visibilityChanged); err != nil {
|
||||
ctx.Handle(500, "UpdateRepository", err)
|
||||
return
|
||||
@@ -108,16 +108,16 @@ func SettingsPost(ctx *context.Context, form auth.RepoSettingForm) {
|
||||
return
|
||||
}
|
||||
|
||||
if form.Interval > 0 {
|
||||
ctx.Repo.Mirror.EnablePrune = form.EnablePrune
|
||||
ctx.Repo.Mirror.Interval = form.Interval
|
||||
ctx.Repo.Mirror.NextUpdate = time.Now().Add(time.Duration(form.Interval) * time.Hour)
|
||||
if f.Interval > 0 {
|
||||
ctx.Repo.Mirror.EnablePrune = f.EnablePrune
|
||||
ctx.Repo.Mirror.Interval = f.Interval
|
||||
ctx.Repo.Mirror.NextUpdate = time.Now().Add(time.Duration(f.Interval) * time.Hour)
|
||||
if err := models.UpdateMirror(ctx.Repo.Mirror); err != nil {
|
||||
ctx.Handle(500, "UpdateMirror", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
if err := ctx.Repo.Mirror.SaveAddress(form.MirrorAddress); err != nil {
|
||||
if err := ctx.Repo.Mirror.SaveAddress(f.MirrorAddress); err != nil {
|
||||
ctx.Handle(500, "SaveAddress", err)
|
||||
return
|
||||
}
|
||||
@@ -136,15 +136,15 @@ func SettingsPost(ctx *context.Context, form auth.RepoSettingForm) {
|
||||
ctx.Redirect(repo.Link() + "/settings")
|
||||
|
||||
case "advanced":
|
||||
repo.EnableWiki = form.EnableWiki
|
||||
repo.EnableExternalWiki = form.EnableExternalWiki
|
||||
repo.ExternalWikiURL = form.ExternalWikiURL
|
||||
repo.EnableIssues = form.EnableIssues
|
||||
repo.EnableExternalTracker = form.EnableExternalTracker
|
||||
repo.ExternalTrackerURL = form.ExternalTrackerURL
|
||||
repo.ExternalTrackerFormat = form.TrackerURLFormat
|
||||
repo.ExternalTrackerStyle = form.TrackerIssueStyle
|
||||
repo.EnablePulls = form.EnablePulls
|
||||
repo.EnableWiki = f.EnableWiki
|
||||
repo.EnableExternalWiki = f.EnableExternalWiki
|
||||
repo.ExternalWikiURL = f.ExternalWikiURL
|
||||
repo.EnableIssues = f.EnableIssues
|
||||
repo.EnableExternalTracker = f.EnableExternalTracker
|
||||
repo.ExternalTrackerURL = f.ExternalTrackerURL
|
||||
repo.ExternalTrackerFormat = f.TrackerURLFormat
|
||||
repo.ExternalTrackerStyle = f.TrackerIssueStyle
|
||||
repo.EnablePulls = f.EnablePulls
|
||||
|
||||
if err := models.UpdateRepository(repo, false); err != nil {
|
||||
ctx.Handle(500, "UpdateRepository", err)
|
||||
@@ -160,7 +160,7 @@ func SettingsPost(ctx *context.Context, form auth.RepoSettingForm) {
|
||||
ctx.Error(404)
|
||||
return
|
||||
}
|
||||
if repo.Name != form.RepoName {
|
||||
if repo.Name != f.RepoName {
|
||||
ctx.RenderWithErr(ctx.Tr("form.enterred_invalid_repo_name"), SETTINGS_OPTIONS, nil)
|
||||
return
|
||||
}
|
||||
@@ -194,7 +194,7 @@ func SettingsPost(ctx *context.Context, form auth.RepoSettingForm) {
|
||||
ctx.Error(404)
|
||||
return
|
||||
}
|
||||
if repo.Name != form.RepoName {
|
||||
if repo.Name != f.RepoName {
|
||||
ctx.RenderWithErr(ctx.Tr("form.enterred_invalid_repo_name"), SETTINGS_OPTIONS, nil)
|
||||
return
|
||||
}
|
||||
@@ -233,7 +233,7 @@ func SettingsPost(ctx *context.Context, form auth.RepoSettingForm) {
|
||||
ctx.Error(404)
|
||||
return
|
||||
}
|
||||
if repo.Name != form.RepoName {
|
||||
if repo.Name != f.RepoName {
|
||||
ctx.RenderWithErr(ctx.Tr("form.enterred_invalid_repo_name"), SETTINGS_OPTIONS, nil)
|
||||
return
|
||||
}
|
||||
@@ -259,7 +259,7 @@ func SettingsPost(ctx *context.Context, form auth.RepoSettingForm) {
|
||||
ctx.Error(404)
|
||||
return
|
||||
}
|
||||
if repo.Name != form.RepoName {
|
||||
if repo.Name != f.RepoName {
|
||||
ctx.RenderWithErr(ctx.Tr("form.enterred_invalid_repo_name"), SETTINGS_OPTIONS, nil)
|
||||
return
|
||||
}
|
||||
@@ -444,7 +444,7 @@ func SettingsProtectedBranch(ctx *context.Context) {
|
||||
ctx.HTML(200, SETTINGS_PROTECTED_BRANCH)
|
||||
}
|
||||
|
||||
func SettingsProtectedBranchPost(ctx *context.Context, form auth.ProtectBranchForm) {
|
||||
func SettingsProtectedBranchPost(ctx *context.Context, f form.ProtectBranch) {
|
||||
branch := ctx.Params("*")
|
||||
if !ctx.Repo.GitRepo.IsBranchExist(branch) {
|
||||
ctx.NotFound()
|
||||
@@ -465,11 +465,11 @@ func SettingsProtectedBranchPost(ctx *context.Context, form auth.ProtectBranchFo
|
||||
}
|
||||
}
|
||||
|
||||
protectBranch.Protected = form.Protected
|
||||
protectBranch.RequirePullRequest = form.RequirePullRequest
|
||||
protectBranch.EnableWhitelist = form.EnableWhitelist
|
||||
protectBranch.Protected = f.Protected
|
||||
protectBranch.RequirePullRequest = f.RequirePullRequest
|
||||
protectBranch.EnableWhitelist = f.EnableWhitelist
|
||||
if ctx.Repo.Owner.IsOrganization() {
|
||||
err = models.UpdateOrgProtectBranch(ctx.Repo.Repository, protectBranch, form.WhitelistUsers, form.WhitelistTeams)
|
||||
err = models.UpdateOrgProtectBranch(ctx.Repo.Repository, protectBranch, f.WhitelistUsers, f.WhitelistTeams)
|
||||
} else {
|
||||
err = models.UpdateProtectBranch(protectBranch)
|
||||
}
|
||||
@@ -547,7 +547,7 @@ func SettingsDeployKeys(ctx *context.Context) {
|
||||
ctx.HTML(200, SETTINGS_DEPLOY_KEYS)
|
||||
}
|
||||
|
||||
func SettingsDeployKeysPost(ctx *context.Context, form auth.AddSSHKeyForm) {
|
||||
func SettingsDeployKeysPost(ctx *context.Context, f form.AddSSHKey) {
|
||||
ctx.Data["Title"] = ctx.Tr("repo.settings.deploy_keys")
|
||||
ctx.Data["PageIsSettingsKeys"] = true
|
||||
|
||||
@@ -563,7 +563,7 @@ func SettingsDeployKeysPost(ctx *context.Context, form auth.AddSSHKeyForm) {
|
||||
return
|
||||
}
|
||||
|
||||
content, err := models.CheckPublicKeyString(form.Content)
|
||||
content, err := models.CheckPublicKeyString(f.Content)
|
||||
if err != nil {
|
||||
if models.IsErrKeyUnableVerify(err) {
|
||||
ctx.Flash.Info(ctx.Tr("form.unable_verify_ssh_key"))
|
||||
@@ -576,16 +576,16 @@ func SettingsDeployKeysPost(ctx *context.Context, form auth.AddSSHKeyForm) {
|
||||
}
|
||||
}
|
||||
|
||||
key, err := models.AddDeployKey(ctx.Repo.Repository.ID, form.Title, content)
|
||||
key, err := models.AddDeployKey(ctx.Repo.Repository.ID, f.Title, content)
|
||||
if err != nil {
|
||||
ctx.Data["HasError"] = true
|
||||
switch {
|
||||
case models.IsErrKeyAlreadyExist(err):
|
||||
ctx.Data["Err_Content"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("repo.settings.key_been_used"), SETTINGS_DEPLOY_KEYS, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("repo.settings.key_been_used"), SETTINGS_DEPLOY_KEYS, &f)
|
||||
case models.IsErrKeyNameAlreadyUsed(err):
|
||||
ctx.Data["Err_Title"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("repo.settings.key_name_used"), SETTINGS_DEPLOY_KEYS, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("repo.settings.key_name_used"), SETTINGS_DEPLOY_KEYS, &f)
|
||||
default:
|
||||
ctx.Handle(500, "AddDeployKey", err)
|
||||
}
|
||||
|
||||
@@ -16,9 +16,9 @@ import (
|
||||
api "github.com/gogits/go-gogs-client"
|
||||
|
||||
"github.com/gogits/gogs/models"
|
||||
"github.com/gogits/gogs/modules/auth"
|
||||
"github.com/gogits/gogs/modules/base"
|
||||
"github.com/gogits/gogs/modules/context"
|
||||
"github.com/gogits/gogs/modules/form"
|
||||
"github.com/gogits/gogs/modules/setting"
|
||||
)
|
||||
|
||||
@@ -103,20 +103,22 @@ func WebhooksNew(ctx *context.Context) {
|
||||
ctx.HTML(200, orCtx.NewTemplate)
|
||||
}
|
||||
|
||||
func ParseHookEvent(form auth.WebhookForm) *models.HookEvent {
|
||||
func ParseHookEvent(f form.Webhook) *models.HookEvent {
|
||||
return &models.HookEvent{
|
||||
PushOnly: form.PushOnly(),
|
||||
SendEverything: form.SendEverything(),
|
||||
ChooseEvents: form.ChooseEvents(),
|
||||
PushOnly: f.PushOnly(),
|
||||
SendEverything: f.SendEverything(),
|
||||
ChooseEvents: f.ChooseEvents(),
|
||||
HookEvents: models.HookEvents{
|
||||
Create: form.Create,
|
||||
Push: form.Push,
|
||||
PullRequest: form.PullRequest,
|
||||
Create: f.Create,
|
||||
Delete: f.Delete,
|
||||
Fork: f.Fork,
|
||||
Push: f.Push,
|
||||
PullRequest: f.PullRequest,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func WebHooksNewPost(ctx *context.Context, form auth.NewWebhookForm) {
|
||||
func WebHooksNewPost(ctx *context.Context, f form.NewWebhook) {
|
||||
ctx.Data["Title"] = ctx.Tr("repo.settings.add_webhook")
|
||||
ctx.Data["PageIsSettingsHooks"] = true
|
||||
ctx.Data["PageIsSettingsHooksNew"] = true
|
||||
@@ -136,17 +138,17 @@ func WebHooksNewPost(ctx *context.Context, form auth.NewWebhookForm) {
|
||||
}
|
||||
|
||||
contentType := models.JSON
|
||||
if models.HookContentType(form.ContentType) == models.FORM {
|
||||
if models.HookContentType(f.ContentType) == models.FORM {
|
||||
contentType = models.FORM
|
||||
}
|
||||
|
||||
w := &models.Webhook{
|
||||
RepoID: orCtx.RepoID,
|
||||
URL: form.PayloadURL,
|
||||
URL: f.PayloadURL,
|
||||
ContentType: contentType,
|
||||
Secret: form.Secret,
|
||||
HookEvent: ParseHookEvent(form.WebhookForm),
|
||||
IsActive: form.Active,
|
||||
Secret: f.Secret,
|
||||
HookEvent: ParseHookEvent(f.Webhook),
|
||||
IsActive: f.Active,
|
||||
HookTaskType: models.GOGS,
|
||||
OrgID: orCtx.OrgID,
|
||||
}
|
||||
@@ -162,7 +164,7 @@ func WebHooksNewPost(ctx *context.Context, form auth.NewWebhookForm) {
|
||||
ctx.Redirect(orCtx.Link + "/settings/hooks")
|
||||
}
|
||||
|
||||
func SlackHooksNewPost(ctx *context.Context, form auth.NewSlackHookForm) {
|
||||
func SlackHooksNewPost(ctx *context.Context, f form.NewSlackHook) {
|
||||
ctx.Data["Title"] = ctx.Tr("repo.settings")
|
||||
ctx.Data["PageIsSettingsHooks"] = true
|
||||
ctx.Data["PageIsSettingsHooksNew"] = true
|
||||
@@ -180,10 +182,10 @@ func SlackHooksNewPost(ctx *context.Context, form auth.NewSlackHookForm) {
|
||||
}
|
||||
|
||||
meta, err := json.Marshal(&models.SlackMeta{
|
||||
Channel: form.Channel,
|
||||
Username: form.Username,
|
||||
IconURL: form.IconURL,
|
||||
Color: form.Color,
|
||||
Channel: f.Channel,
|
||||
Username: f.Username,
|
||||
IconURL: f.IconURL,
|
||||
Color: f.Color,
|
||||
})
|
||||
if err != nil {
|
||||
ctx.Handle(500, "Marshal", err)
|
||||
@@ -192,10 +194,10 @@ func SlackHooksNewPost(ctx *context.Context, form auth.NewSlackHookForm) {
|
||||
|
||||
w := &models.Webhook{
|
||||
RepoID: orCtx.RepoID,
|
||||
URL: form.PayloadURL,
|
||||
URL: f.PayloadURL,
|
||||
ContentType: models.JSON,
|
||||
HookEvent: ParseHookEvent(form.WebhookForm),
|
||||
IsActive: form.Active,
|
||||
HookEvent: ParseHookEvent(f.Webhook),
|
||||
IsActive: f.Active,
|
||||
HookTaskType: models.SLACK,
|
||||
Meta: string(meta),
|
||||
OrgID: orCtx.OrgID,
|
||||
@@ -213,7 +215,7 @@ func SlackHooksNewPost(ctx *context.Context, form auth.NewSlackHookForm) {
|
||||
}
|
||||
|
||||
// FIXME: merge logic to Slack
|
||||
func DiscordHooksNewPost(ctx *context.Context, form auth.NewDiscordHookForm) {
|
||||
func DiscordHooksNewPost(ctx *context.Context, f form.NewDiscordHook) {
|
||||
ctx.Data["Title"] = ctx.Tr("repo.settings")
|
||||
ctx.Data["PageIsSettingsHooks"] = true
|
||||
ctx.Data["PageIsSettingsHooksNew"] = true
|
||||
@@ -231,9 +233,9 @@ func DiscordHooksNewPost(ctx *context.Context, form auth.NewDiscordHookForm) {
|
||||
}
|
||||
|
||||
meta, err := json.Marshal(&models.SlackMeta{
|
||||
Username: form.Username,
|
||||
IconURL: form.IconURL,
|
||||
Color: form.Color,
|
||||
Username: f.Username,
|
||||
IconURL: f.IconURL,
|
||||
Color: f.Color,
|
||||
})
|
||||
if err != nil {
|
||||
ctx.Handle(500, "Marshal", err)
|
||||
@@ -242,10 +244,10 @@ func DiscordHooksNewPost(ctx *context.Context, form auth.NewDiscordHookForm) {
|
||||
|
||||
w := &models.Webhook{
|
||||
RepoID: orCtx.RepoID,
|
||||
URL: form.PayloadURL,
|
||||
URL: f.PayloadURL,
|
||||
ContentType: models.JSON,
|
||||
HookEvent: ParseHookEvent(form.WebhookForm),
|
||||
IsActive: form.Active,
|
||||
HookEvent: ParseHookEvent(f.Webhook),
|
||||
IsActive: f.Active,
|
||||
HookTaskType: models.DISCORD,
|
||||
Meta: string(meta),
|
||||
OrgID: orCtx.OrgID,
|
||||
@@ -319,7 +321,7 @@ func WebHooksEdit(ctx *context.Context) {
|
||||
ctx.HTML(200, orCtx.NewTemplate)
|
||||
}
|
||||
|
||||
func WebHooksEditPost(ctx *context.Context, form auth.NewWebhookForm) {
|
||||
func WebHooksEditPost(ctx *context.Context, f form.NewWebhook) {
|
||||
ctx.Data["Title"] = ctx.Tr("repo.settings.update_webhook")
|
||||
ctx.Data["PageIsSettingsHooks"] = true
|
||||
ctx.Data["PageIsSettingsHooksEdit"] = true
|
||||
@@ -336,15 +338,15 @@ func WebHooksEditPost(ctx *context.Context, form auth.NewWebhookForm) {
|
||||
}
|
||||
|
||||
contentType := models.JSON
|
||||
if models.HookContentType(form.ContentType) == models.FORM {
|
||||
if models.HookContentType(f.ContentType) == models.FORM {
|
||||
contentType = models.FORM
|
||||
}
|
||||
|
||||
w.URL = form.PayloadURL
|
||||
w.URL = f.PayloadURL
|
||||
w.ContentType = contentType
|
||||
w.Secret = form.Secret
|
||||
w.HookEvent = ParseHookEvent(form.WebhookForm)
|
||||
w.IsActive = form.Active
|
||||
w.Secret = f.Secret
|
||||
w.HookEvent = ParseHookEvent(f.Webhook)
|
||||
w.IsActive = f.Active
|
||||
if err := w.UpdateEvent(); err != nil {
|
||||
ctx.Handle(500, "UpdateEvent", err)
|
||||
return
|
||||
@@ -357,7 +359,7 @@ func WebHooksEditPost(ctx *context.Context, form auth.NewWebhookForm) {
|
||||
ctx.Redirect(fmt.Sprintf("%s/settings/hooks/%d", orCtx.Link, w.ID))
|
||||
}
|
||||
|
||||
func SlackHooksEditPost(ctx *context.Context, form auth.NewSlackHookForm) {
|
||||
func SlackHooksEditPost(ctx *context.Context, f form.NewSlackHook) {
|
||||
ctx.Data["Title"] = ctx.Tr("repo.settings")
|
||||
ctx.Data["PageIsSettingsHooks"] = true
|
||||
ctx.Data["PageIsSettingsHooksEdit"] = true
|
||||
@@ -374,20 +376,20 @@ func SlackHooksEditPost(ctx *context.Context, form auth.NewSlackHookForm) {
|
||||
}
|
||||
|
||||
meta, err := json.Marshal(&models.SlackMeta{
|
||||
Channel: form.Channel,
|
||||
Username: form.Username,
|
||||
IconURL: form.IconURL,
|
||||
Color: form.Color,
|
||||
Channel: f.Channel,
|
||||
Username: f.Username,
|
||||
IconURL: f.IconURL,
|
||||
Color: f.Color,
|
||||
})
|
||||
if err != nil {
|
||||
ctx.Handle(500, "Marshal", err)
|
||||
return
|
||||
}
|
||||
|
||||
w.URL = form.PayloadURL
|
||||
w.URL = f.PayloadURL
|
||||
w.Meta = string(meta)
|
||||
w.HookEvent = ParseHookEvent(form.WebhookForm)
|
||||
w.IsActive = form.Active
|
||||
w.HookEvent = ParseHookEvent(f.Webhook)
|
||||
w.IsActive = f.Active
|
||||
if err := w.UpdateEvent(); err != nil {
|
||||
ctx.Handle(500, "UpdateEvent", err)
|
||||
return
|
||||
@@ -401,7 +403,7 @@ func SlackHooksEditPost(ctx *context.Context, form auth.NewSlackHookForm) {
|
||||
}
|
||||
|
||||
// FIXME: merge logic to Slack
|
||||
func DiscordHooksEditPost(ctx *context.Context, form auth.NewDiscordHookForm) {
|
||||
func DiscordHooksEditPost(ctx *context.Context, f form.NewDiscordHook) {
|
||||
ctx.Data["Title"] = ctx.Tr("repo.settings")
|
||||
ctx.Data["PageIsSettingsHooks"] = true
|
||||
ctx.Data["PageIsSettingsHooksEdit"] = true
|
||||
@@ -418,19 +420,19 @@ func DiscordHooksEditPost(ctx *context.Context, form auth.NewDiscordHookForm) {
|
||||
}
|
||||
|
||||
meta, err := json.Marshal(&models.SlackMeta{
|
||||
Username: form.Username,
|
||||
IconURL: form.IconURL,
|
||||
Color: form.Color,
|
||||
Username: f.Username,
|
||||
IconURL: f.IconURL,
|
||||
Color: f.Color,
|
||||
})
|
||||
if err != nil {
|
||||
ctx.Handle(500, "Marshal", err)
|
||||
return
|
||||
}
|
||||
|
||||
w.URL = form.PayloadURL
|
||||
w.URL = f.PayloadURL
|
||||
w.Meta = string(meta)
|
||||
w.HookEvent = ParseHookEvent(form.WebhookForm)
|
||||
w.IsActive = form.Active
|
||||
w.HookEvent = ParseHookEvent(f.Webhook)
|
||||
w.IsActive = f.Active
|
||||
if err := w.UpdateEvent(); err != nil {
|
||||
ctx.Handle(500, "UpdateEvent", err)
|
||||
return
|
||||
|
||||
@@ -12,9 +12,9 @@ import (
|
||||
"github.com/gogits/git-module"
|
||||
|
||||
"github.com/gogits/gogs/models"
|
||||
"github.com/gogits/gogs/modules/auth"
|
||||
"github.com/gogits/gogs/modules/base"
|
||||
"github.com/gogits/gogs/modules/context"
|
||||
"github.com/gogits/gogs/modules/form"
|
||||
"github.com/gogits/gogs/modules/markdown"
|
||||
)
|
||||
|
||||
@@ -198,7 +198,7 @@ func NewWiki(ctx *context.Context) {
|
||||
ctx.HTML(200, WIKI_NEW)
|
||||
}
|
||||
|
||||
func NewWikiPost(ctx *context.Context, form auth.NewWikiForm) {
|
||||
func NewWikiPost(ctx *context.Context, f form.NewWiki) {
|
||||
ctx.Data["Title"] = ctx.Tr("repo.wiki.new_page")
|
||||
ctx.Data["PageIsWiki"] = true
|
||||
ctx.Data["RequireSimpleMDE"] = true
|
||||
@@ -208,17 +208,17 @@ func NewWikiPost(ctx *context.Context, form auth.NewWikiForm) {
|
||||
return
|
||||
}
|
||||
|
||||
if err := ctx.Repo.Repository.AddWikiPage(ctx.User, form.Title, form.Content, form.Message); err != nil {
|
||||
if err := ctx.Repo.Repository.AddWikiPage(ctx.User, f.Title, f.Content, f.Message); err != nil {
|
||||
if models.IsErrWikiAlreadyExist(err) {
|
||||
ctx.Data["Err_Title"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("repo.wiki.page_already_exists"), WIKI_NEW, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("repo.wiki.page_already_exists"), WIKI_NEW, &f)
|
||||
} else {
|
||||
ctx.Handle(500, "AddWikiPage", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Redirect(ctx.Repo.RepoLink + "/wiki/" + models.ToWikiPageURL(models.ToWikiPageName(form.Title)))
|
||||
ctx.Redirect(ctx.Repo.RepoLink + "/wiki/" + models.ToWikiPageURL(models.ToWikiPageName(f.Title)))
|
||||
}
|
||||
|
||||
func EditWiki(ctx *context.Context) {
|
||||
@@ -239,7 +239,7 @@ func EditWiki(ctx *context.Context) {
|
||||
ctx.HTML(200, WIKI_NEW)
|
||||
}
|
||||
|
||||
func EditWikiPost(ctx *context.Context, form auth.NewWikiForm) {
|
||||
func EditWikiPost(ctx *context.Context, f form.NewWiki) {
|
||||
ctx.Data["Title"] = ctx.Tr("repo.wiki.new_page")
|
||||
ctx.Data["PageIsWiki"] = true
|
||||
ctx.Data["RequireSimpleMDE"] = true
|
||||
@@ -249,12 +249,12 @@ func EditWikiPost(ctx *context.Context, form auth.NewWikiForm) {
|
||||
return
|
||||
}
|
||||
|
||||
if err := ctx.Repo.Repository.EditWikiPage(ctx.User, form.OldTitle, form.Title, form.Content, form.Message); err != nil {
|
||||
if err := ctx.Repo.Repository.EditWikiPage(ctx.User, f.OldTitle, f.Title, f.Content, f.Message); err != nil {
|
||||
ctx.Handle(500, "EditWikiPage", err)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Redirect(ctx.Repo.RepoLink + "/wiki/" + models.ToWikiPageURL(models.ToWikiPageName(form.Title)))
|
||||
ctx.Redirect(ctx.Repo.RepoLink + "/wiki/" + models.ToWikiPageURL(models.ToWikiPageName(f.Title)))
|
||||
}
|
||||
|
||||
func DeleteWikiPagePost(ctx *context.Context) {
|
||||
|
||||
@@ -12,9 +12,9 @@ import (
|
||||
log "gopkg.in/clog.v1"
|
||||
|
||||
"github.com/gogits/gogs/models"
|
||||
"github.com/gogits/gogs/modules/auth"
|
||||
"github.com/gogits/gogs/modules/base"
|
||||
"github.com/gogits/gogs/modules/context"
|
||||
"github.com/gogits/gogs/modules/form"
|
||||
"github.com/gogits/gogs/modules/mailer"
|
||||
"github.com/gogits/gogs/modules/setting"
|
||||
)
|
||||
@@ -103,7 +103,7 @@ func SignIn(ctx *context.Context) {
|
||||
ctx.HTML(200, SIGNIN)
|
||||
}
|
||||
|
||||
func SignInPost(ctx *context.Context, form auth.SignInForm) {
|
||||
func SignInPost(ctx *context.Context, f form.SignIn) {
|
||||
ctx.Data["Title"] = ctx.Tr("sign_in")
|
||||
|
||||
if ctx.HasError() {
|
||||
@@ -111,17 +111,17 @@ func SignInPost(ctx *context.Context, form auth.SignInForm) {
|
||||
return
|
||||
}
|
||||
|
||||
u, err := models.UserSignIn(form.UserName, form.Password)
|
||||
u, err := models.UserSignIn(f.UserName, f.Password)
|
||||
if err != nil {
|
||||
if models.IsErrUserNotExist(err) {
|
||||
ctx.RenderWithErr(ctx.Tr("form.username_password_incorrect"), SIGNIN, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("form.username_password_incorrect"), SIGNIN, &f)
|
||||
} else {
|
||||
ctx.Handle(500, "UserSignIn", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if form.Remember {
|
||||
if f.Remember {
|
||||
days := 86400 * setting.LogInRememberDays
|
||||
ctx.SetCookie(setting.CookieUserName, u.Name, days, setting.AppSubUrl, "", setting.CookieSecure, true)
|
||||
ctx.SetSuperSecureCookie(u.Rands+u.Passwd, setting.CookieRememberName, u.Name, days, setting.AppSubUrl, "", setting.CookieSecure, true)
|
||||
@@ -169,7 +169,7 @@ func SignUp(ctx *context.Context) {
|
||||
ctx.HTML(200, SIGNUP)
|
||||
}
|
||||
|
||||
func SignUpPost(ctx *context.Context, cpt *captcha.Captcha, form auth.RegisterForm) {
|
||||
func SignUpPost(ctx *context.Context, cpt *captcha.Captcha, f form.Register) {
|
||||
ctx.Data["Title"] = ctx.Tr("sign_up")
|
||||
|
||||
ctx.Data["EnableCaptcha"] = setting.Service.EnableCaptcha
|
||||
@@ -186,36 +186,36 @@ func SignUpPost(ctx *context.Context, cpt *captcha.Captcha, form auth.RegisterFo
|
||||
|
||||
if setting.Service.EnableCaptcha && !cpt.VerifyReq(ctx.Req) {
|
||||
ctx.Data["Err_Captcha"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("form.captcha_incorrect"), SIGNUP, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("form.captcha_incorrect"), SIGNUP, &f)
|
||||
return
|
||||
}
|
||||
|
||||
if form.Password != form.Retype {
|
||||
if f.Password != f.Retype {
|
||||
ctx.Data["Err_Password"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("form.password_not_match"), SIGNUP, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("form.password_not_match"), SIGNUP, &f)
|
||||
return
|
||||
}
|
||||
|
||||
u := &models.User{
|
||||
Name: form.UserName,
|
||||
Email: form.Email,
|
||||
Passwd: form.Password,
|
||||
Name: f.UserName,
|
||||
Email: f.Email,
|
||||
Passwd: f.Password,
|
||||
IsActive: !setting.Service.RegisterEmailConfirm,
|
||||
}
|
||||
if err := models.CreateUser(u); err != nil {
|
||||
switch {
|
||||
case models.IsErrUserAlreadyExist(err):
|
||||
ctx.Data["Err_UserName"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("form.username_been_taken"), SIGNUP, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("form.username_been_taken"), SIGNUP, &f)
|
||||
case models.IsErrEmailAlreadyUsed(err):
|
||||
ctx.Data["Err_Email"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("form.email_been_used"), SIGNUP, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("form.email_been_used"), SIGNUP, &f)
|
||||
case models.IsErrNameReserved(err):
|
||||
ctx.Data["Err_UserName"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("user.form.name_reserved", err.(models.ErrNameReserved).Name), SIGNUP, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("user.form.name_reserved", err.(models.ErrNameReserved).Name), SIGNUP, &f)
|
||||
case models.IsErrNamePatternNotAllowed(err):
|
||||
ctx.Data["Err_UserName"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("user.form.name_pattern_not_allowed", err.(models.ErrNamePatternNotAllowed).Pattern), SIGNUP, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("user.form.name_pattern_not_allowed", err.(models.ErrNamePatternNotAllowed).Pattern), SIGNUP, &f)
|
||||
default:
|
||||
ctx.Handle(500, "CreateUser", err)
|
||||
}
|
||||
|
||||
@@ -14,9 +14,9 @@ import (
|
||||
log "gopkg.in/clog.v1"
|
||||
|
||||
"github.com/gogits/gogs/models"
|
||||
"github.com/gogits/gogs/modules/auth"
|
||||
"github.com/gogits/gogs/modules/base"
|
||||
"github.com/gogits/gogs/modules/context"
|
||||
"github.com/gogits/gogs/modules/form"
|
||||
"github.com/gogits/gogs/modules/mailer"
|
||||
"github.com/gogits/gogs/modules/setting"
|
||||
)
|
||||
@@ -76,7 +76,7 @@ func handleUsernameChange(ctx *context.Context, newName string) {
|
||||
ctx.User.LowerName = strings.ToLower(newName)
|
||||
}
|
||||
|
||||
func SettingsPost(ctx *context.Context, form auth.UpdateProfileForm) {
|
||||
func SettingsPost(ctx *context.Context, f form.UpdateProfile) {
|
||||
ctx.Data["Title"] = ctx.Tr("settings")
|
||||
ctx.Data["PageIsSettingsProfile"] = true
|
||||
|
||||
@@ -85,15 +85,15 @@ func SettingsPost(ctx *context.Context, form auth.UpdateProfileForm) {
|
||||
return
|
||||
}
|
||||
|
||||
handleUsernameChange(ctx, form.Name)
|
||||
handleUsernameChange(ctx, f.Name)
|
||||
if ctx.Written() {
|
||||
return
|
||||
}
|
||||
|
||||
ctx.User.FullName = form.FullName
|
||||
ctx.User.Email = form.Email
|
||||
ctx.User.Website = form.Website
|
||||
ctx.User.Location = form.Location
|
||||
ctx.User.FullName = f.FullName
|
||||
ctx.User.Email = f.Email
|
||||
ctx.User.Website = f.Website
|
||||
ctx.User.Location = f.Location
|
||||
if err := models.UpdateUser(ctx.User); err != nil {
|
||||
ctx.Handle(500, "UpdateUser", err)
|
||||
return
|
||||
@@ -105,15 +105,15 @@ func SettingsPost(ctx *context.Context, form auth.UpdateProfileForm) {
|
||||
}
|
||||
|
||||
// FIXME: limit size.
|
||||
func UpdateAvatarSetting(ctx *context.Context, form auth.AvatarForm, ctxUser *models.User) error {
|
||||
ctxUser.UseCustomAvatar = form.Source == auth.AVATAR_LOCAL
|
||||
if len(form.Gravatar) > 0 {
|
||||
ctxUser.Avatar = base.EncodeMD5(form.Gravatar)
|
||||
ctxUser.AvatarEmail = form.Gravatar
|
||||
func UpdateAvatarSetting(ctx *context.Context, f form.Avatar, ctxUser *models.User) error {
|
||||
ctxUser.UseCustomAvatar = f.Source == form.AVATAR_LOCAL
|
||||
if len(f.Gravatar) > 0 {
|
||||
ctxUser.Avatar = base.EncodeMD5(f.Gravatar)
|
||||
ctxUser.AvatarEmail = f.Gravatar
|
||||
}
|
||||
|
||||
if form.Avatar != nil {
|
||||
fr, err := form.Avatar.Open()
|
||||
if f.Avatar != nil {
|
||||
fr, err := f.Avatar.Open()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Avatar.Open: %v", err)
|
||||
}
|
||||
@@ -152,8 +152,8 @@ func SettingsAvatar(ctx *context.Context) {
|
||||
ctx.HTML(200, SETTINGS_AVATAR)
|
||||
}
|
||||
|
||||
func SettingsAvatarPost(ctx *context.Context, form auth.AvatarForm) {
|
||||
if err := UpdateAvatarSetting(ctx, form, ctx.User); err != nil {
|
||||
func SettingsAvatarPost(ctx *context.Context, f form.Avatar) {
|
||||
if err := UpdateAvatarSetting(ctx, f, ctx.User); err != nil {
|
||||
ctx.Flash.Error(err.Error())
|
||||
} else {
|
||||
ctx.Flash.Success(ctx.Tr("settings.update_avatar_success"))
|
||||
@@ -176,7 +176,7 @@ func SettingsPassword(ctx *context.Context) {
|
||||
ctx.HTML(200, SETTINGS_PASSWORD)
|
||||
}
|
||||
|
||||
func SettingsPasswordPost(ctx *context.Context, form auth.ChangePasswordForm) {
|
||||
func SettingsPasswordPost(ctx *context.Context, f form.ChangePassword) {
|
||||
ctx.Data["Title"] = ctx.Tr("settings")
|
||||
ctx.Data["PageIsSettingsPassword"] = true
|
||||
|
||||
@@ -185,12 +185,12 @@ func SettingsPasswordPost(ctx *context.Context, form auth.ChangePasswordForm) {
|
||||
return
|
||||
}
|
||||
|
||||
if !ctx.User.ValidatePassword(form.OldPassword) {
|
||||
if !ctx.User.ValidatePassword(f.OldPassword) {
|
||||
ctx.Flash.Error(ctx.Tr("settings.password_incorrect"))
|
||||
} else if form.Password != form.Retype {
|
||||
} else if f.Password != f.Retype {
|
||||
ctx.Flash.Error(ctx.Tr("form.password_not_match"))
|
||||
} else {
|
||||
ctx.User.Passwd = form.Password
|
||||
ctx.User.Passwd = f.Password
|
||||
var err error
|
||||
if ctx.User.Salt, err = models.GetUserSalt(); err != nil {
|
||||
ctx.Handle(500, "UpdateUser", err)
|
||||
@@ -222,7 +222,7 @@ func SettingsEmails(ctx *context.Context) {
|
||||
ctx.HTML(200, SETTINGS_EMAILS)
|
||||
}
|
||||
|
||||
func SettingsEmailPost(ctx *context.Context, form auth.AddEmailForm) {
|
||||
func SettingsEmailPost(ctx *context.Context, f form.AddEmail) {
|
||||
ctx.Data["Title"] = ctx.Tr("settings")
|
||||
ctx.Data["PageIsSettingsEmails"] = true
|
||||
|
||||
@@ -253,12 +253,12 @@ func SettingsEmailPost(ctx *context.Context, form auth.AddEmailForm) {
|
||||
|
||||
email := &models.EmailAddress{
|
||||
UID: ctx.User.ID,
|
||||
Email: form.Email,
|
||||
Email: f.Email,
|
||||
IsActivated: !setting.Service.RegisterEmailConfirm,
|
||||
}
|
||||
if err := models.AddEmailAddress(email); err != nil {
|
||||
if models.IsErrEmailAlreadyUsed(err) {
|
||||
ctx.RenderWithErr(ctx.Tr("form.email_been_used"), SETTINGS_EMAILS, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("form.email_been_used"), SETTINGS_EMAILS, &f)
|
||||
return
|
||||
}
|
||||
ctx.Handle(500, "AddEmailAddress", err)
|
||||
@@ -311,7 +311,7 @@ func SettingsSSHKeys(ctx *context.Context) {
|
||||
ctx.HTML(200, SETTINGS_SSH_KEYS)
|
||||
}
|
||||
|
||||
func SettingsSSHKeysPost(ctx *context.Context, form auth.AddSSHKeyForm) {
|
||||
func SettingsSSHKeysPost(ctx *context.Context, f form.AddSSHKey) {
|
||||
ctx.Data["Title"] = ctx.Tr("settings")
|
||||
ctx.Data["PageIsSettingsSSHKeys"] = true
|
||||
|
||||
@@ -327,7 +327,7 @@ func SettingsSSHKeysPost(ctx *context.Context, form auth.AddSSHKeyForm) {
|
||||
return
|
||||
}
|
||||
|
||||
content, err := models.CheckPublicKeyString(form.Content)
|
||||
content, err := models.CheckPublicKeyString(f.Content)
|
||||
if err != nil {
|
||||
if models.IsErrKeyUnableVerify(err) {
|
||||
ctx.Flash.Info(ctx.Tr("form.unable_verify_ssh_key"))
|
||||
@@ -338,22 +338,22 @@ func SettingsSSHKeysPost(ctx *context.Context, form auth.AddSSHKeyForm) {
|
||||
}
|
||||
}
|
||||
|
||||
if _, err = models.AddPublicKey(ctx.User.ID, form.Title, content); err != nil {
|
||||
if _, err = models.AddPublicKey(ctx.User.ID, f.Title, content); err != nil {
|
||||
ctx.Data["HasError"] = true
|
||||
switch {
|
||||
case models.IsErrKeyAlreadyExist(err):
|
||||
ctx.Data["Err_Content"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("settings.ssh_key_been_used"), SETTINGS_SSH_KEYS, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("settings.ssh_key_been_used"), SETTINGS_SSH_KEYS, &f)
|
||||
case models.IsErrKeyNameAlreadyUsed(err):
|
||||
ctx.Data["Err_Title"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("settings.ssh_key_name_used"), SETTINGS_SSH_KEYS, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("settings.ssh_key_name_used"), SETTINGS_SSH_KEYS, &f)
|
||||
default:
|
||||
ctx.Handle(500, "AddPublicKey", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Flash.Success(ctx.Tr("settings.add_key_success", form.Title))
|
||||
ctx.Flash.Success(ctx.Tr("settings.add_key_success", f.Title))
|
||||
ctx.Redirect(setting.AppSubUrl + "/user/settings/ssh")
|
||||
}
|
||||
|
||||
@@ -383,7 +383,7 @@ func SettingsApplications(ctx *context.Context) {
|
||||
ctx.HTML(200, SETTINGS_APPLICATIONS)
|
||||
}
|
||||
|
||||
func SettingsApplicationsPost(ctx *context.Context, form auth.NewAccessTokenForm) {
|
||||
func SettingsApplicationsPost(ctx *context.Context, f form.NewAccessToken) {
|
||||
ctx.Data["Title"] = ctx.Tr("settings")
|
||||
ctx.Data["PageIsSettingsApplications"] = true
|
||||
|
||||
@@ -400,7 +400,7 @@ func SettingsApplicationsPost(ctx *context.Context, form auth.NewAccessTokenForm
|
||||
|
||||
t := &models.AccessToken{
|
||||
UID: ctx.User.ID,
|
||||
Name: form.Name,
|
||||
Name: f.Name,
|
||||
}
|
||||
if err := models.NewAccessToken(t); err != nil {
|
||||
ctx.Handle(500, "NewAccessToken", err)
|
||||
|
||||
@@ -2,10 +2,7 @@
|
||||
Description=Gogs
|
||||
After=syslog.target
|
||||
After=network.target
|
||||
#After=mysqld.service
|
||||
#After=postgresql.service
|
||||
#After=memcached.service
|
||||
#After=redis.service
|
||||
After=mariadb.service mysqld.service postgresql.service memcached.service redis.service
|
||||
|
||||
[Service]
|
||||
# Modify these two values and uncomment them if you have
|
||||
|
||||
@@ -1 +1 @@
|
||||
0.10.1.0228
|
||||
0.10.8.0307
|
||||
@@ -170,7 +170,7 @@
|
||||
<dd><i class="fa fa{{if .MailerEnabled}}-check{{end}}-square-o"></i></dd>
|
||||
{{if .MailerEnabled}}
|
||||
<dt>{{.i18n.Tr "admin.config.mailer_name"}}</dt>
|
||||
<dd>{{.Mailer.Name}}</dd>
|
||||
<dd>{{.Mailer.Subject}}</dd>
|
||||
<dt>{{.i18n.Tr "admin.config.mailer_disable_helo"}}</dt>
|
||||
<dd><i class="fa fa{{if .Mailer.DisableHelo}}-check{{end}}-square-o"></i></dd>
|
||||
<dt>{{.i18n.Tr "admin.config.mailer_host"}}</dt>
|
||||
@@ -258,8 +258,6 @@
|
||||
<dd>{{.Git.MaxGitDiffFiles}}</dd>
|
||||
<dt>{{.i18n.Tr "admin.config.git_gc_args"}}</dt>
|
||||
<dd><code>{{.Git.GCArgs}}</code></dd>
|
||||
<dt>{{.i18n.Tr "admin.config.git_max_diff_lines"}}</dt>
|
||||
<dd>{{.Git.MaxGitDiffLines}}</dd>
|
||||
<div class="ui divider"></div>
|
||||
<dt>{{.i18n.Tr "admin.config.git_migrate_timeout"}}</dt>
|
||||
<dd>{{.Git.Timeout.Migrate}} {{.i18n.Tr "tool.raw_seconds"}}</dd>
|
||||
@@ -277,15 +275,19 @@
|
||||
<h4 class="ui top attached header">
|
||||
{{.i18n.Tr "admin.config.log_config"}}
|
||||
</h4>
|
||||
<div class="ui attached table segment">
|
||||
<dl class="dl-horizontal admin-dl-horizontal">
|
||||
<div class="ui attached log-config segment">
|
||||
<table class="ui very basic table">
|
||||
{{range .Loggers}}
|
||||
<dt>{{$.i18n.Tr "admin.config.log_mode"}}</dt>
|
||||
<dd>{{.Mode}}</dd>
|
||||
<dt>{{$.i18n.Tr "admin.config.log_config"}}</dt>
|
||||
<dd><pre><code>{{.Config}}</code></pre></dd>
|
||||
<tr>
|
||||
<td>{{$.i18n.Tr "admin.config.log_mode"}}</td>
|
||||
<td>{{.Mode}}</td>
|
||||
<tr>
|
||||
</tr>
|
||||
<td>{{$.i18n.Tr "admin.config.log_options"}}</td>
|
||||
<td><pre><code>{{.Config}}</code></pre></td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</dl>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<div class="inline required field {{if .Err_Owner}}error{{end}}">
|
||||
<label>{{.i18n.Tr "repo.owner"}}</label>
|
||||
<div class="ui selection owner dropdown">
|
||||
<input type="hidden" id="uid" name="uid" value="{{.ContextUser.ID}}" required>
|
||||
<input type="hidden" id="user_id" name="user_id" value="{{.ContextUser.ID}}" required>
|
||||
<span class="text">
|
||||
<img class="ui mini image" src="{{.ContextUser.RelAvatarLink}}">
|
||||
{{.ContextUser.ShortName 20}}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<div class="inline required field {{if .Err_Owner}}error{{end}}">
|
||||
<label>{{.i18n.Tr "repo.owner"}}</label>
|
||||
<div class="ui selection owner dropdown">
|
||||
<input type="hidden" id="uid" name="uid" value="{{.ContextUser.ID}}" required>
|
||||
<input type="hidden" id="user_id" name="user_id" value="{{.ContextUser.ID}}" required>
|
||||
<span class="text">
|
||||
<img class="ui mini image" src="{{.ContextUser.RelAvatarLink}}">
|
||||
{{.ContextUser.ShortName 20}}
|
||||
|
||||
@@ -306,11 +306,11 @@
|
||||
</div>
|
||||
<div class="required field">
|
||||
<label for="repo_name">{{.i18n.Tr "repo.repo_name"}}</label>
|
||||
<input id="repo_name" name="repo_name" required>
|
||||
<input id="repo_name" name="repo_name" autocomplete="off" required>
|
||||
</div>
|
||||
<div class="required field">
|
||||
<label for="new_owner_name">{{.i18n.Tr "repo.settings.transfer_owner"}}</label>
|
||||
<input id="new_owner_name" name="new_owner_name" required>
|
||||
<input id="new_owner_name" name="new_owner_name" autocomplete="off" required>
|
||||
</div>
|
||||
|
||||
<div class="text right actions">
|
||||
@@ -344,7 +344,7 @@
|
||||
</div>
|
||||
<div class="required field">
|
||||
<label for="repo_name">{{.i18n.Tr "repo.repo_name"}}</label>
|
||||
<input id="repo_name" name="repo_name" required>
|
||||
<input id="repo_name" name="repo_name" autocomplete="off" required>
|
||||
</div>
|
||||
|
||||
<div class="text right actions">
|
||||
@@ -376,7 +376,7 @@
|
||||
</div>
|
||||
<div class="required field">
|
||||
<label for="repo_name">{{.i18n.Tr "repo.repo_name"}}</label>
|
||||
<input id="repo_name" name="repo_name" required>
|
||||
<input id="repo_name" name="repo_name" autocomplete="off" required>
|
||||
</div>
|
||||
|
||||
<div class="text right actions">
|
||||
|
||||
@@ -32,6 +32,26 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Delete -->
|
||||
<div class="seven wide column">
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input class="hidden" name="delete" type="checkbox" tabindex="0" {{if .Webhook.Delete}}checked{{end}}>
|
||||
<label>{{.i18n.Tr "repo.settings.event_delete"}}</label>
|
||||
<span class="help">{{.i18n.Tr "repo.settings.event_delete_desc"}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Fork -->
|
||||
<div class="seven wide column">
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input class="hidden" name="fork" type="checkbox" tabindex="0" {{if .Webhook.Fork}}checked{{end}}>
|
||||
<label>{{.i18n.Tr "repo.settings.event_fork"}}</label>
|
||||
<span class="help">{{.i18n.Tr "repo.settings.event_fork_desc"}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Push -->
|
||||
<div class="seven wide column">
|
||||
<div class="field">
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
<h4 class="ui top attached header">
|
||||
{{.i18n.Tr "home.my_repos"}} <span class="ui grey label">{{.ContextUser.NumRepos}}</span>
|
||||
<div class="ui right">
|
||||
<a class="poping up" href="{{AppSubUrl}}/repo/create" data-content="{{.i18n.Tr "new_repo"}}" data-variation="tiny inverted" data-position="left center">
|
||||
<a class="poping up" href="{{AppSubUrl}}/repo/create{{if .ContextUser.IsOrganization}}?org={{.ContextUser.ID}}{{end}}" data-content="{{.i18n.Tr "new_repo"}}" data-variation="tiny inverted" data-position="left center">
|
||||
<i class="plus icon"></i>
|
||||
<span class="sr-only">{{.i18n.Tr "new_repo"}}</span>
|
||||
</a>
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
<div class="{{if eq .GetOpType 5}}push news{{end}}">
|
||||
<p>
|
||||
<a href="{{AppSubUrl}}/{{.GetActUserName}}">{{.ShortActUserName}}</a>
|
||||
{{if eq .GetOpType 1}}
|
||||
<!-- Reference types to models/action.go -->
|
||||
{{if eq .GetOpType 1}}
|
||||
{{$.i18n.Tr "action.create_repo" .GetRepoLink .ShortRepoPath | Str2html}}
|
||||
{{else if eq .GetOpType 2}}
|
||||
{{$.i18n.Tr "action.rename_repo" .GetContent .GetRepoLink .ShortRepoPath | Str2html}}
|
||||
@@ -43,6 +44,15 @@
|
||||
{{else if eq .GetOpType 15}}
|
||||
{{ $index := index .GetIssueInfos 0}}
|
||||
{{$.i18n.Tr "action.reopen_pull_request" .GetRepoLink $index .ShortRepoPath | Str2html}}
|
||||
{{else if eq .GetOpType 16}}
|
||||
{{ $branchLink := .GetBranch | EscapePound}}
|
||||
{{$.i18n.Tr "action.create_branch" .GetRepoLink $branchLink .GetBranch .ShortRepoPath | Str2html}}
|
||||
{{else if eq .GetOpType 17}}
|
||||
{{$.i18n.Tr "action.delete_branch" .GetRepoLink .GetBranch .ShortRepoPath | Str2html}}
|
||||
{{else if eq .GetOpType 18}}
|
||||
{{$.i18n.Tr "action.delete_tag" .GetRepoLink .GetBranch .ShortRepoPath | Str2html}}
|
||||
{{else if eq .GetOpType 19}}
|
||||
{{$.i18n.Tr "action.fork_repo" .GetRepoLink .ShortRepoPath | Str2html}}
|
||||
{{end}}
|
||||
</p>
|
||||
{{if eq .GetOpType 5}}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<div class="ui five wide column">
|
||||
<div class="ui card">
|
||||
{{if eq .SignedUserName .Owner.Name}}
|
||||
<a class="image poping up" href="{{AppSubUrl}}/user/settings" id="profile-avatar" data-content="{{.i18n.Tr "user.change_avatar"}}" data-variation="inverted tiny" data-position="bottom center">
|
||||
<a class="image poping up" href="{{AppSubUrl}}/user/settings/avatar" id="profile-avatar" data-content="{{.i18n.Tr "user.change_avatar"}}" data-variation="inverted tiny" data-position="bottom center">
|
||||
<img src="{{.Owner.RelAvatarLink}}?s=290" title="{{.Owner.Name}}"/>
|
||||
</a>
|
||||
{{else}}
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
</div>
|
||||
<div class="required field {{if .Err_Email}}error{{end}}">
|
||||
<label for="email">{{.i18n.Tr "email"}}</label>
|
||||
<input id="email" name="email" value="{{.SignedUser.Email}}">
|
||||
<input id="email" name="email" value="{{.SignedUser.Email}}" required>
|
||||
</div>
|
||||
<div class="field {{if .Err_Website}}error{{end}}">
|
||||
<label for="website">{{.i18n.Tr "settings.website"}}</label>
|
||||
|
||||
2
vendor/github.com/gogits/go-gogs-client/gogs.go
generated
vendored
2
vendor/github.com/gogits/go-gogs-client/gogs.go
generated
vendored
@@ -14,7 +14,7 @@ import (
|
||||
)
|
||||
|
||||
func Version() string {
|
||||
return "0.12.6"
|
||||
return "0.12.7"
|
||||
}
|
||||
|
||||
// Client represents a Gogs API client.
|
||||
|
||||
52
vendor/github.com/gogits/go-gogs-client/repo_hook.go
generated
vendored
52
vendor/github.com/gogits/go-gogs-client/repo_hook.go
generated
vendored
@@ -91,6 +91,7 @@ type PayloadCommit struct {
|
||||
|
||||
var (
|
||||
_ Payloader = &CreatePayload{}
|
||||
_ Payloader = &DeletePayload{}
|
||||
_ Payloader = &PushPayload{}
|
||||
_ Payloader = &PullRequestPayload{}
|
||||
)
|
||||
@@ -103,10 +104,11 @@ var (
|
||||
// \/ \/ \/ \/
|
||||
|
||||
type CreatePayload struct {
|
||||
Ref string `json:"ref"`
|
||||
RefType string `json:"ref_type"`
|
||||
Repo *Repository `json:"repository"`
|
||||
Sender *User `json:"sender"`
|
||||
Ref string `json:"ref"`
|
||||
RefType string `json:"ref_type"`
|
||||
DefaultBranch string `json:"default_branch"`
|
||||
Repo *Repository `json:"repository"`
|
||||
Sender *User `json:"sender"`
|
||||
}
|
||||
|
||||
func (p *CreatePayload) JSONPayload() ([]byte, error) {
|
||||
@@ -133,6 +135,48 @@ func ParseCreateHook(raw []byte) (*CreatePayload, error) {
|
||||
return hook, nil
|
||||
}
|
||||
|
||||
// ________ .__ __
|
||||
// \______ \ ____ | | _____/ |_ ____
|
||||
// | | \_/ __ \| | _/ __ \ __\/ __ \
|
||||
// | ` \ ___/| |_\ ___/| | \ ___/
|
||||
// /_______ /\___ >____/\___ >__| \___ >
|
||||
// \/ \/ \/ \/
|
||||
|
||||
type PusherType string
|
||||
|
||||
const (
|
||||
PUSHER_TYPE_USER PusherType = "user"
|
||||
)
|
||||
|
||||
type DeletePayload struct {
|
||||
Ref string `json:"ref"`
|
||||
RefType string `json:"ref_type"`
|
||||
PusherType PusherType `json:"pusher_type"`
|
||||
Repo *Repository `json:"repository"`
|
||||
Sender *User `json:"sender"`
|
||||
}
|
||||
|
||||
func (p *DeletePayload) JSONPayload() ([]byte, error) {
|
||||
return json.MarshalIndent(p, "", " ")
|
||||
}
|
||||
|
||||
// ___________ __
|
||||
// \_ _____/__________| | __
|
||||
// | __)/ _ \_ __ \ |/ /
|
||||
// | \( <_> ) | \/ <
|
||||
// \___ / \____/|__| |__|_ \
|
||||
// \/ \/
|
||||
|
||||
type ForkPayload struct {
|
||||
Forkee *Repository `json:"forkee"`
|
||||
Repo *Repository `json:"repository"`
|
||||
Sender *User `json:"sender"`
|
||||
}
|
||||
|
||||
func (p *ForkPayload) JSONPayload() ([]byte, error) {
|
||||
return json.MarshalIndent(p, "", " ")
|
||||
}
|
||||
|
||||
// __________ .__
|
||||
// \______ \__ __ _____| |__
|
||||
// | ___/ | \/ ___/ | \
|
||||
|
||||
@@ -23,7 +23,9 @@ func init() {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if interactive {
|
||||
// While run as Windows service, it is not an interactive session,
|
||||
// but we don't want hook execute to be treated as service, e.g. gogs.exe hook pre-receive.
|
||||
if interactive || len(os.Getenv("SSH_ORIGINAL_COMMAND")) > 0 {
|
||||
return
|
||||
}
|
||||
go func() {
|
||||
4
vendor/golang.org/x/crypto/ssh/channel.go
generated
vendored
4
vendor/golang.org/x/crypto/ssh/channel.go
generated
vendored
@@ -461,8 +461,8 @@ func (m *mux) newChannel(chanType string, direction channelDirection, extraData
|
||||
pending: newBuffer(),
|
||||
extPending: newBuffer(),
|
||||
direction: direction,
|
||||
incomingRequests: make(chan *Request, 16),
|
||||
msg: make(chan interface{}, 16),
|
||||
incomingRequests: make(chan *Request, chanSize),
|
||||
msg: make(chan interface{}, chanSize),
|
||||
chanType: chanType,
|
||||
extraData: extraData,
|
||||
mux: m,
|
||||
|
||||
64
vendor/golang.org/x/crypto/ssh/cipher.go
generated
vendored
64
vendor/golang.org/x/crypto/ssh/cipher.go
generated
vendored
@@ -135,6 +135,7 @@ const prefixLen = 5
|
||||
type streamPacketCipher struct {
|
||||
mac hash.Hash
|
||||
cipher cipher.Stream
|
||||
etm bool
|
||||
|
||||
// The following members are to avoid per-packet allocations.
|
||||
prefix [prefixLen]byte
|
||||
@@ -150,7 +151,14 @@ func (s *streamPacketCipher) readPacket(seqNum uint32, r io.Reader) ([]byte, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s.cipher.XORKeyStream(s.prefix[:], s.prefix[:])
|
||||
var encryptedPaddingLength [1]byte
|
||||
if s.mac != nil && s.etm {
|
||||
copy(encryptedPaddingLength[:], s.prefix[4:5])
|
||||
s.cipher.XORKeyStream(s.prefix[4:5], s.prefix[4:5])
|
||||
} else {
|
||||
s.cipher.XORKeyStream(s.prefix[:], s.prefix[:])
|
||||
}
|
||||
|
||||
length := binary.BigEndian.Uint32(s.prefix[0:4])
|
||||
paddingLength := uint32(s.prefix[4])
|
||||
|
||||
@@ -159,7 +167,12 @@ func (s *streamPacketCipher) readPacket(seqNum uint32, r io.Reader) ([]byte, err
|
||||
s.mac.Reset()
|
||||
binary.BigEndian.PutUint32(s.seqNumBytes[:], seqNum)
|
||||
s.mac.Write(s.seqNumBytes[:])
|
||||
s.mac.Write(s.prefix[:])
|
||||
if s.etm {
|
||||
s.mac.Write(s.prefix[:4])
|
||||
s.mac.Write(encryptedPaddingLength[:])
|
||||
} else {
|
||||
s.mac.Write(s.prefix[:])
|
||||
}
|
||||
macSize = uint32(s.mac.Size())
|
||||
}
|
||||
|
||||
@@ -184,10 +197,17 @@ func (s *streamPacketCipher) readPacket(seqNum uint32, r io.Reader) ([]byte, err
|
||||
}
|
||||
mac := s.packetData[length-1:]
|
||||
data := s.packetData[:length-1]
|
||||
|
||||
if s.mac != nil && s.etm {
|
||||
s.mac.Write(data)
|
||||
}
|
||||
|
||||
s.cipher.XORKeyStream(data, data)
|
||||
|
||||
if s.mac != nil {
|
||||
s.mac.Write(data)
|
||||
if !s.etm {
|
||||
s.mac.Write(data)
|
||||
}
|
||||
s.macResult = s.mac.Sum(s.macResult[:0])
|
||||
if subtle.ConstantTimeCompare(s.macResult, mac) != 1 {
|
||||
return nil, errors.New("ssh: MAC failure")
|
||||
@@ -203,7 +223,13 @@ func (s *streamPacketCipher) writePacket(seqNum uint32, w io.Writer, rand io.Rea
|
||||
return errors.New("ssh: packet too large")
|
||||
}
|
||||
|
||||
paddingLength := packetSizeMultiple - (prefixLen+len(packet))%packetSizeMultiple
|
||||
aadlen := 0
|
||||
if s.mac != nil && s.etm {
|
||||
// packet length is not encrypted for EtM modes
|
||||
aadlen = 4
|
||||
}
|
||||
|
||||
paddingLength := packetSizeMultiple - (prefixLen+len(packet)-aadlen)%packetSizeMultiple
|
||||
if paddingLength < 4 {
|
||||
paddingLength += packetSizeMultiple
|
||||
}
|
||||
@@ -220,15 +246,37 @@ func (s *streamPacketCipher) writePacket(seqNum uint32, w io.Writer, rand io.Rea
|
||||
s.mac.Reset()
|
||||
binary.BigEndian.PutUint32(s.seqNumBytes[:], seqNum)
|
||||
s.mac.Write(s.seqNumBytes[:])
|
||||
|
||||
if s.etm {
|
||||
// For EtM algorithms, the packet length must stay unencrypted,
|
||||
// but the following data (padding length) must be encrypted
|
||||
s.cipher.XORKeyStream(s.prefix[4:5], s.prefix[4:5])
|
||||
}
|
||||
|
||||
s.mac.Write(s.prefix[:])
|
||||
|
||||
if !s.etm {
|
||||
// For non-EtM algorithms, the algorithm is applied on unencrypted data
|
||||
s.mac.Write(packet)
|
||||
s.mac.Write(padding)
|
||||
}
|
||||
}
|
||||
|
||||
if !(s.mac != nil && s.etm) {
|
||||
// For EtM algorithms, the padding length has already been encrypted
|
||||
// and the packet length must remain unencrypted
|
||||
s.cipher.XORKeyStream(s.prefix[:], s.prefix[:])
|
||||
}
|
||||
|
||||
s.cipher.XORKeyStream(packet, packet)
|
||||
s.cipher.XORKeyStream(padding, padding)
|
||||
|
||||
if s.mac != nil && s.etm {
|
||||
// For EtM algorithms, packet and padding must be encrypted
|
||||
s.mac.Write(packet)
|
||||
s.mac.Write(padding)
|
||||
}
|
||||
|
||||
s.cipher.XORKeyStream(s.prefix[:], s.prefix[:])
|
||||
s.cipher.XORKeyStream(packet, packet)
|
||||
s.cipher.XORKeyStream(padding, padding)
|
||||
|
||||
if _, err := w.Write(s.prefix[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
6
vendor/golang.org/x/crypto/ssh/client.go
generated
vendored
6
vendor/golang.org/x/crypto/ssh/client.go
generated
vendored
@@ -40,7 +40,7 @@ func (c *Client) HandleChannelOpen(channelType string) <-chan NewChannel {
|
||||
return nil
|
||||
}
|
||||
|
||||
ch = make(chan NewChannel, 16)
|
||||
ch = make(chan NewChannel, chanSize)
|
||||
c.channelHandlers[channelType] = ch
|
||||
return ch
|
||||
}
|
||||
@@ -97,13 +97,11 @@ func (c *connection) clientHandshake(dialAddress string, config *ClientConfig) e
|
||||
c.transport = newClientTransport(
|
||||
newTransport(c.sshConn.conn, config.Rand, true /* is client */),
|
||||
c.clientVersion, c.serverVersion, config, dialAddress, c.sshConn.RemoteAddr())
|
||||
if err := c.transport.requestInitialKeyChange(); err != nil {
|
||||
if err := c.transport.waitSession(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// We just did the key change, so the session ID is established.
|
||||
c.sessionID = c.transport.getSessionID()
|
||||
|
||||
return c.clientAuthenticate(config)
|
||||
}
|
||||
|
||||
|
||||
4
vendor/golang.org/x/crypto/ssh/client_auth.go
generated
vendored
4
vendor/golang.org/x/crypto/ssh/client_auth.go
generated
vendored
@@ -30,8 +30,10 @@ func (c *connection) clientAuthenticate(config *ClientConfig) error {
|
||||
// then any untried methods suggested by the server.
|
||||
tried := make(map[string]bool)
|
||||
var lastMethods []string
|
||||
|
||||
sessionID := c.transport.getSessionID()
|
||||
for auth := AuthMethod(new(noneAuth)); auth != nil; {
|
||||
ok, methods, err := auth.auth(c.transport.getSessionID(), config.User, c.transport, config.Rand)
|
||||
ok, methods, err := auth.auth(sessionID, config.User, c.transport, config.Rand)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
17
vendor/golang.org/x/crypto/ssh/common.go
generated
vendored
17
vendor/golang.org/x/crypto/ssh/common.go
generated
vendored
@@ -56,7 +56,7 @@ var supportedHostKeyAlgos = []string{
|
||||
// This is based on RFC 4253, section 6.4, but with hmac-md5 variants removed
|
||||
// because they have reached the end of their useful life.
|
||||
var supportedMACs = []string{
|
||||
"hmac-sha2-256", "hmac-sha1", "hmac-sha1-96",
|
||||
"hmac-sha2-256-etm@openssh.com", "hmac-sha2-256", "hmac-sha1", "hmac-sha1-96",
|
||||
}
|
||||
|
||||
var supportedCompressions = []string{compressionNone}
|
||||
@@ -104,6 +104,21 @@ type directionAlgorithms struct {
|
||||
Compression string
|
||||
}
|
||||
|
||||
// rekeyBytes returns a rekeying intervals in bytes.
|
||||
func (a *directionAlgorithms) rekeyBytes() int64 {
|
||||
// According to RFC4344 block ciphers should rekey after
|
||||
// 2^(BLOCKSIZE/4) blocks. For all AES flavors BLOCKSIZE is
|
||||
// 128.
|
||||
switch a.Cipher {
|
||||
case "aes128-ctr", "aes192-ctr", "aes256-ctr", gcmCipherID, aes128cbcID:
|
||||
return 16 * (1 << 32)
|
||||
|
||||
}
|
||||
|
||||
// For others, stick with RFC4253 recommendation to rekey after 1 Gb of data.
|
||||
return 1 << 30
|
||||
}
|
||||
|
||||
type algorithms struct {
|
||||
kex string
|
||||
hostKey string
|
||||
|
||||
435
vendor/golang.org/x/crypto/ssh/handshake.go
generated
vendored
435
vendor/golang.org/x/crypto/ssh/handshake.go
generated
vendored
@@ -19,6 +19,11 @@ import (
|
||||
// messages are wrong when using ECDH.
|
||||
const debugHandshake = false
|
||||
|
||||
// chanSize sets the amount of buffering SSH connections. This is
|
||||
// primarily for testing: setting chanSize=0 uncovers deadlocks more
|
||||
// quickly.
|
||||
const chanSize = 16
|
||||
|
||||
// keyingTransport is a packet based transport that supports key
|
||||
// changes. It need not be thread-safe. It should pass through
|
||||
// msgNewKeys in both directions.
|
||||
@@ -53,34 +58,58 @@ type handshakeTransport struct {
|
||||
incoming chan []byte
|
||||
readError error
|
||||
|
||||
mu sync.Mutex
|
||||
writeError error
|
||||
sentInitPacket []byte
|
||||
sentInitMsg *kexInitMsg
|
||||
pendingPackets [][]byte // Used when a key exchange is in progress.
|
||||
|
||||
// If the read loop wants to schedule a kex, it pings this
|
||||
// channel, and the write loop will send out a kex
|
||||
// message.
|
||||
requestKex chan struct{}
|
||||
|
||||
// If the other side requests or confirms a kex, its kexInit
|
||||
// packet is sent here for the write loop to find it.
|
||||
startKex chan *pendingKex
|
||||
|
||||
// data for host key checking
|
||||
hostKeyCallback func(hostname string, remote net.Addr, key PublicKey) error
|
||||
dialAddress string
|
||||
remoteAddr net.Addr
|
||||
|
||||
readSinceKex uint64
|
||||
// Algorithms agreed in the last key exchange.
|
||||
algorithms *algorithms
|
||||
|
||||
// Protects the writing side of the connection
|
||||
mu sync.Mutex
|
||||
cond *sync.Cond
|
||||
sentInitPacket []byte
|
||||
sentInitMsg *kexInitMsg
|
||||
writtenSinceKex uint64
|
||||
writeError error
|
||||
readPacketsLeft uint32
|
||||
readBytesLeft int64
|
||||
|
||||
writePacketsLeft uint32
|
||||
writeBytesLeft int64
|
||||
|
||||
// The session ID or nil if first kex did not complete yet.
|
||||
sessionID []byte
|
||||
}
|
||||
|
||||
type pendingKex struct {
|
||||
otherInit []byte
|
||||
done chan error
|
||||
}
|
||||
|
||||
func newHandshakeTransport(conn keyingTransport, config *Config, clientVersion, serverVersion []byte) *handshakeTransport {
|
||||
t := &handshakeTransport{
|
||||
conn: conn,
|
||||
serverVersion: serverVersion,
|
||||
clientVersion: clientVersion,
|
||||
incoming: make(chan []byte, 16),
|
||||
config: config,
|
||||
incoming: make(chan []byte, chanSize),
|
||||
requestKex: make(chan struct{}, 1),
|
||||
startKex: make(chan *pendingKex, 1),
|
||||
|
||||
config: config,
|
||||
}
|
||||
t.cond = sync.NewCond(&t.mu)
|
||||
|
||||
// We always start with a mandatory key exchange.
|
||||
t.requestKex <- struct{}{}
|
||||
return t
|
||||
}
|
||||
|
||||
@@ -95,6 +124,7 @@ func newClientTransport(conn keyingTransport, clientVersion, serverVersion []byt
|
||||
t.hostKeyAlgorithms = supportedHostKeyAlgos
|
||||
}
|
||||
go t.readLoop()
|
||||
go t.kexLoop()
|
||||
return t
|
||||
}
|
||||
|
||||
@@ -102,6 +132,7 @@ func newServerTransport(conn keyingTransport, clientVersion, serverVersion []byt
|
||||
t := newHandshakeTransport(conn, &config.Config, clientVersion, serverVersion)
|
||||
t.hostKeys = config.hostKeys
|
||||
go t.readLoop()
|
||||
go t.kexLoop()
|
||||
return t
|
||||
}
|
||||
|
||||
@@ -109,6 +140,20 @@ func (t *handshakeTransport) getSessionID() []byte {
|
||||
return t.sessionID
|
||||
}
|
||||
|
||||
// waitSession waits for the session to be established. This should be
|
||||
// the first thing to call after instantiating handshakeTransport.
|
||||
func (t *handshakeTransport) waitSession() error {
|
||||
p, err := t.readPacket()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if p[0] != msgNewKeys {
|
||||
return fmt.Errorf("ssh: first packet should be msgNewKeys")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *handshakeTransport) id() string {
|
||||
if len(t.hostKeys) > 0 {
|
||||
return "server"
|
||||
@@ -116,6 +161,20 @@ func (t *handshakeTransport) id() string {
|
||||
return "client"
|
||||
}
|
||||
|
||||
func (t *handshakeTransport) printPacket(p []byte, write bool) {
|
||||
action := "got"
|
||||
if write {
|
||||
action = "sent"
|
||||
}
|
||||
|
||||
if p[0] == msgChannelData || p[0] == msgChannelExtendedData {
|
||||
log.Printf("%s %s data (packet %d bytes)", t.id(), action, len(p))
|
||||
} else {
|
||||
msg, err := decode(p)
|
||||
log.Printf("%s %s %T %v (%v)", t.id(), action, msg, msg, err)
|
||||
}
|
||||
}
|
||||
|
||||
func (t *handshakeTransport) readPacket() ([]byte, error) {
|
||||
p, ok := <-t.incoming
|
||||
if !ok {
|
||||
@@ -125,8 +184,10 @@ func (t *handshakeTransport) readPacket() ([]byte, error) {
|
||||
}
|
||||
|
||||
func (t *handshakeTransport) readLoop() {
|
||||
first := true
|
||||
for {
|
||||
p, err := t.readOnePacket()
|
||||
p, err := t.readOnePacket(first)
|
||||
first = false
|
||||
if err != nil {
|
||||
t.readError = err
|
||||
close(t.incoming)
|
||||
@@ -138,67 +199,204 @@ func (t *handshakeTransport) readLoop() {
|
||||
t.incoming <- p
|
||||
}
|
||||
|
||||
// If we can't read, declare the writing part dead too.
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
if t.writeError == nil {
|
||||
t.writeError = t.readError
|
||||
}
|
||||
t.cond.Broadcast()
|
||||
// Stop writers too.
|
||||
t.recordWriteError(t.readError)
|
||||
|
||||
// Unblock the writer should it wait for this.
|
||||
close(t.startKex)
|
||||
|
||||
// Don't close t.requestKex; it's also written to from writePacket.
|
||||
}
|
||||
|
||||
func (t *handshakeTransport) readOnePacket() ([]byte, error) {
|
||||
if t.readSinceKex > t.config.RekeyThreshold {
|
||||
if err := t.requestKeyChange(); err != nil {
|
||||
return nil, err
|
||||
func (t *handshakeTransport) pushPacket(p []byte) error {
|
||||
if debugHandshake {
|
||||
t.printPacket(p, true)
|
||||
}
|
||||
return t.conn.writePacket(p)
|
||||
}
|
||||
|
||||
func (t *handshakeTransport) getWriteError() error {
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
return t.writeError
|
||||
}
|
||||
|
||||
func (t *handshakeTransport) recordWriteError(err error) {
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
if t.writeError == nil && err != nil {
|
||||
t.writeError = err
|
||||
}
|
||||
}
|
||||
|
||||
func (t *handshakeTransport) requestKeyExchange() {
|
||||
select {
|
||||
case t.requestKex <- struct{}{}:
|
||||
default:
|
||||
// something already requested a kex, so do nothing.
|
||||
}
|
||||
}
|
||||
|
||||
func (t *handshakeTransport) kexLoop() {
|
||||
|
||||
write:
|
||||
for t.getWriteError() == nil {
|
||||
var request *pendingKex
|
||||
var sent bool
|
||||
|
||||
for request == nil || !sent {
|
||||
var ok bool
|
||||
select {
|
||||
case request, ok = <-t.startKex:
|
||||
if !ok {
|
||||
break write
|
||||
}
|
||||
case <-t.requestKex:
|
||||
break
|
||||
}
|
||||
|
||||
if !sent {
|
||||
if err := t.sendKexInit(); err != nil {
|
||||
t.recordWriteError(err)
|
||||
break
|
||||
}
|
||||
sent = true
|
||||
}
|
||||
}
|
||||
|
||||
if err := t.getWriteError(); err != nil {
|
||||
if request != nil {
|
||||
request.done <- err
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
// We're not servicing t.requestKex, but that is OK:
|
||||
// we never block on sending to t.requestKex.
|
||||
|
||||
// We're not servicing t.startKex, but the remote end
|
||||
// has just sent us a kexInitMsg, so it can't send
|
||||
// another key change request, until we close the done
|
||||
// channel on the pendingKex request.
|
||||
|
||||
err := t.enterKeyExchange(request.otherInit)
|
||||
|
||||
t.mu.Lock()
|
||||
t.writeError = err
|
||||
t.sentInitPacket = nil
|
||||
t.sentInitMsg = nil
|
||||
t.writePacketsLeft = packetRekeyThreshold
|
||||
if t.config.RekeyThreshold > 0 {
|
||||
t.writeBytesLeft = int64(t.config.RekeyThreshold)
|
||||
} else if t.algorithms != nil {
|
||||
t.writeBytesLeft = t.algorithms.w.rekeyBytes()
|
||||
}
|
||||
|
||||
// we have completed the key exchange. Since the
|
||||
// reader is still blocked, it is safe to clear out
|
||||
// the requestKex channel. This avoids the situation
|
||||
// where: 1) we consumed our own request for the
|
||||
// initial kex, and 2) the kex from the remote side
|
||||
// caused another send on the requestKex channel,
|
||||
clear:
|
||||
for {
|
||||
select {
|
||||
case <-t.requestKex:
|
||||
//
|
||||
default:
|
||||
break clear
|
||||
}
|
||||
}
|
||||
|
||||
request.done <- t.writeError
|
||||
|
||||
// kex finished. Push packets that we received while
|
||||
// the kex was in progress. Don't look at t.startKex
|
||||
// and don't increment writtenSinceKex: if we trigger
|
||||
// another kex while we are still busy with the last
|
||||
// one, things will become very confusing.
|
||||
for _, p := range t.pendingPackets {
|
||||
t.writeError = t.pushPacket(p)
|
||||
if t.writeError != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
t.pendingPackets = t.pendingPackets[:0]
|
||||
t.mu.Unlock()
|
||||
}
|
||||
|
||||
// drain startKex channel. We don't service t.requestKex
|
||||
// because nobody does blocking sends there.
|
||||
go func() {
|
||||
for init := range t.startKex {
|
||||
init.done <- t.writeError
|
||||
}
|
||||
}()
|
||||
|
||||
// Unblock reader.
|
||||
t.conn.Close()
|
||||
}
|
||||
|
||||
// The protocol uses uint32 for packet counters, so we can't let them
|
||||
// reach 1<<32. We will actually read and write more packets than
|
||||
// this, though: the other side may send more packets, and after we
|
||||
// hit this limit on writing we will send a few more packets for the
|
||||
// key exchange itself.
|
||||
const packetRekeyThreshold = (1 << 31)
|
||||
|
||||
func (t *handshakeTransport) readOnePacket(first bool) ([]byte, error) {
|
||||
p, err := t.conn.readPacket()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
t.readSinceKex += uint64(len(p))
|
||||
if debugHandshake {
|
||||
if p[0] == msgChannelData || p[0] == msgChannelExtendedData {
|
||||
log.Printf("%s got data (packet %d bytes)", t.id(), len(p))
|
||||
} else {
|
||||
msg, err := decode(p)
|
||||
log.Printf("%s got %T %v (%v)", t.id(), msg, msg, err)
|
||||
}
|
||||
if t.readPacketsLeft > 0 {
|
||||
t.readPacketsLeft--
|
||||
} else {
|
||||
t.requestKeyExchange()
|
||||
}
|
||||
|
||||
if t.readBytesLeft > 0 {
|
||||
t.readBytesLeft -= int64(len(p))
|
||||
} else {
|
||||
t.requestKeyExchange()
|
||||
}
|
||||
|
||||
if debugHandshake {
|
||||
t.printPacket(p, false)
|
||||
}
|
||||
|
||||
if first && p[0] != msgKexInit {
|
||||
return nil, fmt.Errorf("ssh: first packet should be msgKexInit")
|
||||
}
|
||||
|
||||
if p[0] != msgKexInit {
|
||||
return p, nil
|
||||
}
|
||||
|
||||
t.mu.Lock()
|
||||
|
||||
firstKex := t.sessionID == nil
|
||||
|
||||
err = t.enterKeyExchangeLocked(p)
|
||||
if err != nil {
|
||||
// drop connection
|
||||
t.conn.Close()
|
||||
t.writeError = err
|
||||
kex := pendingKex{
|
||||
done: make(chan error, 1),
|
||||
otherInit: p,
|
||||
}
|
||||
t.startKex <- &kex
|
||||
err = <-kex.done
|
||||
|
||||
if debugHandshake {
|
||||
log.Printf("%s exited key exchange (first %v), err %v", t.id(), firstKex, err)
|
||||
}
|
||||
|
||||
// Unblock writers.
|
||||
t.sentInitMsg = nil
|
||||
t.sentInitPacket = nil
|
||||
t.cond.Broadcast()
|
||||
t.writtenSinceKex = 0
|
||||
t.mu.Unlock()
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
t.readSinceKex = 0
|
||||
t.readPacketsLeft = packetRekeyThreshold
|
||||
if t.config.RekeyThreshold > 0 {
|
||||
t.readBytesLeft = int64(t.config.RekeyThreshold)
|
||||
} else {
|
||||
t.readBytesLeft = t.algorithms.r.rekeyBytes()
|
||||
}
|
||||
|
||||
// By default, a key exchange is hidden from higher layers by
|
||||
// translating it into msgIgnore.
|
||||
@@ -213,61 +411,16 @@ func (t *handshakeTransport) readOnePacket() ([]byte, error) {
|
||||
return successPacket, nil
|
||||
}
|
||||
|
||||
// keyChangeCategory describes whether a key exchange is the first on a
|
||||
// connection, or a subsequent one.
|
||||
type keyChangeCategory bool
|
||||
|
||||
const (
|
||||
firstKeyExchange keyChangeCategory = true
|
||||
subsequentKeyExchange keyChangeCategory = false
|
||||
)
|
||||
|
||||
// sendKexInit sends a key change message, and returns the message
|
||||
// that was sent. After initiating the key change, all writes will be
|
||||
// blocked until the change is done, and a failed key change will
|
||||
// close the underlying transport. This function is safe for
|
||||
// concurrent use by multiple goroutines.
|
||||
func (t *handshakeTransport) sendKexInit(isFirst keyChangeCategory) error {
|
||||
var err error
|
||||
|
||||
// sendKexInit sends a key change message.
|
||||
func (t *handshakeTransport) sendKexInit() error {
|
||||
t.mu.Lock()
|
||||
// If this is the initial key change, but we already have a sessionID,
|
||||
// then do nothing because the key exchange has already completed
|
||||
// asynchronously.
|
||||
if !isFirst || t.sessionID == nil {
|
||||
_, _, err = t.sendKexInitLocked(isFirst)
|
||||
}
|
||||
t.mu.Unlock()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if isFirst {
|
||||
if packet, err := t.readPacket(); err != nil {
|
||||
return err
|
||||
} else if packet[0] != msgNewKeys {
|
||||
return unexpectedMessageError(msgNewKeys, packet[0])
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *handshakeTransport) requestInitialKeyChange() error {
|
||||
return t.sendKexInit(firstKeyExchange)
|
||||
}
|
||||
|
||||
func (t *handshakeTransport) requestKeyChange() error {
|
||||
return t.sendKexInit(subsequentKeyExchange)
|
||||
}
|
||||
|
||||
// sendKexInitLocked sends a key change message. t.mu must be locked
|
||||
// while this happens.
|
||||
func (t *handshakeTransport) sendKexInitLocked(isFirst keyChangeCategory) (*kexInitMsg, []byte, error) {
|
||||
// kexInits may be sent either in response to the other side,
|
||||
// or because our side wants to initiate a key change, so we
|
||||
// may have already sent a kexInit. In that case, don't send a
|
||||
// second kexInit.
|
||||
defer t.mu.Unlock()
|
||||
if t.sentInitMsg != nil {
|
||||
return t.sentInitMsg, t.sentInitPacket, nil
|
||||
// kexInits may be sent either in response to the other side,
|
||||
// or because our side wants to initiate a key change, so we
|
||||
// may have already sent a kexInit. In that case, don't send a
|
||||
// second kexInit.
|
||||
return nil
|
||||
}
|
||||
|
||||
msg := &kexInitMsg{
|
||||
@@ -295,53 +448,65 @@ func (t *handshakeTransport) sendKexInitLocked(isFirst keyChangeCategory) (*kexI
|
||||
packetCopy := make([]byte, len(packet))
|
||||
copy(packetCopy, packet)
|
||||
|
||||
if err := t.conn.writePacket(packetCopy); err != nil {
|
||||
return nil, nil, err
|
||||
if err := t.pushPacket(packetCopy); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
t.sentInitMsg = msg
|
||||
t.sentInitPacket = packet
|
||||
return msg, packet, nil
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *handshakeTransport) writePacket(p []byte) error {
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
|
||||
if t.writtenSinceKex > t.config.RekeyThreshold {
|
||||
t.sendKexInitLocked(subsequentKeyExchange)
|
||||
}
|
||||
for t.sentInitMsg != nil && t.writeError == nil {
|
||||
t.cond.Wait()
|
||||
}
|
||||
if t.writeError != nil {
|
||||
return t.writeError
|
||||
}
|
||||
t.writtenSinceKex += uint64(len(p))
|
||||
|
||||
switch p[0] {
|
||||
case msgKexInit:
|
||||
return errors.New("ssh: only handshakeTransport can send kexInit")
|
||||
case msgNewKeys:
|
||||
return errors.New("ssh: only handshakeTransport can send newKeys")
|
||||
default:
|
||||
return t.conn.writePacket(p)
|
||||
}
|
||||
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
if t.writeError != nil {
|
||||
return t.writeError
|
||||
}
|
||||
|
||||
if t.sentInitMsg != nil {
|
||||
// Copy the packet so the writer can reuse the buffer.
|
||||
cp := make([]byte, len(p))
|
||||
copy(cp, p)
|
||||
t.pendingPackets = append(t.pendingPackets, cp)
|
||||
return nil
|
||||
}
|
||||
|
||||
if t.writeBytesLeft > 0 {
|
||||
t.writeBytesLeft -= int64(len(p))
|
||||
} else {
|
||||
t.requestKeyExchange()
|
||||
}
|
||||
|
||||
if t.writePacketsLeft > 0 {
|
||||
t.writePacketsLeft--
|
||||
} else {
|
||||
t.requestKeyExchange()
|
||||
}
|
||||
|
||||
if err := t.pushPacket(p); err != nil {
|
||||
t.writeError = err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *handshakeTransport) Close() error {
|
||||
return t.conn.Close()
|
||||
}
|
||||
|
||||
// enterKeyExchange runs the key exchange. t.mu must be held while running this.
|
||||
func (t *handshakeTransport) enterKeyExchangeLocked(otherInitPacket []byte) error {
|
||||
func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error {
|
||||
if debugHandshake {
|
||||
log.Printf("%s entered key exchange", t.id())
|
||||
}
|
||||
myInit, myInitPacket, err := t.sendKexInitLocked(subsequentKeyExchange)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
otherInit := &kexInitMsg{}
|
||||
if err := Unmarshal(otherInitPacket, otherInit); err != nil {
|
||||
@@ -352,20 +517,20 @@ func (t *handshakeTransport) enterKeyExchangeLocked(otherInitPacket []byte) erro
|
||||
clientVersion: t.clientVersion,
|
||||
serverVersion: t.serverVersion,
|
||||
clientKexInit: otherInitPacket,
|
||||
serverKexInit: myInitPacket,
|
||||
serverKexInit: t.sentInitPacket,
|
||||
}
|
||||
|
||||
clientInit := otherInit
|
||||
serverInit := myInit
|
||||
serverInit := t.sentInitMsg
|
||||
if len(t.hostKeys) == 0 {
|
||||
clientInit = myInit
|
||||
serverInit = otherInit
|
||||
clientInit, serverInit = serverInit, clientInit
|
||||
|
||||
magics.clientKexInit = myInitPacket
|
||||
magics.clientKexInit = t.sentInitPacket
|
||||
magics.serverKexInit = otherInitPacket
|
||||
}
|
||||
|
||||
algs, err := findAgreedAlgorithms(clientInit, serverInit)
|
||||
var err error
|
||||
t.algorithms, err = findAgreedAlgorithms(clientInit, serverInit)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -388,16 +553,16 @@ func (t *handshakeTransport) enterKeyExchangeLocked(otherInitPacket []byte) erro
|
||||
}
|
||||
}
|
||||
|
||||
kex, ok := kexAlgoMap[algs.kex]
|
||||
kex, ok := kexAlgoMap[t.algorithms.kex]
|
||||
if !ok {
|
||||
return fmt.Errorf("ssh: unexpected key exchange algorithm %v", algs.kex)
|
||||
return fmt.Errorf("ssh: unexpected key exchange algorithm %v", t.algorithms.kex)
|
||||
}
|
||||
|
||||
var result *kexResult
|
||||
if len(t.hostKeys) > 0 {
|
||||
result, err = t.server(kex, algs, &magics)
|
||||
result, err = t.server(kex, t.algorithms, &magics)
|
||||
} else {
|
||||
result, err = t.client(kex, algs, &magics)
|
||||
result, err = t.client(kex, t.algorithms, &magics)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
@@ -409,7 +574,7 @@ func (t *handshakeTransport) enterKeyExchangeLocked(otherInitPacket []byte) erro
|
||||
}
|
||||
result.SessionID = t.sessionID
|
||||
|
||||
t.conn.prepareKeyChange(algs, result)
|
||||
t.conn.prepareKeyChange(t.algorithms, result)
|
||||
if err = t.conn.writePacket([]byte{msgNewKeys}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
6
vendor/golang.org/x/crypto/ssh/keys.go
generated
vendored
6
vendor/golang.org/x/crypto/ssh/keys.go
generated
vendored
@@ -798,8 +798,8 @@ func ParseDSAPrivateKey(der []byte) (*dsa.PrivateKey, error) {
|
||||
P *big.Int
|
||||
Q *big.Int
|
||||
G *big.Int
|
||||
Priv *big.Int
|
||||
Pub *big.Int
|
||||
Priv *big.Int
|
||||
}
|
||||
rest, err := asn1.Unmarshal(der, &k)
|
||||
if err != nil {
|
||||
@@ -816,9 +816,9 @@ func ParseDSAPrivateKey(der []byte) (*dsa.PrivateKey, error) {
|
||||
Q: k.Q,
|
||||
G: k.G,
|
||||
},
|
||||
Y: k.Priv,
|
||||
Y: k.Pub,
|
||||
},
|
||||
X: k.Pub,
|
||||
X: k.Priv,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
||||
10
vendor/golang.org/x/crypto/ssh/mac.go
generated
vendored
10
vendor/golang.org/x/crypto/ssh/mac.go
generated
vendored
@@ -15,6 +15,7 @@ import (
|
||||
|
||||
type macMode struct {
|
||||
keySize int
|
||||
etm bool
|
||||
new func(key []byte) hash.Hash
|
||||
}
|
||||
|
||||
@@ -45,13 +46,16 @@ func (t truncatingMAC) Size() int {
|
||||
func (t truncatingMAC) BlockSize() int { return t.hmac.BlockSize() }
|
||||
|
||||
var macModes = map[string]*macMode{
|
||||
"hmac-sha2-256": {32, func(key []byte) hash.Hash {
|
||||
"hmac-sha2-256-etm@openssh.com": {32, true, func(key []byte) hash.Hash {
|
||||
return hmac.New(sha256.New, key)
|
||||
}},
|
||||
"hmac-sha1": {20, func(key []byte) hash.Hash {
|
||||
"hmac-sha2-256": {32, false, func(key []byte) hash.Hash {
|
||||
return hmac.New(sha256.New, key)
|
||||
}},
|
||||
"hmac-sha1": {20, false, func(key []byte) hash.Hash {
|
||||
return hmac.New(sha1.New, key)
|
||||
}},
|
||||
"hmac-sha1-96": {20, func(key []byte) hash.Hash {
|
||||
"hmac-sha1-96": {20, false, func(key []byte) hash.Hash {
|
||||
return truncatingMAC{12, hmac.New(sha1.New, key)}
|
||||
}},
|
||||
}
|
||||
|
||||
4
vendor/golang.org/x/crypto/ssh/mux.go
generated
vendored
4
vendor/golang.org/x/crypto/ssh/mux.go
generated
vendored
@@ -116,9 +116,9 @@ func (m *mux) Wait() error {
|
||||
func newMux(p packetConn) *mux {
|
||||
m := &mux{
|
||||
conn: p,
|
||||
incomingChannels: make(chan NewChannel, 16),
|
||||
incomingChannels: make(chan NewChannel, chanSize),
|
||||
globalResponses: make(chan interface{}, 1),
|
||||
incomingRequests: make(chan *Request, 16),
|
||||
incomingRequests: make(chan *Request, chanSize),
|
||||
errCond: newCond(),
|
||||
}
|
||||
if debugMux {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user