mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-26 12:27:06 +00:00 
			
		
		
		
	#1487 Readme Template
This commit is contained in:
		| @@ -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, | ||||||
|   | |||||||
							
								
								
									
										192
									
								
								models/repo.go
									
									
									
									
									
								
							
							
						
						
									
										192
									
								
								models/repo.go
									
									
									
									
									
								
							| @@ -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 | ||||||
|   | |||||||
| @@ -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 { | ||||||
|   | |||||||
							
								
								
									
										4
									
								
								public/ng/css/font-awesome.min.css
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								public/ng/css/font-awesome.min.css
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| @@ -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.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								public/ng/fonts/fontawesome-webfont.eot
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								public/ng/fonts/fontawesome-webfont.eot
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										1064
									
								
								public/ng/fonts/fontawesome-webfont.svg
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										1064
									
								
								public/ng/fonts/fontawesome-webfont.svg
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| Before Width: | Height: | Size: 248 KiB After Width: | Height: | Size: 348 KiB | 
							
								
								
									
										
											BIN
										
									
								
								public/ng/fonts/fontawesome-webfont.ttf
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								public/ng/fonts/fontawesome-webfont.ttf
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								public/ng/fonts/fontawesome-webfont.woff
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								public/ng/fonts/fontawesome-webfont.woff
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								public/ng/fonts/fontawesome-webfont.woff2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								public/ng/fonts/fontawesome-webfont.woff2
									
									
									
									
									
										Normal file
									
								
							
										
											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) || | ||||||
|   | |||||||
| @@ -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
	 Unknwon
					Unknwon