mirror of
https://github.com/go-gitea/gitea.git
synced 2026-10-06 21:07:06 +02:00
#1487 Readme Template
This commit is contained in:
1 parent
46bee50e45
commit
bb3b90fcd6
17 files changed
+791
-634
No files matched your search
@@ -424,6 +424,15 @@
|
|||||||
"strictMath": 0,
|
"strictMath": 0,
|
||||||
"strictUnits": 0
|
"strictUnits": 0
|
||||||
},
|
},
|
||||||
|
"\/public\/ng\/css\/font-awesome.min.css": {
|
||||||
|
"fileType": 16,
|
||||||
|
"ignore": 0,
|
||||||
|
"ignoreWasSetByUser": 0,
|
||||||
|
"inputAbbreviatedPath": "\/public\/ng\/css\/font-awesome.min.css",
|
||||||
|
"outputAbbreviatedPath": "No Output Path",
|
||||||
|
"outputPathIsOutsideProject": 0,
|
||||||
|
"outputPathIsSetByUser": 0
|
||||||
|
},
|
||||||
"\/public\/ng\/css\/gogs.css": {
|
"\/public\/ng\/css\/gogs.css": {
|
||||||
"fileType": 16,
|
"fileType": 16,
|
||||||
"ignore": 1,
|
"ignore": 1,
|
||||||
|
|||||||
+110
-82
@@ -5,6 +5,7 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"html/template"
|
"html/template"
|
||||||
@@ -403,7 +404,12 @@ func MirrorRepository(repoId int64, userName, repoName, repoPath, url string) er
|
|||||||
|
|
||||||
// MigrateRepository migrates a existing repository from other project hosting.
|
// MigrateRepository migrates a existing repository from other project hosting.
|
||||||
func MigrateRepository(u *User, name, desc string, private, mirror bool, url string) (*Repository, error) {
|
func MigrateRepository(u *User, name, desc string, private, mirror bool, url string) (*Repository, error) {
|
||||||
repo, err := CreateRepository(u, name, desc, "", "", private, mirror, false)
|
repo, err := CreateRepository(u, CreateRepoOptions{
|
||||||
|
Name: name,
|
||||||
|
Description: desc,
|
||||||
|
IsPrivate: private,
|
||||||
|
IsMirror: mirror,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -488,8 +494,89 @@ func createUpdateHook(repoPath string) error {
|
|||||||
[]byte(fmt.Sprintf(_TPL_UPDATE_HOOK, setting.ScriptType, "\""+appPath+"\"", setting.CustomConf)), 0777)
|
[]byte(fmt.Sprintf(_TPL_UPDATE_HOOK, setting.ScriptType, "\""+appPath+"\"", setting.CustomConf)), 0777)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type CreateRepoOptions struct {
|
||||||
|
Name string
|
||||||
|
Description string
|
||||||
|
Gitignores string
|
||||||
|
License string
|
||||||
|
Readme string
|
||||||
|
IsPrivate bool
|
||||||
|
IsMirror bool
|
||||||
|
AutoInit bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func getRepoInitFile(tp, name string) ([]byte, error) {
|
||||||
|
relPath := path.Join("conf", tp, name)
|
||||||
|
|
||||||
|
// Use custom file when available.
|
||||||
|
customPath := path.Join(setting.CustomPath, relPath)
|
||||||
|
if com.IsFile(customPath) {
|
||||||
|
return ioutil.ReadFile(customPath)
|
||||||
|
}
|
||||||
|
return bindata.Asset(relPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
func prepareRepoCommit(repo *Repository, tmpDir, repoPath string, opts CreateRepoOptions) error {
|
||||||
|
// Clone to temprory path and do the init commit.
|
||||||
|
_, stderr, err := process.Exec(
|
||||||
|
fmt.Sprintf("initRepository(git clone): %s", repoPath), "git", "clone", repoPath, tmpDir)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("git clone: %v - %s", err, stderr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// README
|
||||||
|
data, err := getRepoInitFile("readme", opts.Readme)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("getRepoInitFile[%s]: %v", opts.Readme, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
match := map[string]string{
|
||||||
|
"Name": repo.Name,
|
||||||
|
"Description": repo.Description,
|
||||||
|
}
|
||||||
|
if err = ioutil.WriteFile(filepath.Join(tmpDir, "README.md"),
|
||||||
|
[]byte(com.Expand(string(data), match)), 0644); err != nil {
|
||||||
|
return fmt.Errorf("write README.md: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// .gitignore
|
||||||
|
if len(opts.Gitignores) > 0 {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
names := strings.Split(opts.Gitignores, ",")
|
||||||
|
for _, name := range names {
|
||||||
|
data, err = getRepoInitFile("gitignore", name)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("getRepoInitFile[%s]: %v", name, err)
|
||||||
|
}
|
||||||
|
buf.WriteString("# ---> " + name + "\n")
|
||||||
|
buf.Write(data)
|
||||||
|
buf.WriteString("\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
if buf.Len() > 0 {
|
||||||
|
if err = ioutil.WriteFile(filepath.Join(tmpDir, ".gitignore"), buf.Bytes(), 0644); err != nil {
|
||||||
|
return fmt.Errorf("write .gitignore: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// LICENSE
|
||||||
|
if len(opts.License) > 0 {
|
||||||
|
data, err = getRepoInitFile("license", opts.License)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("getRepoInitFile[%s]: %v", opts.License, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = ioutil.WriteFile(filepath.Join(tmpDir, "LICENSE"), data, 0644); err != nil {
|
||||||
|
return fmt.Errorf("write LICENSE: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// InitRepository initializes README and .gitignore if needed.
|
// InitRepository initializes README and .gitignore if needed.
|
||||||
func initRepository(e Engine, repoPath string, u *User, repo *Repository, initReadme bool, repoLang, license string) error {
|
func initRepository(e Engine, repoPath string, u *User, repo *Repository, opts CreateRepoOptions) error {
|
||||||
// Somehow the directory could exist.
|
// Somehow the directory could exist.
|
||||||
if com.IsExist(repoPath) {
|
if com.IsExist(repoPath) {
|
||||||
return fmt.Errorf("initRepository: path already exists: %s", repoPath)
|
return fmt.Errorf("initRepository: path already exists: %s", repoPath)
|
||||||
@@ -498,83 +585,32 @@ func initRepository(e Engine, repoPath string, u *User, repo *Repository, initRe
|
|||||||
// Init bare new repository.
|
// Init bare new repository.
|
||||||
os.MkdirAll(repoPath, os.ModePerm)
|
os.MkdirAll(repoPath, os.ModePerm)
|
||||||
_, stderr, err := process.ExecDir(-1, repoPath,
|
_, stderr, err := process.ExecDir(-1, repoPath,
|
||||||
fmt.Sprintf("initRepository(git init --bare): %s", repoPath),
|
fmt.Sprintf("initRepository(git init --bare): %s", repoPath), "git", "init", "--bare")
|
||||||
"git", "init", "--bare")
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("git init --bare: %s", err)
|
return fmt.Errorf("git init --bare: %v - %s", err, stderr)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := createUpdateHook(repoPath); err != nil {
|
if err := createUpdateHook(repoPath); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize repository according to user's choice.
|
|
||||||
fileName := map[string]string{}
|
|
||||||
if initReadme {
|
|
||||||
fileName["readme"] = "README.md"
|
|
||||||
}
|
|
||||||
if repoLang != "" {
|
|
||||||
fileName["gitign"] = ".gitignore"
|
|
||||||
}
|
|
||||||
if license != "" {
|
|
||||||
fileName["license"] = "LICENSE"
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clone to temprory path and do the init commit.
|
|
||||||
tmpDir := filepath.Join(os.TempDir(), com.ToStr(time.Now().Nanosecond()))
|
tmpDir := filepath.Join(os.TempDir(), com.ToStr(time.Now().Nanosecond()))
|
||||||
os.MkdirAll(tmpDir, os.ModePerm)
|
|
||||||
defer os.RemoveAll(tmpDir)
|
|
||||||
|
|
||||||
_, stderr, err = process.Exec(
|
// Initialize repository according to user's choice.
|
||||||
fmt.Sprintf("initRepository(git clone): %s", repoPath),
|
if opts.AutoInit {
|
||||||
"git", "clone", repoPath, tmpDir)
|
os.MkdirAll(tmpDir, os.ModePerm)
|
||||||
if err != nil {
|
defer os.RemoveAll(tmpDir)
|
||||||
return errors.New("git clone: " + stderr)
|
|
||||||
}
|
|
||||||
|
|
||||||
// README
|
if err = prepareRepoCommit(repo, tmpDir, repoPath, opts); err != nil {
|
||||||
if initReadme {
|
return fmt.Errorf("prepareRepoCommit: %v", err)
|
||||||
defaultReadme := repo.Name + "\n" + strings.Repeat("=",
|
|
||||||
utf8.RuneCountInString(repo.Name)) + "\n\n" + repo.Description
|
|
||||||
if err := ioutil.WriteFile(filepath.Join(tmpDir, fileName["readme"]),
|
|
||||||
[]byte(defaultReadme), 0644); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: following two can be merged.
|
// Apply changes and commit.
|
||||||
|
if err = initRepoCommit(tmpDir, u.NewGitSig()); err != nil {
|
||||||
// .gitignore
|
return fmt.Errorf("initRepoCommit: %v", err)
|
||||||
// Copy custom file when available.
|
|
||||||
customPath := path.Join(setting.CustomPath, "conf/gitignore", repoLang)
|
|
||||||
targetPath := path.Join(tmpDir, fileName["gitign"])
|
|
||||||
if com.IsFile(customPath) {
|
|
||||||
if err := com.Copy(customPath, targetPath); err != nil {
|
|
||||||
return fmt.Errorf("copy gitignore: %v", err)
|
|
||||||
}
|
|
||||||
} else if com.IsSliceContainsStr(Gitignores, repoLang) {
|
|
||||||
if err = ioutil.WriteFile(targetPath,
|
|
||||||
bindata.MustAsset(path.Join("conf/gitignore", repoLang)), 0644); err != nil {
|
|
||||||
return fmt.Errorf("generate gitignore: %v", err)
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
delete(fileName, "gitign")
|
repo.IsBare = true
|
||||||
}
|
|
||||||
|
|
||||||
// LICENSE
|
|
||||||
customPath = path.Join(setting.CustomPath, "conf/license", license)
|
|
||||||
targetPath = path.Join(tmpDir, fileName["license"])
|
|
||||||
if com.IsFile(customPath) {
|
|
||||||
if err = com.Copy(customPath, targetPath); err != nil {
|
|
||||||
return fmt.Errorf("copy license: %v", err)
|
|
||||||
}
|
|
||||||
} else if com.IsSliceContainsStr(Licenses, license) {
|
|
||||||
if err = ioutil.WriteFile(targetPath,
|
|
||||||
bindata.MustAsset(path.Join("conf/license", license)), 0644); err != nil {
|
|
||||||
return fmt.Errorf("generate license: %v", err)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
delete(fileName, "license")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Re-fetch the repository from database before updating it (else it would
|
// Re-fetch the repository from database before updating it (else it would
|
||||||
@@ -582,21 +618,13 @@ func initRepository(e Engine, repoPath string, u *User, repo *Repository, initRe
|
|||||||
if repo, err = getRepositoryByID(e, repo.ID); err != nil {
|
if repo, err = getRepositoryByID(e, repo.ID); err != nil {
|
||||||
return fmt.Errorf("getRepositoryByID: %v", err)
|
return fmt.Errorf("getRepositoryByID: %v", err)
|
||||||
}
|
}
|
||||||
if len(fileName) == 0 {
|
|
||||||
repo.IsBare = true
|
|
||||||
}
|
|
||||||
repo.DefaultBranch = "master"
|
repo.DefaultBranch = "master"
|
||||||
if err = updateRepository(e, repo, false); err != nil {
|
if err = updateRepository(e, repo, false); err != nil {
|
||||||
return fmt.Errorf("updateRepository: %v", err)
|
return fmt.Errorf("updateRepository: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ignore init process if user choose not to.
|
return nil
|
||||||
if len(fileName) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply changes and commit.
|
|
||||||
return initRepoCommit(tmpDir, u.NewGitSig())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func createRepository(e *xorm.Session, u *User, repo *Repository) (err error) {
|
func createRepository(e *xorm.Session, u *User, repo *Repository) (err error) {
|
||||||
@@ -642,14 +670,14 @@ func createRepository(e *xorm.Session, u *User, repo *Repository) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CreateRepository creates a repository for given user or organization.
|
// CreateRepository creates a repository for given user or organization.
|
||||||
func CreateRepository(u *User, name, desc, lang, license string, isPrivate, isMirror, initReadme bool) (_ *Repository, err error) {
|
func CreateRepository(u *User, opts CreateRepoOptions) (_ *Repository, err error) {
|
||||||
repo := &Repository{
|
repo := &Repository{
|
||||||
OwnerID: u.Id,
|
OwnerID: u.Id,
|
||||||
Owner: u,
|
Owner: u,
|
||||||
Name: name,
|
Name: opts.Name,
|
||||||
LowerName: strings.ToLower(name),
|
LowerName: strings.ToLower(opts.Name),
|
||||||
Description: desc,
|
Description: opts.Description,
|
||||||
IsPrivate: isPrivate,
|
IsPrivate: opts.IsPrivate,
|
||||||
}
|
}
|
||||||
|
|
||||||
sess := x.NewSession()
|
sess := x.NewSession()
|
||||||
@@ -663,9 +691,9 @@ func CreateRepository(u *User, name, desc, lang, license string, isPrivate, isMi
|
|||||||
}
|
}
|
||||||
|
|
||||||
// No need for init mirror.
|
// No need for init mirror.
|
||||||
if !isMirror {
|
if !opts.IsMirror {
|
||||||
repoPath := RepoPath(u.Name, repo.Name)
|
repoPath := RepoPath(u.Name, repo.Name)
|
||||||
if err = initRepository(sess, repoPath, u, repo, initReadme, lang, license); err != nil {
|
if err = initRepository(sess, repoPath, u, repo, opts); err != nil {
|
||||||
if err2 := os.RemoveAll(repoPath); err2 != nil {
|
if err2 := os.RemoveAll(repoPath); err2 != nil {
|
||||||
log.Error(4, "initRepository: %v", err)
|
log.Error(4, "initRepository: %v", err)
|
||||||
return nil, fmt.Errorf(
|
return nil, fmt.Errorf(
|
||||||
|
|||||||
@@ -194,6 +194,12 @@ func GetMaxSize(field reflect.StructField) string {
|
|||||||
return getSize(field, "MaxSize(")
|
return getSize(field, "MaxSize(")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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 {
|
func validate(errs binding.Errors, data map[string]interface{}, f Form, l macaron.Locale) binding.Errors {
|
||||||
if errs.Len() == 0 {
|
if errs.Len() == 0 {
|
||||||
return errs
|
return errs
|
||||||
|
|||||||
+10
-11
@@ -16,19 +16,15 @@ import (
|
|||||||
// |____|_ /_______ / |____| \_______ /_______ /|___| |____| \_______ /____|_ // ______|
|
// |____|_ /_______ / |____| \_______ /_______ /|___| |____| \_______ /____|_ // ______|
|
||||||
// \/ \/ \/ \/ \/ \/ \/
|
// \/ \/ \/ \/ \/ \/ \/
|
||||||
|
|
||||||
type RepoForm struct {
|
type CreateRepoForm struct {
|
||||||
Uid int64 `binding:"Required"`
|
Uid int64 `binding:"Required"`
|
||||||
RepoName string `binding:"Required;AlphaDashDot;MaxSize(100)"`
|
RepoName string `binding:"Required;AlphaDashDot;MaxSize(100)"`
|
||||||
Private bool
|
Private bool
|
||||||
Description string `binding:"MaxSize(255)"`
|
Description string `binding:"MaxSize(255)"`
|
||||||
}
|
AutoInit bool
|
||||||
|
Gitignores string
|
||||||
type CreateRepoForm struct {
|
License string
|
||||||
RepoForm
|
Readme string
|
||||||
AutoInit bool
|
|
||||||
Gitignores string
|
|
||||||
License string
|
|
||||||
Readme string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *CreateRepoForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
func (f *CreateRepoForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||||
@@ -39,8 +35,11 @@ type MigrateRepoForm struct {
|
|||||||
CloneAddr string `binding:"Required"`
|
CloneAddr string `binding:"Required"`
|
||||||
AuthUsername string
|
AuthUsername string
|
||||||
AuthPassword string
|
AuthPassword string
|
||||||
RepoForm
|
Mirror bool
|
||||||
Mirror bool
|
Uid int64 `binding:"Required"`
|
||||||
|
RepoName string `binding:"Required;AlphaDashDot;MaxSize(100)"`
|
||||||
|
Private bool
|
||||||
|
Description string `binding:"MaxSize(255)"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *MigrateRepoForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
func (f *MigrateRepoForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||||
|
|||||||
Vendored
+4
@@ -0,0 +1,4 @@
|
|||||||
|
/*!
|
||||||
|
* Font Awesome 4.4.0 by @davegandy - http://fontawesome.io - @fontawesome
|
||||||
|
* License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)
|
||||||
|
*/@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.4.0');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.4.0') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff2?v=4.4.0') format('woff2'),url('../fonts/fontawesome-webfont.woff?v=4.4.0') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.4.0') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.4.0#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1);-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1);-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-remove:before,.fa-close:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{conteLine truncated
|
||||||
@@ -284,7 +284,7 @@ img.avatar-100 {
|
|||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
line-height: 1.6;
|
line-height: 1.6;
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
padding: 0 2em 2em !important;
|
padding: 5px 2em 2em !important;
|
||||||
}
|
}
|
||||||
.markdown > *:first-child {
|
.markdown > *:first-child {
|
||||||
margin-top: 0 !important;
|
margin-top: 0 !important;
|
||||||
|
|||||||
Binary file not shown.
Executable → Regular
BIN
Binary file not shown.
Executable → Regular
+601
-465
File diff suppressed because it is too large.
Load diff
|
Before Width: | Height: | Size: 248 KiB After Width: | Height: | Size: 348 KiB |
Executable → Regular
BIN
Binary file not shown.
Executable → Regular
BIN
Binary file not shown.
Binary file not shown.
@@ -4,7 +4,7 @@
|
|||||||
font-size:16px;
|
font-size:16px;
|
||||||
line-height:1.6;
|
line-height:1.6;
|
||||||
word-wrap:break-word;
|
word-wrap:break-word;
|
||||||
padding: 0 2em 2em !important;
|
padding: 5px 2em 2em !important;
|
||||||
|
|
||||||
>*:first-child {
|
>*:first-child {
|
||||||
margin-top:0 !important;
|
margin-top:0 !important;
|
||||||
|
|||||||
@@ -101,8 +101,15 @@ func SearchRepos(ctx *middleware.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func createRepo(ctx *middleware.Context, owner *models.User, opt api.CreateRepoOption) {
|
func createRepo(ctx *middleware.Context, owner *models.User, opt api.CreateRepoOption) {
|
||||||
repo, err := models.CreateRepository(owner, opt.Name, opt.Description,
|
repo, err := models.CreateRepository(owner, models.CreateRepoOptions{
|
||||||
opt.Gitignore, opt.License, opt.Private, false, opt.AutoInit)
|
Name: opt.Name,
|
||||||
|
Description: opt.Description,
|
||||||
|
Gitignores: opt.Gitignore,
|
||||||
|
License: opt.License,
|
||||||
|
// Readme: form.Readme,
|
||||||
|
IsPrivate: opt.Private,
|
||||||
|
AutoInit: opt.AutoInit,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if models.IsErrRepoAlreadyExist(err) ||
|
if models.IsErrRepoAlreadyExist(err) ||
|
||||||
models.IsErrNameReserved(err) ||
|
models.IsErrNameReserved(err) ||
|
||||||
|
|||||||
+37
-69
@@ -28,6 +28,12 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func checkContextUser(ctx *middleware.Context, uid int64) *models.User {
|
func checkContextUser(ctx *middleware.Context, uid int64) *models.User {
|
||||||
|
if err := ctx.User.GetOrganizations(); err != nil {
|
||||||
|
ctx.Handle(500, "GetOrganizations", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
ctx.Data["Orgs"] = ctx.User.Orgs
|
||||||
|
|
||||||
// Not equal means current user is an organization.
|
// Not equal means current user is an organization.
|
||||||
if uid == ctx.User.Id || uid == 0 {
|
if uid == ctx.User.Id || uid == 0 {
|
||||||
return ctx.User
|
return ctx.User
|
||||||
@@ -41,7 +47,10 @@ func checkContextUser(ctx *middleware.Context, uid int64) *models.User {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Handle(500, "checkContextUser", fmt.Errorf("GetUserById(%d): %v", uid, err))
|
ctx.Handle(500, "checkContextUser", fmt.Errorf("GetUserById(%d): %v", uid, err))
|
||||||
return nil
|
return nil
|
||||||
} else if !org.IsOrganization() {
|
}
|
||||||
|
|
||||||
|
// Check ownership of organization.
|
||||||
|
if !org.IsOrganization() || !org.IsOwnedBy(ctx.User.Id) {
|
||||||
ctx.Error(403)
|
ctx.Error(403)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -63,15 +72,25 @@ func Create(ctx *middleware.Context) {
|
|||||||
}
|
}
|
||||||
ctx.Data["ContextUser"] = ctxUser
|
ctx.Data["ContextUser"] = ctxUser
|
||||||
|
|
||||||
if err := ctx.User.GetOrganizations(); err != nil {
|
|
||||||
ctx.Handle(500, "GetOrganizations", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ctx.Data["Orgs"] = ctx.User.Orgs
|
|
||||||
|
|
||||||
ctx.HTML(200, CREATE)
|
ctx.HTML(200, CREATE)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func handleCreateError(ctx *middleware.Context, err error, name string, tpl base.TplName, form interface{}) {
|
||||||
|
switch {
|
||||||
|
case models.IsErrRepoAlreadyExist(err):
|
||||||
|
ctx.Data["Err_RepoName"] = true
|
||||||
|
ctx.RenderWithErr(ctx.Tr("form.repo_name_been_taken"), tpl, form)
|
||||||
|
case models.IsErrNameReserved(err):
|
||||||
|
ctx.Data["Err_RepoName"] = true
|
||||||
|
ctx.RenderWithErr(ctx.Tr("repo.form.name_reserved", err.(models.ErrNameReserved).Name), tpl, form)
|
||||||
|
case models.IsErrNamePatternNotAllowed(err):
|
||||||
|
ctx.Data["Err_RepoName"] = true
|
||||||
|
ctx.RenderWithErr(ctx.Tr("repo.form.name_pattern_not_allowed", err.(models.ErrNamePatternNotAllowed).Pattern), tpl, form)
|
||||||
|
default:
|
||||||
|
ctx.Handle(500, name, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func CreatePost(ctx *middleware.Context, form auth.CreateRepoForm) {
|
func CreatePost(ctx *middleware.Context, form auth.CreateRepoForm) {
|
||||||
ctx.Data["Title"] = ctx.Tr("new_repo")
|
ctx.Data["Title"] = ctx.Tr("new_repo")
|
||||||
|
|
||||||
@@ -85,27 +104,20 @@ func CreatePost(ctx *middleware.Context, form auth.CreateRepoForm) {
|
|||||||
}
|
}
|
||||||
ctx.Data["ContextUser"] = ctxUser
|
ctx.Data["ContextUser"] = ctxUser
|
||||||
|
|
||||||
if err := ctx.User.GetOrganizations(); err != nil {
|
|
||||||
ctx.Handle(500, "GetOrganizations", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ctx.Data["Orgs"] = ctx.User.Orgs
|
|
||||||
|
|
||||||
if ctx.HasError() {
|
if ctx.HasError() {
|
||||||
ctx.HTML(200, CREATE)
|
ctx.HTML(200, CREATE)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if ctxUser.IsOrganization() {
|
repo, err := models.CreateRepository(ctxUser, models.CreateRepoOptions{
|
||||||
// Check ownership of organization.
|
Name: form.RepoName,
|
||||||
if !ctxUser.IsOwnedBy(ctx.User.Id) {
|
Description: form.Description,
|
||||||
ctx.Error(403)
|
Gitignores: form.Gitignores,
|
||||||
return
|
License: form.License,
|
||||||
}
|
Readme: form.Readme,
|
||||||
}
|
IsPrivate: form.Private,
|
||||||
|
AutoInit: form.AutoInit,
|
||||||
repo, err := models.CreateRepository(ctxUser, form.RepoName, form.Description,
|
})
|
||||||
form.Gitignores, form.License, form.Private, false, form.AutoInit)
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
log.Trace("Repository created: %s/%s", ctxUser.Name, repo.Name)
|
log.Trace("Repository created: %s/%s", ctxUser.Name, repo.Name)
|
||||||
ctx.Redirect(setting.AppSubUrl + "/" + ctxUser.Name + "/" + repo.Name)
|
ctx.Redirect(setting.AppSubUrl + "/" + ctxUser.Name + "/" + repo.Name)
|
||||||
@@ -118,19 +130,7 @@ func CreatePost(ctx *middleware.Context, form auth.CreateRepoForm) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch {
|
handleCreateError(ctx, err, "CreatePost", CREATE, &form)
|
||||||
case models.IsErrRepoAlreadyExist(err):
|
|
||||||
ctx.Data["Err_RepoName"] = true
|
|
||||||
ctx.RenderWithErr(ctx.Tr("form.repo_name_been_taken"), CREATE, &form)
|
|
||||||
case models.IsErrNameReserved(err):
|
|
||||||
ctx.Data["Err_RepoName"] = true
|
|
||||||
ctx.RenderWithErr(ctx.Tr("repo.form.name_reserved", err.(models.ErrNameReserved).Name), CREATE, &form)
|
|
||||||
case models.IsErrNamePatternNotAllowed(err):
|
|
||||||
ctx.Data["Err_RepoName"] = true
|
|
||||||
ctx.RenderWithErr(ctx.Tr("repo.form.name_pattern_not_allowed", err.(models.ErrNamePatternNotAllowed).Pattern), CREATE, &form)
|
|
||||||
default:
|
|
||||||
ctx.Handle(500, "CreatePost", err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Migrate(ctx *middleware.Context) {
|
func Migrate(ctx *middleware.Context) {
|
||||||
@@ -142,12 +142,6 @@ func Migrate(ctx *middleware.Context) {
|
|||||||
}
|
}
|
||||||
ctx.Data["ContextUser"] = ctxUser
|
ctx.Data["ContextUser"] = ctxUser
|
||||||
|
|
||||||
if err := ctx.User.GetOrganizations(); err != nil {
|
|
||||||
ctx.Handle(500, "GetOrganizations", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ctx.Data["Orgs"] = ctx.User.Orgs
|
|
||||||
|
|
||||||
ctx.HTML(200, MIGRATE)
|
ctx.HTML(200, MIGRATE)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,25 +154,11 @@ func MigratePost(ctx *middleware.Context, form auth.MigrateRepoForm) {
|
|||||||
}
|
}
|
||||||
ctx.Data["ContextUser"] = ctxUser
|
ctx.Data["ContextUser"] = ctxUser
|
||||||
|
|
||||||
if err := ctx.User.GetOrganizations(); err != nil {
|
|
||||||
ctx.Handle(500, "GetOrganizations", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ctx.Data["Orgs"] = ctx.User.Orgs
|
|
||||||
|
|
||||||
if ctx.HasError() {
|
if ctx.HasError() {
|
||||||
ctx.HTML(200, MIGRATE)
|
ctx.HTML(200, MIGRATE)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if ctxUser.IsOrganization() {
|
|
||||||
// Check ownership of organization.
|
|
||||||
if !ctxUser.IsOwnedBy(ctx.User.Id) {
|
|
||||||
ctx.Error(403)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remote address can be HTTP/HTTPS/Git URL or local path.
|
// Remote address can be HTTP/HTTPS/Git URL or local path.
|
||||||
// Note: remember to change api/v1/repo.go: MigrateRepo
|
// Note: remember to change api/v1/repo.go: MigrateRepo
|
||||||
// FIXME: merge these two functions with better error handling
|
// FIXME: merge these two functions with better error handling
|
||||||
@@ -222,19 +202,7 @@ func MigratePost(ctx *middleware.Context, form auth.MigrateRepoForm) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
switch {
|
handleCreateError(ctx, err, "MigratePost", MIGRATE, &form)
|
||||||
case models.IsErrRepoAlreadyExist(err):
|
|
||||||
ctx.Data["Err_RepoName"] = true
|
|
||||||
ctx.RenderWithErr(ctx.Tr("form.repo_name_been_taken"), MIGRATE, &form)
|
|
||||||
case models.IsErrNameReserved(err):
|
|
||||||
ctx.Data["Err_RepoName"] = true
|
|
||||||
ctx.RenderWithErr(ctx.Tr("repo.form.name_reserved", err.(models.ErrNameReserved).Name), MIGRATE, &form)
|
|
||||||
case models.IsErrNamePatternNotAllowed(err):
|
|
||||||
ctx.Data["Err_RepoName"] = true
|
|
||||||
ctx.RenderWithErr(ctx.Tr("repo.form.name_pattern_not_allowed", err.(models.ErrNamePatternNotAllowed).Pattern), MIGRATE, &form)
|
|
||||||
default:
|
|
||||||
ctx.Handle(500, "MigratePost", err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Action(ctx *middleware.Context) {
|
func Action(ctx *middleware.Context) {
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
<link rel="shortcut icon" href="{{AppSubUrl}}/img/favicon.png" />
|
<link rel="shortcut icon" href="{{AppSubUrl}}/img/favicon.png" />
|
||||||
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="{{AppSubUrl}}/css/font-awesome.min.css">
|
<link rel="stylesheet" href="{{AppSubUrl}}/ng/css/font-awesome.min.css">
|
||||||
|
|
||||||
<script src="{{AppSubUrl}}/ng/js/lib/jquery-1.11.1.min.js"></script>
|
<script src="{{AppSubUrl}}/ng/js/lib/jquery-1.11.1.min.js"></script>
|
||||||
|
|
||||||
|
|||||||
@@ -57,7 +57,7 @@
|
|||||||
<div class="inline field">
|
<div class="inline field">
|
||||||
<label>{{.i18n.Tr "repo.repo_lang"}}</label>
|
<label>{{.i18n.Tr "repo.repo_lang"}}</label>
|
||||||
<div class="ui multiple search normal selection dropdown">
|
<div class="ui multiple search normal selection dropdown">
|
||||||
<input type="hidden" name="gitignores" value="{{.gitignoresValue}}">
|
<input type="hidden" name="gitignores" value="{{.gitignores}}">
|
||||||
<div class="default text">{{.i18n.Tr "repo.repo_lang_helper"}}</div>
|
<div class="default text">{{.i18n.Tr "repo.repo_lang_helper"}}</div>
|
||||||
<div class="menu">
|
<div class="menu">
|
||||||
{{range .Gitignores}}
|
{{range .Gitignores}}
|
||||||
@@ -82,7 +82,7 @@
|
|||||||
<div class="inline field">
|
<div class="inline field">
|
||||||
<label>{{.i18n.Tr "repo.readme"}}</label>
|
<label>{{.i18n.Tr "repo.readme"}}</label>
|
||||||
<div class="ui selection dropdown">
|
<div class="ui selection dropdown">
|
||||||
<input type="hidden" name="license" value="{{.readme}}">
|
<input type="hidden" name="readme" value="{{.readme}}">
|
||||||
<div class="default text">{{.i18n.Tr "repo.readme_helper"}}</div>
|
<div class="default text">{{.i18n.Tr "repo.readme_helper"}}</div>
|
||||||
<div class="menu">
|
<div class="menu">
|
||||||
{{range .Readmes}}
|
{{range .Readmes}}
|
||||||
|
|||||||
Reference in new issue
Block a user