diff --git a/models/action.go b/models/action.go index 1174929354..44d7aea8ca 100644 --- a/models/action.go +++ b/models/action.go @@ -59,14 +59,18 @@ func (a Action) GetContent() string { // CommitRepoAction records action for commit repository. func CommitRepoAction(userId int64, userName string, repoId int64, repoName string, refName string, commits *base.PushCommits) error { + log.Trace("action.CommitRepoAction: %d/%s", userId, repoName) + bs, err := json.Marshal(commits) if err != nil { + log.Error("action.CommitRepoAction(json): %d/%s", userId, repoName) return err } // Add feeds for user self and all watchers. watches, err := GetWatches(repoId) if err != nil { + log.Error("action.CommitRepoAction(get watches): %d/%s", userId, repoName) return err } watches = append(watches, Watch{UserId: userId}) @@ -86,20 +90,23 @@ func CommitRepoAction(userId int64, userName string, RepoName: repoName, RefName: refName, }) + if err != nil { + log.Error("action.CommitRepoAction(notify watches): %d/%s", userId, repoName) + } return err } // Update repository last update time. repo, err := GetRepositoryByName(userId, repoName) if err != nil { + log.Error("action.CommitRepoAction(GetRepositoryByName): %d/%s", userId, repoName) return err } repo.IsBare = false if err = UpdateRepository(repo); err != nil { + log.Error("action.CommitRepoAction(UpdateRepository): %d/%s", userId, repoName) return err } - - log.Trace("action.CommitRepoAction: %d/%s", userId, repo.LowerName) return nil } diff --git a/models/repo.go b/models/repo.go index f03d7683dd..6cbfaf1059 100644 --- a/models/repo.go +++ b/models/repo.go @@ -261,6 +261,7 @@ func initRepository(f string, user *User, repo *Repository, initReadme bool, rep return err } + /* // hook/post-update pu, err := os.OpenFile(filepath.Join(repoPath, "hooks", "post-update"), os.O_CREATE|os.O_WRONLY, 0777) if err != nil { @@ -282,6 +283,7 @@ func initRepository(f string, user *User, repo *Repository, initReadme bool, rep if _, err = pu2.WriteString("#!/usr/bin/env bash\ngit update-server-info\n"); err != nil { return err } + */ // Initialize repository according to user's choice. fileName := map[string]string{} @@ -387,7 +389,7 @@ func UpdateRepository(repo *Repository) error { repo.Website = repo.Website[:255] } - _, err := orm.Id(repo.Id).UseBool().Cols("description", "website", "updated").Update(repo) + _, err := orm.Id(repo.Id).AllCols().Update(repo) return err } diff --git a/models/user.go b/models/user.go index d2ed5a907d..6ca16ec32e 100644 --- a/models/user.go +++ b/models/user.go @@ -211,7 +211,7 @@ func UpdateUser(user *User) (err error) { user.Website = user.Website[:255] } - _, err = orm.Id(user.Id).UseBool().Cols("email", "passwd", "avatar", "avatar_email", "website", "location", "is_active", "is_admin", "updated").Update(user) + _, err = orm.Id(user.Id).AllCols().Update(user) return err } diff --git a/modules/base/conf.go b/modules/base/conf.go index 2bf529d9d1..b4e0de97bd 100644 --- a/modules/base/conf.go +++ b/modules/base/conf.go @@ -100,7 +100,7 @@ func newService() { Service.EnableCacheAvatar = Cfg.MustBool("service", "ENABLE_CACHE_AVATAR", false) } -func newLogService() { +func NewLogService() { // Get and check log mode. LogMode = Cfg.MustValue("log", "MODE", "console") modeSec := "log." + LogMode @@ -125,7 +125,7 @@ func newLogService() { logPath := Cfg.MustValue(modeSec, "FILE_NAME", "log/gogs.log") os.MkdirAll(path.Dir(logPath), os.ModePerm) LogConfig = fmt.Sprintf( - `{"level":%s,"filename":%s,"rotate":%v,"maxlines":%d,"maxsize",%d,"daily":%v,"maxdays":%d}`, level, + `{"level":%s,"filename":"%s","rotate":%v,"maxlines":%d,"maxsize":%d,"daily":%v,"maxdays":%d}`, level, logPath, Cfg.MustBool(modeSec, "LOG_ROTATE", true), Cfg.MustInt(modeSec, "MAX_LINES", 1000000), @@ -133,20 +133,20 @@ func newLogService() { Cfg.MustBool(modeSec, "DAILY_ROTATE", true), Cfg.MustInt(modeSec, "MAX_DAYS", 7)) case "conn": - LogConfig = fmt.Sprintf(`{"level":%s,"reconnectOnMsg":%v,"reconnect":%v,"net":%s,"addr":%s}`, level, + LogConfig = fmt.Sprintf(`{"level":"%s","reconnectOnMsg":%v,"reconnect":%v,"net":"%s","addr":"%s"}`, level, Cfg.MustBool(modeSec, "RECONNECT_ON_MSG", false), Cfg.MustBool(modeSec, "RECONNECT", false), Cfg.MustValue(modeSec, "PROTOCOL", "tcp"), Cfg.MustValue(modeSec, "ADDR", ":7020")) case "smtp": - LogConfig = fmt.Sprintf(`{"level":%s,"username":%s,"password":%s,"host":%s,"sendTos":%s,"subject":%s}`, level, + LogConfig = fmt.Sprintf(`{"level":"%s","username":"%s","password":"%s","host":"%s","sendTos":"%s","subject":"%s"}`, level, Cfg.MustValue(modeSec, "USER", "example@example.com"), Cfg.MustValue(modeSec, "PASSWD", "******"), Cfg.MustValue(modeSec, "HOST", "127.0.0.1:25"), Cfg.MustValue(modeSec, "RECEIVERS", "[]"), Cfg.MustValue(modeSec, "SUBJECT", "Diagnostic message from serve")) case "database": - LogConfig = fmt.Sprintf(`{"level":%s,"driver":%s,"conn":%s}`, level, + LogConfig = fmt.Sprintf(`{"level":"%s","driver":"%s","conn":"%s"}`, level, Cfg.MustValue(modeSec, "Driver"), Cfg.MustValue(modeSec, "CONN")) } @@ -259,11 +259,16 @@ func NewConfigContext() { Cfg.BlockMode = false cfgPath = filepath.Join(workDir, "custom/conf/app.ini") - if com.IsFile(cfgPath) { - if err = Cfg.AppendFiles(cfgPath); err != nil { - fmt.Printf("Cannot load config file '%s'\n", cfgPath) - os.Exit(2) - } + if !com.IsFile(cfgPath) { + fmt.Println("Custom configuration not found(custom/conf/app.ini)\n" + + "Please create it and make your own configuration!") + os.Exit(2) + + } + + if err = Cfg.AppendFiles(cfgPath); err != nil { + fmt.Printf("Cannot load config file '%s'\n", cfgPath) + os.Exit(2) } AppName = Cfg.MustValue("", "APP_NAME", "Gogs: Go Git Service") @@ -291,7 +296,7 @@ func NewConfigContext() { func NewServices() { newService() - newLogService() + NewLogService() newCacheService() newSessionService() newMailService() diff --git a/public/css/gogs.css b/public/css/gogs.css index 65a6c03d71..434af03590 100755 --- a/public/css/gogs.css +++ b/public/css/gogs.css @@ -711,6 +711,12 @@ html, body { width: 1%; } +.file-content .file-body.file-code .lines-ellipsis { + background-color: #FAFAFA; + color: #999; + width: 1%; +} + .file-content .file-body.file-code .lines-num span { font-family: Menlo, Monaco, Consolas, "Courier New", monospace; line-height: 1.6; @@ -798,7 +804,7 @@ html, body { margin-left: .5em; } -.commit-box .avatar { +.commit-box .avatar, .diff-head-box .avatar { width: 20px; height: 20px; margin-right: 8px; @@ -831,10 +837,141 @@ html, body { background-color: #FFF; } -.guide-box { +.guide-box, .diff-head-box { margin-top: 20px; } +.diff-head-box h4 { + margin-top: 0; + margin-bottom: 0; + line-height: 26px; +} + +.diff-head-box p { + margin-bottom: 0; +} + +.diff-head-box .sha { + margin-left: 8px; +} + +.diff-head-box a.name { + color: #444; + margin-right: 8px; +} + +.diff-head-box span.time { + color: #888; +} + +.diff-detail-box { + margin-bottom: 16px; + line-height: 30px; +} + +.diff-detail-box span.status { + display: inline-block; + width: 12px; + height: 12px; + margin-right: 8px; + vertical-align: middle; +} + +.diff-detail-box ol { + padding-left: 0; + margin-bottom: 28px; +} + +.diff-detail-box li { + list-style: none; + padding-bottom: 4px; + margin-bottom: 4px; + border-bottom: 1px dashed #DDD; + padding-left: 6px; +} + +.diff-detail-box span.status.modify { + background-color: #f0db88; +} + +.diff-detail-box span.status.add { + background-color: #b4e2b4; +} + +.diff-detail-box span.status.del { + background-color: #e9aeae; +} + +.diff-detail-box span.status.rename { + background-color: #dad8ff; +} + +.diff-file-box .panel-heading { + padding: 10px 20px; + line-height: 26px; +} + +.diff-box .count { + margin-right: 12px; +} + +.diff-box .count .bar { + width: 40px; + display: inline-block; + margin: 2px 4px 0 4px; + vertical-align: text-top; +} + +.diff-box .file { + color: #888; +} + +#gogs-source .file-content.diff-file-box { + margin-bottom: 20px; +} + +.diff-box .count .bar .add { + background-color: #77c64a; + height: 12px; +} + +.diff-box .count .bar .del, .diff-box .count .bar { + background-color: #e75316; + height: 12px; +} + +.diff-file-box .file-body.file-code .lines-code > pre { + margin: 0; + padding: 3px; +} + +.diff-file-box .file-body.file-code .lines-num-old { + border-right: 1px solid #DDD; +} + +.diff-file-box .code-bin td { + padding: 20px; +} + +.diff-file-box .code-diff tbody tr.add-code td, .diff-file-box .code-diff tbody tr.add-code pre { + background-color: #d1ffd6 !important; + border-color: #b4e2b4 !important; +} + +.diff-file-box .code-diff tbody tr.del-code td, .diff-file-box .code-diff tbody tr.del-code pre { + background-color: #ffe2dd !important; + border-color: #e9aeae !important; +} + +.diff-file-box .code-diff tbody tr:hover td, .diff-file-box .code-diff tbody tr:hover pre { + background-color: #fff8d2 !important; + border-color: #f0db88 !important; +} + +.diff-file-box .ellipsis-code pre { + color: #AAA; +} + /* wrapper and footer */ #wrapper { diff --git a/public/js/app.js b/public/js/app.js index 4bf4b29e5f..9a58a6f2f2 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -2,11 +2,11 @@ var Gogits = { "PageIsSignup": false }; -(function($){ +(function ($) { // extend jQuery ajax, set csrf token value var ajax = $.ajax; $.extend({ - ajax: function(url, options) { + ajax: function (url, options) { if (typeof url === 'object') { options = url; url = undefined; @@ -17,24 +17,24 @@ var Gogits = { var headers = options.headers || {}; var domain = document.domain.replace(/\./ig, '\\.'); if (!/^(http:|https:).*/.test(url) || eval('/^(http:|https:)\\/\\/(.+\\.)*' + domain + '.*/').test(url)) { - headers = $.extend(headers, {'X-Csrf-Token':csrftoken}); + headers = $.extend(headers, {'X-Csrf-Token': csrftoken}); } options.headers = headers; var callback = options.success; - options.success = function(data){ - if(data.once){ + options.success = function (data) { + if (data.once) { // change all _once value if ajax data.once exist $('[name=_once]').val(data.once); } - if(callback){ + if (callback) { callback.apply(this, arguments); } }; return ajax(url, options); }, - changeHash: function(hash) { - if(history.pushState) { + changeHash: function (hash) { + if (history.pushState) { history.pushState(null, null, hash); } else { @@ -42,8 +42,8 @@ var Gogits = { } }, - deSelect: function() { - if(window.getSelection) { + deSelect: function () { + if (window.getSelection) { window.getSelection().removeAllRanges(); } else { document.selection.empty(); @@ -114,8 +114,8 @@ var Gogits = { $tabs.find("li:eq(0) a").tab("show"); }; // fix dropdown inside click - Gogits.initDropDown = function(){ - $('.dropdown-menu.no-propagation').on('click',function(e){ + Gogits.initDropDown = function () { + $('.dropdown-menu.no-propagation').on('click', function (e) { e.stopPropagation(); }); }; @@ -144,24 +144,24 @@ var Gogits = { node = node.wrap('
'); node.append(''); }); - } + }; Gogits.renderCodeView = function () { - function selectRange($list, $select, $from){ + function selectRange($list, $select, $from) { $list.removeClass('active'); - if($from){ + if ($from) { var a = parseInt($select.attr('rel').substr(1)); var b = parseInt($from.attr('rel').substr(1)); var c; - if(a != b){ - if(a > b){ + if (a != b) { + if (a > b) { c = a; a = b; b = c; } var classes = []; - for(i = a; i <= b; i++) { - classes.push('.L'+i); + for (i = a; i <= b; i++) { + classes.push('.L' + i); } $list.filter(classes.join(',')).addClass('active'); $.changeHash('#L' + a + '-' + 'L' + b); @@ -175,11 +175,11 @@ var Gogits = { $(document).on('click', '.lines-num span', function (e) { var $select = $(this); var $list = $select.parent().siblings('.lines-code').find('ol.linenums > li'); - selectRange($list, $list.filter('[rel='+$select.attr('rel')+']'), (e.shiftKey?$list.filter('.active').eq(0):null)); + selectRange($list, $list.filter('[rel=' + $select.attr('rel') + ']'), (e.shiftKey ? $list.filter('.active').eq(0) : null)); $.deSelect(); }); - $('.code-view .lines-code > pre').each(function(){ + $('.code-view .lines-code > pre').each(function () { var $pre = $(this); var $lineCode = $pre.parent(); var $lineNums = $lineCode.siblings('.lines-num'); @@ -191,20 +191,20 @@ var Gogits = { } }); - $(window).on('hashchange', function(e) { + $(window).on('hashchange',function (e) { var m = window.location.hash.match(/^#(L\d+)\-(L\d+)$/); var $list = $('.code-view ol.linenums > li'); - if(m){ - var $first = $list.filter('.'+m[1]); - selectRange($list, $first, $list.filter('.'+m[2])); - $("html, body").scrollTop($first.offset().top-200); + if (m) { + var $first = $list.filter('.' + m[1]); + selectRange($list, $first, $list.filter('.' + m[2])); + $("html, body").scrollTop($first.offset().top - 200); return; } m = window.location.hash.match(/^#(L\d+)$/); - if(m){ - var $first = $list.filter('.'+m[1]); + if (m) { + var $first = $list.filter('.' + m[1]); selectRange($list, $first); - $("html, body").scrollTop($first.offset().top-200); + $("html, body").scrollTop($first.offset().top - 200); } }).trigger('hashchange'); }; @@ -334,6 +334,21 @@ function initRepository() { return false; }); })(); + + // repo diff counter + (function () { + var $counter = $('.diff-counter'); + if ($counter.length < 1) { + return; + } + $counter.each(function (i, item) { + var $item = $(item); + var addLine = $item.find('span[data-line].add').data("line"); + var delLine = $item.find('span[data-line].del').data("line"); + var addPercent = parseFloat(addLine) / (parseFloat(addLine) + parseFloat(delLine)) * 100; + $item.find(".bar .add").css("width", addPercent + "%"); + }); + }()); } (function ($) { diff --git a/routers/repo/commit.go b/routers/repo/commit.go index 60ee2177f3..e038998f94 100644 --- a/routers/repo/commit.go +++ b/routers/repo/commit.go @@ -33,3 +33,9 @@ func Commits(ctx *middleware.Context, params martini.Params) { ctx.Data["Commits"] = commits ctx.HTML(200, "repo/commits") } + +func Diff(ctx *middleware.Context,params martini.Params){ + ctx.Data["Title"] = "commit-sha" + ctx.Data["IsRepoToolbarCommits"] = true + ctx.HTML(200,"repo/diff") +} diff --git a/serve.go b/serve.go index b84fa2a4e5..06815b65df 100644 --- a/serve.go +++ b/serve.go @@ -44,6 +44,10 @@ gogs serv provide access auth for repositories`, Flags: []cli.Flag{}, } +func init() { + log.NewLogger(10000, "file", fmt.Sprintf(`{"filename":"%s"}`, "log/serv.log")) +} + func parseCmd(cmd string) (string, string) { ss := strings.SplitN(cmd, " ", 2) if len(ss) != 2 { @@ -68,6 +72,7 @@ func runServ(k *cli.Context) { base.NewConfigContext() models.LoadModelsConfig() models.NewEngine() + base.NewLogService() keys := strings.Split(os.Args[2], "-") if len(keys) != 2 { @@ -227,7 +232,7 @@ func runServ(k *cli.Context) { return } if ref, ok = refs[refname]; !ok { - println("unknow reference name -", refname, "-") + log.Trace("unknow reference name -", refname, "-", b.String()) return } l, err = ref.AllCommits() diff --git a/templates/repo/diff.tmpl b/templates/repo/diff.tmpl new file mode 100644 index 0000000000..b0836127ff --- /dev/null +++ b/templates/repo/diff.tmpl @@ -0,0 +1,448 @@ +{{template "base/head" .}} +{{template "base/navbar" .}} +{{template "repo/nav" .}} +{{template "repo/toolbar" .}} ++ + 5 changed files with 25 additions and 9 deletions. +
++ 1 + | ++ 1 + | +
+ "github.com/youtube/vitess/go/bson"+ |
+
+ 2 + | ++ 2 + | +
+ "github.com/youtube/vitess/go/bson"+ |
+
+ 3 + | ++ 3 + | +
+ "github.com/youtube/vitess/go/bson"+ |
+
+ + + | ++ 4 + | +
+ "github.com/youtube/vitess/go/bson"+ |
+
+ + + | ++ 5 + | +
+ "github.com/youtube/vitess/go/bson"+ |
+
+ 4 + | ++ - + | +
+ "github.com/youtube/vitess/go/bson"+ |
+
+ 5 + | ++ - + | +
+ "github.com/youtube/vitess/go/bson"+ |
+
+ 6 + | ++ - + | +
+ "github.com/youtube/vitess/go/bson"+ |
+
+ 7 + | ++ - + | +
+ "github.com/youtube/vitess/go/bson"+ |
+
+ 8 + | ++ 6 + | +
+ "github.com/youtube/vitess/go/bson"+ |
+
+ 9 + | ++ 7 + | +
+ "github.com/youtube/vitess/go/bson"+ |
+
+ 10 + | ++ 8 + | +
+ "github.com/youtube/vitess/go/bson"+ |
+
+ 1 + | ++ 1 + | +
+ "github.com/youtube/vitess/go/bson"+ |
+
+ 2 + | ++ 2 + | +
+ "github.com/youtube/vitess/go/bson"+ |
+
+ 3 + | ++ 3 + | +
+ "github.com/youtube/vitess/go/bson"+ |
+
+ + + | ++ 4 + | +
+ "github.com/youtube/vitess/go/bson"+ |
+
+ + + | ++ 5 + | +
+ "github.com/youtube/vitess/go/bson"+ |
+
+ 4 + | ++ - + | +
+ "github.com/youtube/vitess/go/bson"+ |
+
+ 5 + | ++ - + | +
+ "github.com/youtube/vitess/go/bson"+ |
+
+ 6 + | ++ - + | +
+ "github.com/youtube/vitess/go/bson"+ |
+
+ 7 + | ++ - + | +
+ "github.com/youtube/vitess/go/bson"+ |
+
+ 8 + | ++ 6 + | +
+ "github.com/youtube/vitess/go/bson"+ |
+
+ 9 + | ++ 7 + | +
+ "github.com/youtube/vitess/go/bson"+ |
+
+ 10 + | ++ 8 + | +
+ "github.com/youtube/vitess/go/bson"+ |
+
+ + | +
+ "github.com/youtube/vitess/go/bson"+ |
+ |
+ 10 + | ++ 8 + | +
+ "github.com/youtube/vitess/go/bson"+ |
+
+ 10 + | ++ 8 + | +
+ "github.com/youtube/vitess/go/bson"+ |
+