From 9ffa8a40836a5e3341267affbaef08acf4765a74 Mon Sep 17 00:00:00 2001
From: Unknown <joe2010xtmf@163.com>
Date: Sat, 12 Apr 2014 21:30:09 -0400
Subject: [PATCH] finish mirror fix #63

---
 .gopmfile            |  8 ++++----
 models/repo.go       | 26 ++++++++++++++++++++++++++
 modules/cron/cron.go | 17 +++++++++++++++++
 routers/install.go   |  2 ++
 4 files changed, 49 insertions(+), 4 deletions(-)
 create mode 100644 modules/cron/cron.go

diff --git a/.gopmfile b/.gopmfile
index c9fad8a036..d7eeef0782 100644
--- a/.gopmfile
+++ b/.gopmfile
@@ -4,22 +4,22 @@ path = github.com/gogits/gogs
 [deps]
 github.com/codegangsta/cli = 
 github.com/go-martini/martini = 
-github.com/Unknwon/com = 
-github.com/Unknwon/cae = 
-github.com/Unknwon/goconfig = 
 github.com/nfnt/resize = 
 github.com/lunny/xorm = 
 github.com/go-sql-driver/mysql = 
 github.com/lib/pq = 
 github.com/qiniu/log = 
+github.com/robfig/cron = 
 code.google.com/p/goauth2 = 
+github.com/Unknwon/com = 
+github.com/Unknwon/cae = 
+github.com/Unknwon/goconfig = 
 github.com/gogits/logs = 
 github.com/gogits/binding = 
 github.com/gogits/git = 
 github.com/gogits/gfm = 
 github.com/gogits/cache = 
 github.com/gogits/session = 
-github.com/gogits/webdav = 
 
 [res]
 include = templates|public|conf
diff --git a/models/repo.go b/models/repo.go
index a2c63a50c9..ae8fe5efd1 100644
--- a/models/repo.go
+++ b/models/repo.go
@@ -130,6 +130,32 @@ type Mirror struct {
 	NextUpdate time.Time
 }
 
+// MirrorUpdate checks and updates mirror repositories.
+func MirrorUpdate() {
+	if err := orm.Iterate(new(Mirror), func(idx int, bean interface{}) error {
+		m := bean.(*Mirror)
+		if m.NextUpdate.After(time.Now()) {
+			return nil
+		}
+
+		repoPath := filepath.Join(base.RepoRootPath, m.RepoName+".git")
+		_, stderr, err := com.ExecCmdDir(repoPath, "git", "remote", "update")
+		if err != nil {
+			return err
+		} else if strings.Contains(stderr, "fatal:") {
+			return errors.New(stderr)
+		} else if err = git.UnpackRefs(repoPath); err != nil {
+			return err
+		}
+
+		m.NextUpdate = time.Now().Add(time.Duration(m.Interval) * time.Hour)
+		_, err = orm.Id(m.Id).Update(m)
+		return err
+	}); err != nil {
+		log.Error("repo.MirrorUpdate: %v", err)
+	}
+}
+
 // MirrorRepository creates a mirror repository from source.
 func MirrorRepository(repoId int64, userName, repoName, repoPath, url string) error {
 	_, stderr, err := com.ExecCmd("git", "clone", "--mirror", url, repoPath)
diff --git a/modules/cron/cron.go b/modules/cron/cron.go
new file mode 100644
index 0000000000..27b1fc41bb
--- /dev/null
+++ b/modules/cron/cron.go
@@ -0,0 +1,17 @@
+// 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 cron
+
+import (
+	"github.com/robfig/cron"
+
+	"github.com/gogits/gogs/models"
+)
+
+func NewCronContext() {
+	c := cron.New()
+	c.AddFunc("@every 1h", models.MirrorUpdate)
+	c.Start()
+}
diff --git a/routers/install.go b/routers/install.go
index 76c03f0529..d66f5b39b6 100644
--- a/routers/install.go
+++ b/routers/install.go
@@ -18,6 +18,7 @@ import (
 	"github.com/gogits/gogs/models"
 	"github.com/gogits/gogs/modules/auth"
 	"github.com/gogits/gogs/modules/base"
+	"github.com/gogits/gogs/modules/cron"
 	"github.com/gogits/gogs/modules/log"
 	"github.com/gogits/gogs/modules/mailer"
 	"github.com/gogits/gogs/modules/middleware"
@@ -49,6 +50,7 @@ func GlobalInit() {
 		}
 
 		models.HasEngine = true
+		cron.NewCronContext()
 	}
 	base.NewServices()
 	checkRunMode()