Преглед изворни кода

Merge branch 'master' of github.com:gogits/gogs

Lunny Xiao пре 11 година
родитељ
комит
f824d6a4b1

+ 1 - 0
README.md

@@ -17,6 +17,7 @@ Please see [Wiki](https://github.com/gogits/gogs/wiki) for project design, devel
 
 ## Features
 
+- Activity timeline
 - SSH protocal support.
 - Register/delete account.
 - Create/delete public repository.

+ 2 - 2
conf/app.ini

@@ -3,8 +3,8 @@ RUN_USER = lunny
 
 [repository]
 ROOT = /Users/%(RUN_USER)s/git/gogs-repositories
-LANG_IGNS=Google Go|C|Python
-LICENSES=Apache v2 License|GPL v2|BSD (3-Clause) License
+LANG_IGNS=Google Go|C|Python|Ruby
+LICENSES=Apache v2 License|GPL v2|MIT License|BSD (3-Clause) License
 
 [server]
 HTTP_ADDR = 

+ 18 - 0
conf/gitignore/Ruby

@@ -0,0 +1,18 @@
+*.gem
+*.rbc
+.bundle
+.config
+coverage
+InstalledFiles
+lib/bundler/man
+pkg
+rdoc
+spec/reports
+test/tmp
+test/version_tmp
+tmp
+
+# YARD artifacts
+.yardoc
+_yardoc
+doc/

+ 21 - 0
conf/license/MIT License

@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.

+ 11 - 13
gogs.go

@@ -7,7 +7,7 @@ package main
 
 import (
 	"os"
-	"os/user"
+	// "os/user"
 	"runtime"
 
 	"github.com/codegangsta/cli"
@@ -20,21 +20,21 @@ import (
 // Test that go1.1 tag above is included in builds. main.go refers to this definition.
 const go11tag = true
 
-const APP_VER = "0.0.8.0315"
+const APP_VER = "0.0.8.0316.1"
 
 func init() {
 	base.AppVer = APP_VER
 	runtime.GOMAXPROCS(runtime.NumCPU())
 }
 
-func checkRunUser() bool {
-	u, err := user.Current()
-	if err != nil {
-		// TODO: log
-		return false
-	}
-	return u.Username == base.Cfg.MustValue("", "RUN_USER")
-}
+// func checkRunUser() bool {
+// 	u, err := user.Current()
+// 	if err != nil {
+// 		// TODO: log
+// 		return false
+// 	}
+// 	return u.Username == base.Cfg.MustValue("", "RUN_USER")
+// }
 
 func main() {
 	/*if !checkRunUser() {
@@ -51,8 +51,6 @@ func main() {
 		CmdServ,
 		CmdUpdate,
 	}
-	app.Flags = append(app.Flags, []cli.Flag{
-		cli.BoolFlag{"noterm", "disable color output"},
-	}...)
+	app.Flags = append(app.Flags, []cli.Flag{}...)
 	app.Run(os.Args)
 }

+ 2 - 2
models/action.go

@@ -43,6 +43,7 @@ func (a Action) GetRepoName() string {
 	return a.RepoName
 }
 
+// CommitRepoAction records action for commit repository.
 func CommitRepoAction(userId int64, userName string,
 	repoId int64, repoName string, msg string) error {
 	_, err := orm.InsertOne(&Action{
@@ -57,8 +58,7 @@ func CommitRepoAction(userId int64, userName string,
 	return err
 }
 
-// NewRepoAction inserts action for create repository.
-
+// NewRepoAction records action for create repository.
 func NewRepoAction(user *User, repo *Repository) error {
 	_, err := orm.InsertOne(&Action{
 		UserId:      user.Id,

+ 128 - 19
models/publickey.go

@@ -1,21 +1,32 @@
+// 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 models
 
 import (
+	"bufio"
+	"errors"
 	"fmt"
+	"io"
 	"os"
 	"os/exec"
+	"path"
 	"path/filepath"
+	"strings"
+	"sync"
 	"time"
 
 	"github.com/Unknwon/com"
 )
 
 var (
+	sshOpLocker = sync.Mutex{}
 	//publicKeyRootPath string
-	sshPath       string
-	appPath       string
-	tmplPublicKey = "### autogenerated by gitgos, DO NOT EDIT\n" +
-		"command=\"%s serv key-%d\",no-port-forwarding," +
+	sshPath string
+	appPath string
+	// "### autogenerated by gitgos, DO NOT EDIT\n"
+	tmplPublicKey = "command=\"%s serv key-%d\",no-port-forwarding," +
 		"no-X11-forwarding,no-agent-forwarding,no-pty %s\n"
 )
 
@@ -47,29 +58,60 @@ func init() {
 }
 
 type PublicKey struct {
-	Id      int64
-	OwnerId int64     `xorm:"index"`
-	Name    string    `xorm:"unique not null"`
-	Content string    `xorm:"text not null"`
-	Created time.Time `xorm:"created"`
-	Updated time.Time `xorm:"updated"`
+	Id          int64
+	OwnerId     int64  `xorm:"index"`
+	Name        string `xorm:"unique not null"`
+	Fingerprint string
+	Content     string    `xorm:"text not null"`
+	Created     time.Time `xorm:"created"`
+	Updated     time.Time `xorm:"updated"`
 }
 
+var (
+	ErrKeyAlreadyExist = errors.New("Public key already exist")
+)
+
 func GenAuthorizedKey(keyId int64, key string) string {
 	return fmt.Sprintf(tmplPublicKey, appPath, keyId, key)
 }
 
-func AddPublicKey(key *PublicKey) error {
-	_, err := orm.Insert(key)
+func AddPublicKey(key *PublicKey) (err error) {
+	// Check if public key name has been used.
+	has, err := orm.Get(key)
 	if err != nil {
 		return err
+	} else if has {
+		return ErrKeyAlreadyExist
 	}
 
-	err = SaveAuthorizedKeyFile(key)
+	// Calculate fingerprint.
+	tmpPath := filepath.Join(os.TempDir(), fmt.Sprintf("%d", time.Now().Nanosecond()),
+		"id_rsa.pub")
+	os.MkdirAll(path.Dir(tmpPath), os.ModePerm)
+	f, err := os.Create(tmpPath)
+	if err != nil {
+		return
+	}
+	if _, err = f.WriteString(key.Content); err != nil {
+		return err
+	}
+	f.Close()
+	stdout, _, err := com.ExecCmd("ssh-keygen", "-l", "-f", tmpPath)
 	if err != nil {
-		_, err2 := orm.Delete(key)
-		if err2 != nil {
-			// TODO: log the error
+		return err
+	} else if len(stdout) < 2 {
+		return errors.New("Not enough output for calculating fingerprint")
+	}
+	key.Fingerprint = strings.Split(stdout, " ")[1]
+
+	// Save SSH key.
+	if _, err = orm.Insert(key); err != nil {
+		return err
+	}
+
+	if err = SaveAuthorizedKeyFile(key); err != nil {
+		if _, err2 := orm.Delete(key); err2 != nil {
+			return err2
 		}
 		return err
 	}
@@ -77,9 +119,71 @@ func AddPublicKey(key *PublicKey) error {
 	return nil
 }
 
-func DeletePublicKey(key *PublicKey) error {
-	_, err := orm.Delete(key)
-	return err
+// DeletePublicKey deletes SSH key information both in database and authorized_keys file.
+func DeletePublicKey(key *PublicKey) (err error) {
+	has, err := orm.Id(key.Id).Get(key)
+	if err != nil {
+		return err
+	} else if !has {
+		return errors.New("Public key does not exist")
+	}
+	if _, err = orm.Delete(key); err != nil {
+		return err
+	}
+
+	sshOpLocker.Lock()
+	defer sshOpLocker.Unlock()
+
+	p := filepath.Join(sshPath, "authorized_keys")
+	tmpP := filepath.Join(sshPath, "authorized_keys.tmp")
+	fr, err := os.Open(p)
+	if err != nil {
+		return err
+	}
+	defer fr.Close()
+
+	fw, err := os.Create(tmpP)
+	if err != nil {
+		return err
+	}
+	defer fw.Close()
+
+	buf := bufio.NewReader(fr)
+	for {
+		line, errRead := buf.ReadString('\n')
+		line = strings.TrimSpace(line)
+
+		if errRead != nil {
+			if errRead != io.EOF {
+				return errRead
+			}
+
+			// Reached end of file, if nothing to read then break,
+			// otherwise handle the last line.
+			if len(line) == 0 {
+				break
+			}
+		}
+
+		// Found the line and copy rest of file.
+		if strings.Contains(line, fmt.Sprintf("key-%d", key.Id)) && strings.Contains(line, key.Content) {
+			continue
+		}
+		// Still finding the line, copy the line that currently read.
+		if _, err = fw.WriteString(line + "\n"); err != nil {
+			return err
+		}
+
+		if errRead == io.EOF {
+			break
+		}
+	}
+
+	if err = os.Remove(p); err != nil {
+		return err
+	}
+
+	return os.Rename(tmpP, p)
 }
 
 func ListPublicKey(userId int64) ([]PublicKey, error) {
@@ -89,11 +193,16 @@ func ListPublicKey(userId int64) ([]PublicKey, error) {
 }
 
 func SaveAuthorizedKeyFile(key *PublicKey) error {
+	sshOpLocker.Lock()
+	defer sshOpLocker.Unlock()
+
 	p := filepath.Join(sshPath, "authorized_keys")
 	f, err := os.OpenFile(p, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0600)
 	if err != nil {
 		return err
 	}
+	defer f.Close()
+
 	//os.Chmod(p, 0600)
 	_, err = f.WriteString(GenAuthorizedKey(key.Id, key.Content))
 	return err

+ 1 - 1
models/repo.go

@@ -264,7 +264,7 @@ func GetRepositoryById(id int64) (repo *Repository, err error) {
 // GetRepositories returns the list of repositories of given user.
 func GetRepositories(user *User) ([]Repository, error) {
 	repos := make([]Repository, 0, 10)
-	err := orm.Find(&repos, &Repository{OwnerId: user.Id})
+	err := orm.Desc("updated").Find(&repos, &Repository{OwnerId: user.Id})
 	return repos, err
 }
 

+ 27 - 2
models/user.go

@@ -142,6 +142,7 @@ func UpdateUser(user *User) (err error) {
 
 // DeleteUser completely deletes everything of the user.
 func DeleteUser(user *User) error {
+	// Check ownership of repository.
 	count, err := GetRepositoryCount(user)
 	if err != nil {
 		return errors.New("modesl.GetRepositories: " + err.Error())
@@ -151,6 +152,22 @@ func DeleteUser(user *User) error {
 
 	// TODO: check issues, other repos' commits
 
+	// Delete all feeds.
+	if _, err = orm.Delete(&Action{UserId: user.Id}); err != nil {
+		return err
+	}
+
+	// Delete all SSH keys.
+	keys := make([]PublicKey, 0, 10)
+	if err = orm.Find(&keys, &PublicKey{OwnerId: user.Id}); err != nil {
+		return err
+	}
+	for _, key := range keys {
+		if err = DeletePublicKey(&key); err != nil {
+			return err
+		}
+	}
+
 	_, err = orm.Delete(user)
 	// TODO: delete and update follower information.
 	return err
@@ -158,8 +175,8 @@ func DeleteUser(user *User) error {
 
 // EncodePasswd encodes password to safe format.
 func (user *User) EncodePasswd() error {
-	newPasswd, err := scrypt.Key([]byte(user.Passwd), []byte(UserPasswdSalt), 16384, 8, 1, 64)
-	user.Passwd = fmt.Sprintf("%x", newPasswd)
+	var err error
+	user.Passwd, err = EncodePasswd(user.Passwd)
 	return err
 }
 
@@ -167,6 +184,14 @@ func UserPath(userName string) string {
 	return filepath.Join(RepoRootPath, userName)
 }
 
+func EncodePasswd(rawPasswd string) (string, error) {
+	newPasswd, err := scrypt.Key([]byte(rawPasswd), []byte(UserPasswdSalt), 16384, 8, 1, 64)
+	if err != nil {
+		return "", err
+	}
+	return fmt.Sprintf("%x", newPasswd), nil
+}
+
 func GetUserByKeyId(keyId int64) (*User, error) {
 	user := new(User)
 	has, err := orm.Sql("select a.* from user as a, public_key as b where a.id = b.owner_id and b.id=?", keyId).Get(user)

+ 5 - 9
modules/middleware/repo.go

@@ -5,6 +5,8 @@
 package middleware
 
 import (
+	"errors"
+
 	"github.com/codegangsta/martini"
 
 	"github.com/gogits/gogs/models"
@@ -31,9 +33,7 @@ func RepoAssignment(redirect bool) martini.Handler {
 					ctx.Render.Redirect("/")
 					return
 				}
-				//data["ErrorMsg"] = err
-				//log.Error("repo.Single: %v", err)
-				//r.HTML(200, "base/error", data)
+				ctx.Handle(200, "RepoAssignment", err)
 				return
 			}
 		} else {
@@ -45,9 +45,7 @@ func RepoAssignment(redirect bool) martini.Handler {
 				ctx.Render.Redirect("/")
 				return
 			}
-			//data["ErrorMsg"] = "invliad user account for single repository"
-			//log.Error("repo.Single: %v", err)
-			//r.HTML(200, "base/error", data)
+			ctx.Handle(200, "RepoAssignment", errors.New("invliad user account for single repository"))
 			return
 		}
 
@@ -60,9 +58,7 @@ func RepoAssignment(redirect bool) martini.Handler {
 				ctx.Render.Redirect("/")
 				return
 			}
-			//data["ErrorMsg"] = err
-			//log.Error("repo.Single: %v", err)
-			//r.HTML(200, "base/error", data)
+			ctx.Handle(200, "RepoAssignment", err)
 			return
 		}
 

Разлика између датотеке није приказан због своје велике величине
+ 0 - 0
public/css/bootstrap.min.css


+ 69 - 64
public/css/gogs.css

@@ -302,16 +302,16 @@ html, body {
 /* gogits user ssh keys */
 
 #gogs-ssh-keys .list-group-item {
-    line-height: 48px;
+    padding: 15px 0;
     border-bottom: 1px solid #DDD;
 }
 
-#gogs-ssh-keys .list-group-item:after {
-    clear: both;
+#gogs-ssh-keys .list-group-item .delete {
+    margin: -5px 50px 0;
 }
 
-#gogs-ssh-keys .list-group-item:hover a.delete {
-    display: block;
+#gogs-ssh-keys .list-group-item:after {
+    clear: both;
 }
 
 #gogs-ssh-keys .name {
@@ -319,15 +319,6 @@ html, body {
     font-weight: bold;
 }
 
-#gogs-ssh-keys .list-group-item a.delete {
-    float: right;
-    color: white;
-    cursor: pointer;
-    margin-top: 10px;
-    border-radius: 3px;
-    display: none;
-}
-
 #gogs-ssh-keys .print {
     padding-left: 1em;
     color: #888;
@@ -472,56 +463,6 @@ html, body {
     padding: 0;
 }
 
-/* #gogs-source */
-
-#gogs-source-toolbar:after {
-    clear: both;
-}
-
-#gogs-source-toolbar .branch-switch {
-    display: inline-block;
-}
-
-#gogs-source-toolbar .breadcrumb {
-    margin: 0 .5em;
-    font-size: 16px;
-    vertical-align: middle;
-    display: inline-block;
-    background-color: transparent;
-}
-
-#gogs-source-table {
-    margin-top: 1.5em;
-    font-size: 14px;
-}
-
-#gogs-source-table .fa{
-    font-size: 15px;
-    width: 16px;
-    text-align: center;
-    color: #666;
-}
-
-#gogs-source-table .name{
-    width: 160px;
-}
-
-#gogs-source-table .size{
-    width: 80px;
-}
-
-#gogs-source-table .date{
-    width: 120px;
-}
-
-#gogs-source-table .is-dir .name {
-    font-weight: bold;
-}
-
-#gogs-source-table.table-hover > tbody > tr:hover > td {
-    background-color: #FEFEFE;
-}
-
 .activity-list {
     font-size: 14px;
 }
@@ -583,6 +524,70 @@ html, body {
     color: #999;
 }
 
+/* #gogs-source */
+#gogs-source .source-toolbar:after {
+    clear: both;
+}
+
+#gogs-source .source-toolbar .branch-switch {
+    display: inline-block;
+}
+
+#gogs-source .source-toolbar .breadcrumb {
+    margin: 0 .5em;
+    padding: 6px 15px;
+    font-size: 16px;
+    vertical-align: middle;
+    display: inline-block;
+    background-color: transparent;
+}
+
+#gogs-source .source-toolbar,
+#gogs-source .info-box,
+#gogs-source .file-content {
+    margin: 0 0 10px;
+}
+
+.info-box .info-head,
+.info-box .info-content {
+    padding: 9px 20px;
+}
+
+.file-list {
+    background-color: #fafafa;
+}
+
+.file-list .icon {
+    font-size: 17px;
+    padding: 5px 0 4px 10px;
+    width: 40px;
+}
+
+.file-list .wrap {
+    display: inline-block;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    vertical-align: top;
+    white-space: nowrap;
+}
+
+.file-list .name .wrap {
+    max-width: 180px;
+}
+
+.file-list .text .wrap {
+    max-width: 450px;
+}
+
+.file-list .date .wrap {
+    max-width: 100px;
+    padding: 0 20px 0 0; 
+}
+
+.file-list .date {
+    text-align: right;
+}
+
 #wrapper {
     min-height: 100%;
     height: auto !important;

+ 11 - 10
public/js/app.js

@@ -99,15 +99,16 @@ function initRegister() {
 }
 
 function initUserSetting(){
-    $('#gogs-ssh-keys').on("click",".delete",function(){
-        var $this = $(this);
-        Gogits.ajaxDelete("",{"id":$this.data("del")},function(json){
-            if(json.ok){
-                window.location.reload();
-            }else{
-                alert(json.err);
-            }
-        });
-        return false;
+    $('#gogs-ssh-keys .delete').confirmation({
+        singleton: true,
+        onConfirm: function(e, $this){
+            Gogits.ajaxDelete("",{"id":$this.data("del")},function(json){
+                if(json.ok){
+                    window.location.reload();
+                }else{
+                    alert(json.err);
+                }
+            });
+        }
     });
 }

Разлика између датотеке није приказан због своје велике величине
+ 0 - 0
public/js/bootstrap.min.js


+ 4 - 0
routers/dashboard.go

@@ -17,3 +17,7 @@ func Home(ctx *middleware.Context) {
 	ctx.Data["PageIsHome"] = true
 	ctx.Render.HTML(200, "home", ctx.Data)
 }
+
+func Help(ctx *middleware.Context) string {
+	return "This is help page"
+}

+ 16 - 0
routers/repo/single.go

@@ -1,3 +1,7 @@
+// 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 repo
 
 import (
@@ -60,3 +64,15 @@ func Setting(ctx *middleware.Context) {
 	ctx.Data["IsRepoToolbarSetting"] = true
 	ctx.Render.HTML(200, "repo/setting", ctx.Data)
 }
+
+func Commits(ctx *middleware.Context) string {
+	return "This is commits page"
+}
+
+func Issues(ctx *middleware.Context) string {
+	return "This is issues page"
+}
+
+func Pulls(ctx *middleware.Context) string {
+	return "This is pulls page"
+}

+ 4 - 0
routers/user/setting.go

@@ -128,6 +128,10 @@ func SettingSSHKeys(ctx *middleware.Context, form auth.AddSSHKeyForm) {
 		}
 
 		if err := models.AddPublicKey(k); err != nil {
+			if err.Error() == models.ErrKeyAlreadyExist.Error() {
+				ctx.RenderWithErr("Public key name has been used", "user/publickey", &form)
+				return
+			}
 			ctx.Handle(200, "ssh.AddPublicKey", err)
 			return
 		} else {

+ 28 - 6
routers/user/user.go

@@ -157,13 +157,23 @@ func Delete(ctx *middleware.Context) {
 		return
 	}
 
-	if err := models.DeleteUser(ctx.User); err != nil {
+	rawPasswd := ctx.Query("password")
+	encodedPwd, _ := models.EncodePasswd(rawPasswd)
+	if len(encodedPwd) == 0 || encodedPwd != ctx.User.Passwd {
 		ctx.Data["HasError"] = true
-		switch err.Error() {
-		case models.ErrUserOwnRepos.Error():
-			ctx.Data["ErrorMsg"] = "Your account still have ownership of repository, you have to delete or transfer them first."
-		default:
-			ctx.Handle(200, "user.Delete", err)
+		ctx.Data["ErrorMsg"] = "Your password error. Make sure you are owner of this account."
+	} else {
+		if err := models.DeleteUser(ctx.User); err != nil {
+			ctx.Data["HasError"] = true
+			switch err {
+			case models.ErrUserOwnRepos:
+				ctx.Data["ErrorMsg"] = "Your account still have ownership of repository, you have to delete or transfer them first."
+			default:
+				ctx.Handle(200, "user.Delete", err)
+				return
+			}
+		} else {
+			ctx.Render.Redirect("/")
 			return
 		}
 	}
@@ -189,3 +199,15 @@ func Feeds(ctx *middleware.Context, form auth.FeedsForm) {
 	}
 	ctx.Render.JSON(200, &feeds)
 }
+
+func Issues(ctx *middleware.Context) string {
+	return "This is issues page"
+}
+
+func Pulls(ctx *middleware.Context) string {
+	return "This is pulls page"
+}
+
+func Stars(ctx *middleware.Context) string {
+	return "This is stars page"
+}

+ 1 - 1
serve.go

@@ -58,7 +58,7 @@ func runServ(*cli.Context) {
 
 	cmd := os.Getenv("SSH_ORIGINAL_COMMAND")
 	if cmd == "" {
-		println("Hi ", user.Name, "! You've successfully authenticated, but Gogs does not provide shell access.")
+		println("Hi", user.Name, "! You've successfully authenticated, but Gogs does not provide shell access.")
 		return
 	}
 

+ 1 - 2
templates/base/navbar.tmpl

@@ -3,8 +3,7 @@
         <nav class="gogs-nav">
             <a id="gogs-nav-logo" class="gogs-nav-item{{if .PageIsHome}} active{{end}}" href="/"><img src="/img/favicon.png" alt="Gogs Logo" id="gogs-logo"></a>
             <a class="gogs-nav-item{{if .PageIsUserDashboard}} active{{end}}" href="/">Dashboard</a>
-            <a class="gogs-nav-item" href="#">Explore</a>
-            <a class="gogs-nav-item" href="#">Help</a>{{if .IsSigned}}
+            <a class="gogs-nav-item" href="/help">Help</a>{{if .IsSigned}}
             <a id="gogs-nav-out" class="gogs-nav-item navbar-right navbar-btn btn btn-danger" href="/user/logout/"><i class="fa fa-power-off fa-lg"></i></a>
             <a id="gogs-nav-avatar" class="gogs-nav-item navbar-right" href="{{.SignedUser.HomeLink}}" data-toggle="tooltip" data-placement="bottom" title="{{.SignedUserName}}">
                 <img src="{{.SignedUser.AvatarLink}}?s=28" alt="user-avatar" title="username"/>

+ 1 - 1
templates/repo/create.tmpl

@@ -59,7 +59,7 @@
             <div class="col-md-8 col-md-offset-2">
                 <div class="checkbox">
                     <label>
-                        <input type="checkbox" name="initReadme">
+                        <input type="checkbox" name="initReadme" {{if .initReadme}}checked{{end}}>
                         <strong>Initialize this repository with a README</strong>
                     </label>
                 </div>

+ 1 - 1
templates/repo/setting.tmpl

@@ -14,7 +14,7 @@
     </div>
     <div id="gogs-repo-setting-container" class="col-md-9 tab-content">
         <div id="options" class="tab-pane">
-            repo-options
+            <h4>Repository Options</h4>
         </div>
         <div id="delete" class="tab-pane">
             <h4>Delete Repository</h4>

+ 57 - 26
templates/repo/single.tmpl

@@ -4,14 +4,14 @@
 {{template "repo/toolbar" .}}
 <div id="gogs-body" class="container">
     <div id="gogs-source">
-        <div id="gogs-source-toolbar">
+        <div class="source-toolbar">
             <button class="btn btn-default pull-right"><i class="fa fa-plus-square"></i>Add File</button>
             <div class="dropdown branch-switch">
                 <a href="#" class="btn btn-success dropdown-toggle" data-toggle="dropdown"><i class="fa fa-chain"></i>master&nbsp;&nbsp;
                     <b class="caret"></b></a>
                 <ul class="dropdown-menu">
-                    <li><a class="current" href="/{{.RepositoryLink}}/branch/master">master</a></li>
-                    <li><a href="//{{.RepositoryLink}}/branch/develop">develop</a></li>
+                    <li><a class="current" href="/{{.RepositoryLink}}/tree/master">master</a></li>
+                    <li><a href="/{{.RepositoryLink}}/tree/develop">develop</a></li>
                 </ul>
             </div>
             {{$paths := .Paths}}
@@ -32,29 +32,60 @@
                 {{end}}
             </ol>
         </div>
-        <table id="gogs-source-table" class="table table-hover">
-            <thead class="hidden">
-	            <tr>
-	                <th class="name">Filename</th>
-	                <th class="date">Date modified</th>
-	                <th class="text">Message</th>
-	            </tr>
-            </thead>
-            <tbody>
-    			{{range .Files}}
-				<tr {{if .IsDir}}class="is-dir"{{end}}>
-	                <td class="name"><i class="fa {{if .IsDir}}fa-folder{{else}}fa-file{{end}}"></i>
-                    {{if .IsDir}}
-                    <a href="/{{$username}}/{{$reponame}}/tree/{{$branchname}}/{{.Path}}">{{.Name}}</a>
-                    {{else}}
-                    <a href="#">{{.Name}} - {{FileSize .Size}}</a>
-                    {{end}}</td>
-	                <td class="date"><time datetime="{{.Created}}" data-title="true" title="{{.Created}}">{{TimeSince .Created}}</time></td>
-	                <td class="text">{{.Message}}</td>
-				</tr>
-    			{{end}}
-            </tbody>
-        </table>
+        <div class="panel panel-default info-box">
+            <div class="panel-heading info-head">
+                Merge branch 'release/1.1.1'
+            </div>
+            <div class="panel-body info-content">
+                slene authored 4 days ago
+            </div>
+            <table class="panel-footer table file-list">
+                <thead class="hidden">
+    	            <tr>
+                        <th class="icon"></th>
+    	                <th class="name">Filename</th>
+                        <th class="text">Message</th>
+    	                <th class="date">Date modified</th>
+    	            </tr>
+                </thead>
+                <tbody>
+        			{{range .Files}}
+    				<tr {{if .IsDir}}class="is-dir"{{end}}>
+                        <td class="icon">
+                            <i class="fa {{if .IsDir}}fa-folder{{else}}fa-file-text-o{{end}}"></i>
+                        </td>
+    	                <td class="name">
+                            <span class="wrap">
+                                {{if .IsDir}}
+                                <a href="/{{$username}}/{{$reponame}}/tree/{{$branchname}}/{{.Path}}">{{.Name}}</a>
+                                {{else}}
+                                <a href="/{{$username}}/{{$reponame}}/blob/{{$branchname}}/{{.Name}}">{{.Name}}</a>
+                                {{end}}
+                            </span>
+                        </td>
+    	                <td class="text">
+                            <span class="wrap">
+                                {{.Message}}
+                            </span>
+                        </td>
+                        <td class="date">
+                            <span class="wrap">
+                                {{TimeSince .Created}}
+                            </span>
+                        </td>
+    				</tr>
+        			{{end}}
+                </tbody>
+            </table>
+        </div>
+        <div class="panel panel-default file-content">
+            <div class="panel-heading">
+                README.md
+            </div>
+            <div class="panel-body markdown">
+                 httplib
+            </div>
+        </div>
     </div>
 </div>
 {{template "base/footer" .}}

+ 26 - 15
templates/user/delete.tmpl

@@ -13,22 +13,33 @@
         </ul>
     </div>
     <div id="gogs-user-setting-container" class="col-md-9">
-        <form action="/user/delete" method="post" class="form-horizontal" id="gogs-user-delete">
-            <h4>Delete Account</h4>
-            <p class="alert alert-danger">{{if not .HasError}}The operation will delete your account permanently. Sorry to see you go, but we know you'll back soon.{{else}}{{.ErrorMsg}}{{end}}</p>
-            <div class="form-group">
-                <div class="col-md-3">
-                    <button type="submit" class="btn btn-danger btn-lg">Delete Account</button>
+        <h4>Delete Account</h4>
+        <p class="alert alert-danger">{{if not .HasError}}The operation will delete your account permanently. Sorry to see you go, but we know you'll back soon.{{else}}{{.ErrorMsg}}{{end}}</p>
+        <div class="form-group">
+            <button type="submit" class="btn btn-danger btn-lg" href="#delete-account-modal" id="gogs-delete-account" data-toggle="modal">Delete Account</button>
+        </div>
+    </div>
+    <div class="modal fade" id="delete-account-modal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
+        <div class="modal-dialog">
+            <form action="/user/delete" method="post" class="modal-content" id="gogs-user-delete">
+                <div class="modal-header">
+                    <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
+                    <h4 class="modal-title" id="myModalLabel">Delete Account</h4>
+                </div>
+
+                <div class="modal-body">
+                    <div class="form-group">
+                        <label>Make sure your are owner of this account. Please enter your password.<strong class="text-danger">*</strong></label>
+                        <input name="password" class="form-control" type="password" placeholder="Type your account password" required="required">
+                    </div>
+                </div>
+
+                <div class="modal-footer">
+                    <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
+                    <button type="submit" class="btn btn-danger">Delete</button>
                 </div>
-            </div>
-        </form>
+            </form>
+        </div>
     </div>
 </div>
-<script>
-    $(function(){
-       $('#gogs-user-delete').on('submit',function(){
-           return confirm("Are you sure ?");
-       })
-    });
-</script>
 {{template "base/footer" .}}

+ 7 - 5
templates/user/publickey.tmpl

@@ -5,7 +5,7 @@
         <h4>Account Setting</h4>
         <ul class="list-group">
             <li class="list-group-item"><a href="/user/setting">Account Profile</a></li>
-            <li class="list-group-item"><a href="/user/setting/Password">Password</a></li>
+            <li class="list-group-item"><a href="/user/setting/password">Password</a></li>
             <li class="list-group-item"><a href="/user/setting/notification">Notifications</a></li>
             <li class="list-group-item list-group-item-success"><a href="/user/setting/ssh/">SSH Keys</a></li>
             <li class="list-group-item"><a href="/user/setting/security">Security</a></li>
@@ -18,12 +18,14 @@
             <h4>SSH Keys</h4>{{if .AddSSHKeySuccess}}
             <p class="alert alert-success">New SSH Key has been added !</p>{{else if .HasError}}<p class="alert alert-danger">{{.ErrorMsg}}</p>{{end}}
             <ul id="gogs-ssh-keys-list" class="list-group">
-                <li class="list-group-item"><span class="name">SSH Key's name</span></li>{{range .Keys}}
+                <li class="list-group-item"><span class="name">SSH Key's name</span></li>
+                {{range .Keys}}
                 <li class="list-group-item">
                     <span class="name">{{.Name}}</span>
-                    <span class="print">(print code)</span>
-                    <a href="#" class="btn btn-link btn-danger right delete" rel="{{.Id}}" data-del="{{.Id}}">Delete</a>
-                </li>{{end}}
+                    <span class="print">({{.Fingerprint}})</span>
+                    <button href="#" class="btn btn-danger delete pull-right" rel="{{.Id}}" data-del="{{.Id}}">Delete</button>
+                </li>
+                {{end}}
                 <li class="list-group-item">
                     <a class="btn btn-link btn-primary" href="#ssh-add-modal" id="gogs-ssh-add" data-toggle="modal">Add SSH Key</a>
                 </li>

+ 20 - 7
update.go

@@ -1,13 +1,19 @@
+// 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 main
 
 import (
 	"os"
 	"strconv"
 
-	"github.com/gogits/gogs/models"
-
 	"github.com/codegangsta/cli"
+
 	git "github.com/gogits/git"
+
+	"github.com/gogits/gogs/models"
+	"github.com/gogits/gogs/modules/log"
 )
 
 var CmdUpdate = cli.Command{
@@ -41,11 +47,18 @@ func runUpdate(*cli.Context) {
 	if err != nil {
 		return
 	}
-	sUserId, _ := strconv.Atoi(userId)
-	sRepoId, _ := strconv.Atoi(repoId)
-	err = models.CommitRepoAction(int64(sUserId), userName,
-		int64(sRepoId), repoName, lastCommit.Message())
+	sUserId, err := strconv.Atoi(userId)
 	if err != nil {
-		//TODO: log
+		log.Error("runUpdate.Parse userId: %v", err)
+		return
+	}
+	sRepoId, err := strconv.Atoi(repoId)
+	if err != nil {
+		log.Error("runUpdate.Parse repoId: %v", err)
+		return
+	}
+	if err = models.CommitRepoAction(int64(sUserId), userName,
+		int64(sRepoId), repoName, lastCommit.Message()); err != nil {
+		log.Error("runUpdate.models.CommitRepoAction: %v", err)
 	}
 }

+ 8 - 2
web.go

@@ -50,6 +50,9 @@ func runWeb(*cli.Context) {
 
 	// Routers.
 	m.Get("/", middleware.SignInRequire(false), routers.Home)
+	m.Get("/issues", middleware.SignInRequire(true), user.Issues)
+	m.Get("/pulls", middleware.SignInRequire(true), user.Pulls)
+	m.Get("/stars", middleware.SignInRequire(true), user.Stars)
 	m.Any("/user/login", middleware.SignOutRequire(), binding.BindIgnErr(auth.LogInForm{}), user.SignIn)
 	m.Any("/user/logout", middleware.SignInRequire(true), user.SignOut)
 	m.Any("/user/sign_up", middleware.SignOutRequire(), binding.BindIgnErr(auth.RegisterForm{}), user.SignUp)
@@ -67,15 +70,18 @@ func runWeb(*cli.Context) {
 	m.Any("/repo/create", middleware.SignInRequire(true), binding.BindIgnErr(auth.CreateRepoForm{}), repo.Create)
 	m.Any("/repo/delete", middleware.SignInRequire(true), binding.Bind(auth.DeleteRepoForm{}), repo.Delete)
 
+	m.Get("/help", routers.Help)
+
 	m.Get("/:username/:reponame/settings", middleware.SignInRequire(false), middleware.RepoAssignment(true), repo.Setting)
+	m.Get("/:username/:reponame/commits", middleware.SignInRequire(false), middleware.RepoAssignment(true), repo.Commits)
+	m.Get("/:username/:reponame/issues", middleware.SignInRequire(false), middleware.RepoAssignment(true), repo.Issues)
+	m.Get("/:username/:reponame/pulls", middleware.SignInRequire(false), middleware.RepoAssignment(true), repo.Pulls)
 	m.Get("/:username/:reponame/tree/:branchname/**",
 		middleware.SignInRequire(false), middleware.RepoAssignment(true), repo.Single)
 	m.Get("/:username/:reponame/tree/:branchname",
 		middleware.SignInRequire(false), middleware.RepoAssignment(true), repo.Single)
 	m.Get("/:username/:reponame", middleware.SignInRequire(false), middleware.RepoAssignment(true), repo.Single)
 
-	//m.Get("/:username/:reponame", repo.Repo)
-
 	listenAddr := fmt.Sprintf("%s:%s",
 		base.Cfg.MustValue("server", "HTTP_ADDR"),
 		base.Cfg.MustValue("server", "HTTP_PORT", "3000"))

Неке датотеке нису приказане због велике количине промена