From fa298a2c30c358dbfa47fc123c6aca83fe9eb999 Mon Sep 17 00:00:00 2001 From: Unknwon Date: Sat, 25 Jul 2015 21:32:04 +0800 Subject: [PATCH] #835: Realtime webhooks --- cmd/serve.go | 7 ++ cmd/web.go | 1 + conf/app.ini | 4 +- gogs.go | 2 +- models/action.go | 2 + models/webhook.go | 172 ++++++++++++++++++++++++------------- modules/bindata/bindata.go | 4 +- modules/cron/manager.go | 1 - modules/setting/setting.go | 4 +- routers/install.go | 1 + routers/repo/http.go | 5 +- routers/repo/setting.go | 4 + templates/.VERSION | 2 +- 13 files changed, 140 insertions(+), 69 deletions(-) diff --git a/cmd/serve.go b/cmd/serve.go index 3d3bb1a90..fed65bba1 100644 --- a/cmd/serve.go +++ b/cmd/serve.go @@ -16,6 +16,7 @@ import ( "github.com/codegangsta/cli" "github.com/gogits/gogs/models" + "github.com/gogits/gogs/modules/httplib" "github.com/gogits/gogs/modules/log" "github.com/gogits/gogs/modules/setting" "github.com/gogits/gogs/modules/uuid" @@ -193,6 +194,12 @@ func runServ(c *cli.Context) { } } + // Send deliver hook request. + resp, err := httplib.Head(setting.AppUrl + setting.AppSubUrl + repoUserName + "/" + repoName + "/hooks/trigger").Response() + if err == nil { + resp.Body.Close() + } + // Update key activity. key, err := models.GetPublicKeyById(keyId) if err != nil { diff --git a/cmd/web.go b/cmd/web.go index 92c0185c4..b6d41c1aa 100644 --- a/cmd/web.go +++ b/cmd/web.go @@ -451,6 +451,7 @@ func runWeb(ctx *cli.Context) { m.Get("/archive/*", repo.Download) m.Get("/pulls2/", repo.PullRequest2) m.Get("/milestone2/", repo.Milestones2) + m.Head("/hooks/trigger", repo.TriggerHook) m.Group("", func() { m.Get("/src/*", repo.Home) diff --git a/conf/app.ini b/conf/app.ini index f630c1e52..08eaec7c2 100644 --- a/conf/app.ini +++ b/conf/app.ini @@ -91,8 +91,8 @@ ENABLE_REVERSE_PROXY_AUTO_REGISTRATION = false DISABLE_MINIMUM_KEY_SIZE_CHECK = false [webhook] -; Cron task interval in minutes -TASK_INTERVAL = 1 +; Hook task queue length +QUEUE_LENGTH = 1000 ; Deliver timeout in seconds DELIVER_TIMEOUT = 5 ; Allow insecure certification diff --git a/gogs.go b/gogs.go index c22ade3db..f438a4764 100644 --- a/gogs.go +++ b/gogs.go @@ -17,7 +17,7 @@ import ( "github.com/gogits/gogs/modules/setting" ) -const APP_VER = "0.6.2.0725 Beta" +const APP_VER = "0.6.3.0725 Beta" func init() { runtime.GOMAXPROCS(runtime.NumCPU()) diff --git a/models/action.go b/models/action.go index 86520b57b..2c16a575b 100644 --- a/models/action.go +++ b/models/action.go @@ -431,6 +431,8 @@ func CommitRepoAction(userId, repoUserId int64, userName, actEmail string, } if err = CreateHookTask(&HookTask{ + RepoID: repo.Id, + HookID: w.Id, Type: w.HookTaskType, Url: w.Url, BasePayload: payload, diff --git a/models/webhook.go b/models/webhook.go index bfa52b990..18cda7487 100644 --- a/models/webhook.go +++ b/models/webhook.go @@ -9,6 +9,7 @@ import ( "encoding/json" "errors" "io/ioutil" + "sync" "time" "github.com/gogits/gogs/modules/httplib" @@ -259,7 +260,9 @@ func (p Payload) GetJSONPayload() ([]byte, error) { // HookTask represents a hook task. type HookTask struct { - Id int64 + ID int64 `xorm:"pk autoincr"` + RepoID int64 `xorm:"INDEX"` + HookID int64 Uuid string Type HookTaskType Url string @@ -269,6 +272,7 @@ type HookTask struct { EventType HookEventType IsSsl bool IsDelivered bool + Delivered int64 IsSucceed bool } @@ -287,87 +291,137 @@ func CreateHookTask(t *HookTask) error { // UpdateHookTask updates information of hook task. func UpdateHookTask(t *HookTask) error { - _, err := x.Id(t.Id).AllCols().Update(t) + _, err := x.Id(t.ID).AllCols().Update(t) return err } -var ( - // Prevent duplicate deliveries. - // This happens with massive hook tasks cannot finish delivering - // before next shooting starts. - isShooting = false -) +type hookQueue struct { + // Make sure one repository only occur once in the queue. + lock sync.Mutex + repoIDs map[int64]bool -// DeliverHooks checks and delivers undelivered hooks. -// FIXME: maybe can use goroutine to shoot a number of them at same time? -func DeliverHooks() { - if isShooting { + queue chan int64 +} + +func (q *hookQueue) removeRepoID(id int64) { + q.lock.Lock() + defer q.lock.Unlock() + delete(q.repoIDs, id) +} + +func (q *hookQueue) addRepoID(id int64) { + q.lock.Lock() + if q.repoIDs[id] { + q.lock.Unlock() return } - isShooting = true - defer func() { isShooting = false }() + q.repoIDs[id] = true + q.lock.Unlock() + q.queue <- id +} - tasks := make([]*HookTask, 0, 10) +// AddRepoID adds repository ID to hook delivery queue. +func (q *hookQueue) AddRepoID(id int64) { + go q.addRepoID(id) +} + +var HookQueue *hookQueue + +func deliverHook(t *HookTask) { timeout := time.Duration(setting.Webhook.DeliverTimeout) * time.Second - x.Where("is_delivered=?", false).Iterate(new(HookTask), - func(idx int, bean interface{}) error { - t := bean.(*HookTask) - req := httplib.Post(t.Url).SetTimeout(timeout, timeout). - Header("X-Gogs-Delivery", t.Uuid). - Header("X-Gogs-Event", string(t.EventType)). - SetTLSClientConfig(&tls.Config{InsecureSkipVerify: setting.Webhook.SkipTLSVerify}) + req := httplib.Post(t.Url).SetTimeout(timeout, timeout). + Header("X-Gogs-Delivery", t.Uuid). + Header("X-Gogs-Event", string(t.EventType)). + SetTLSClientConfig(&tls.Config{InsecureSkipVerify: setting.Webhook.SkipTLSVerify}) - switch t.ContentType { - case JSON: - req = req.Header("Content-Type", "application/json").Body(t.PayloadContent) - case FORM: - req.Param("payload", t.PayloadContent) + switch t.ContentType { + case JSON: + req = req.Header("Content-Type", "application/json").Body(t.PayloadContent) + case FORM: + req.Param("payload", t.PayloadContent) + } + + t.IsDelivered = true + + // FIXME: record response. + switch t.Type { + case GOGS: + { + if resp, err := req.Response(); err != nil { + log.Error(5, "Delivery: %v", err) + } else { + resp.Body.Close() + t.IsSucceed = true } - - t.IsDelivered = true - - // FIXME: record response. - switch t.Type { - case GOGS: - { - if _, err := req.Response(); err != nil { - log.Error(5, "Delivery: %v", err) + } + case SLACK: + { + if resp, err := req.Response(); err != nil { + log.Error(5, "Delivery: %v", err) + } else { + defer resp.Body.Close() + contents, err := ioutil.ReadAll(resp.Body) + if err != nil { + log.Error(5, "%s", err) + } else { + if string(contents) != "ok" { + log.Error(5, "slack failed with: %s", string(contents)) } else { t.IsSucceed = true } } - case SLACK: - { - if res, err := req.Response(); err != nil { - log.Error(5, "Delivery: %v", err) - } else { - defer res.Body.Close() - contents, err := ioutil.ReadAll(res.Body) - if err != nil { - log.Error(5, "%s", err) - } else { - if string(contents) != "ok" { - log.Error(5, "slack failed with: %s", string(contents)) - } else { - t.IsSucceed = true - } - } - } - } } + } + } + t.Delivered = time.Now().UTC().UnixNano() + if t.IsSucceed { + log.Trace("Hook delivered(%s): %s", t.Uuid, t.PayloadContent) + } +} + +// DeliverHooks checks and delivers undelivered hooks. +func DeliverHooks() { + tasks := make([]*HookTask, 0, 10) + x.Where("is_delivered=?", false).Iterate(new(HookTask), + func(idx int, bean interface{}) error { + t := bean.(*HookTask) + deliverHook(t) tasks = append(tasks, t) - - if t.IsSucceed { - log.Trace("Hook delivered(%s): %s", t.Uuid, t.PayloadContent) - } return nil }) // Update hook task status. for _, t := range tasks { if err := UpdateHookTask(t); err != nil { - log.Error(4, "UpdateHookTask(%d): %v", t.Id, err) + log.Error(4, "UpdateHookTask(%d): %v", t.ID, err) + } + } + + HookQueue = &hookQueue{ + lock: sync.Mutex{}, + repoIDs: make(map[int64]bool), + queue: make(chan int64, setting.Webhook.QueueLength), + } + + // Start listening on new hook requests. + for repoID := range HookQueue.queue { + HookQueue.removeRepoID(repoID) + + tasks = make([]*HookTask, 0, 5) + if err := x.Where("repo_id=? AND is_delivered=?", repoID, false).Find(&tasks); err != nil { + log.Error(4, "Get repository(%d) hook tasks: %v", repoID, err) + continue + } + for _, t := range tasks { + deliverHook(t) + if err := UpdateHookTask(t); err != nil { + log.Error(4, "UpdateHookTask(%d): %v", t.ID, err) + } } } } + +func InitDeliverHooks() { + go DeliverHooks() +} diff --git a/modules/bindata/bindata.go b/modules/bindata/bindata.go index 21e22251b..edefe4656 100644 --- a/modules/bindata/bindata.go +++ b/modules/bindata/bindata.go @@ -111,7 +111,7 @@ func (fi bindataFileInfo) Sys() interface{} { return nil } -var _confAppIni = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\xb4\x59\x4f\x73\xe3\x46\x76\xbf\xe3\x53\xf4\xd0\x71\x3c\x93\x22\x29\x4a\xf2\xfc\xb1\x6c\x25\xa6\x48\x90\xc2\x8a\xff\x0c\x90\x33\x1e\x4f\xa9\x30\x10\xd0\x24\x61\x81\x68\x0c\x1a\x90\xc4\xad\x1c\xd6\x95\x43\xaa\x72\x4c\xb6\x92\x4b\x0e\xc9\x21\x95\xaa\x24\x9b\x64\x2b\x97\xdd\x4d\xe5\xe4\xca\x7d\xe6\x3b\xb8\xbc\x9b\x6f\x91\xdf\xeb\x06\x48\x50\x23\xcf\x7a\x9d\x6c\xcd\x94\x08\xf4\x9f\xd7\xfd\x5e\xbf\xf7\x7b\xbf\xd7\x78\x8f\x8d\xcc\xa7\xa6\xcd\xd4\x9f\xe1\xb8\x6b\xf5\x9e\xb3\xe9\xa9\xe5\xb0\x9e\x35\x30\x8d\xf7\xd8\x64\x60\xb6\x1d\x93\x0d\xdb\x67\x26\xeb\x9c\xb6\x47\x7d\xd3\x61\xe3\x11\xeb\x8c\x6d\xdb\x74\x26\xe3\x51\xd7\x1a\xf5\x59\x67\xe6\x4c\xc7\x43\x34\x8e\x7a\x56\x5f\xcf\x34\x3e\x66\xed\x24\x61\xb1\xb7\xe2\x2c\x5b\x7a\x19\x93\x4b\x71\x2d\x99\x88\x19\xbf\xe2\xe9\x9a\x25\xde\x02\x1d\x61\x16\x71\xa3\x3d\x99\xb8\xa3\xf6\xd0\x64\xc7\xac\x2f\x16\xf2\x08\x7f\x59\x3f\xcc\x98\xc3\xd3\xab\xd0\xe7\x90\xd4\x59\x7a\x31\x86\xa3\x2d\x9c\xb3\xb5\xc8\x59\x9a\xc7\x2c\x12\xbe\x17\x45\x6b\xc3\x9e\x8d\xdc\x99\x83\xdd\x1f\xb3\x45\x98\x61\xb4\x19\x66\x4b\x9e\xb2\x5a\xc0\xaf\x6a\x75\x56\x4b\x52\x11\xd4\x98\x40\x43\xc6\x65\x86\x96\x80\xcf\xbd\x3c\x82\x2c\xa9\xc7\x28\x09\x50\x9d\x36\x80\x77\xc3\x78\x91\xf2\x44\xc8\x30\x13\xe9\xfa\xdc\xb0\xc7\xe3\x29\x3b\x36\x9c\x8e\x6d\x4d\xa6\xee\xf4\xf9\x84\x86\x5d\x78\x72\x89\x71\x79\x78\x8e\xf5\x46\xf9\xea\x02\xeb\x89\x39\x24\xca\x9c\x4b\xad\xaf\x97\x72\xa5\x33\x0f\x58\x18\x43\x6f\xae\x54\x36\x2c\xc7\x99\x99\xee\xa4\xdd\x87\xdd\xdc\xd1\x6c\x08\x61\xfb\x2d\x88\x92\x50\x96\xa7\xe7\xc6\xc4\x1e\x4f\xc7\x9d\xf1\x00\xed\xcb\x2c\x4b\x8c\xee\x78\xd8\xb6\x46\x78\x53\xea\x2e\x85\xcc\xd4\x8e\xdc\x99\x4d\x43\xde\xbf\x5f\x8e\x7f\x20\x8f\xf6\xf6\xde\xbf\xaf\x87\xe3\xe5\xfd\xfb\xa7\xd3\xe9\xc4\x9d\x8c\xed\xe9\x03\xb9\x67\xa8\x97\x76\xb7\x0b\x2b\x19\x9b\x0e\x08\x38\x6c\xb5\x5a\x50\xa1\x1b\x4a\xef\x22\xe2\xcc\x71\x4e\xd9\x9c\x7b\x59\x8e\xcd\x5f\x2f\x79\xcc\x62\x01\x4d\xae\xbc\x30\xa2\x6e\xa3\x6b\x39\xed\x93\x81\xe9\xd2\xb0\x63\x36\xf7\x22\xc9\x0d\x3c\x97\xc2\x0e\x0e\x2a\xa2\x3a\xdd\x11\x1d\x75\x4c\xda\x17\x67\xb0\x12\x01\x37\xc6\xbd\xde\xc0\x1a\x99\xa5\xc1\xb5\x90\x52\xb0\x3d\x9e\x4d\x4d\xdb\x1d\x8c\xfb\x9b\xae\x8f\x59\x9f\xc7\x3c\xf5\x32\x98\x33\xe3\x89\x3c\x42\xcb\x1f\x30\x3f\x80\x39\xb3\xe5\x5e\x26\xf6\x16\xf0\x99\x3d\x3f\x97\x99\x58\xed\x91\xc9\xa4\x1a\xd0\x54\xed\xcc\xe7\x69\xc6\x1a\xbe\x77\x9c\xa5\x39\x67\x8d\x20\x87\xa0\x50\xc4\xc7\x4f\x1e\x3f\x6a\x2d\x5b\xab\x96\x64\x0d\xb2\xe9\xf1\x6a\x4d\x3f\x4d\x7e\xe3\xad\x92\x88\x37\x7d\xb1\x32\x3e\x86\x9c\x71\xca\xe6\xa9\x58\x31\x8f\x35\x93\xf9\x0d\x9b\x87\x50\x8c\xdf\x24\x22\xcd\x70\xac\xaa\x07\xae\xc6\x9e\x85\x71\x40\xce\x4d\x8b\x85\xf3\xd0\xd7\x7b\x15\xb0\xe1\xfd\x40\x40\x0a\x19\x71\x2e\xd2\x05\xcf\x58\x26\x8a\xf9\x6a\x62\x92\x86\x57\x34\xf8\x92\xaf\x1f\x68\xbd\x44\xc2\x63\x29\x23\x96\x5c\xfa\x72\xff\x80\x35\x60\x3c\x92\xaa\x56\x6f\x88\x3c\x2b\xde\xf8\x8a\x35\x62\x81\x69\xf2\xfb\xcd\xc2\xc8\x72\x12\x75\x48\x7a\x08\xb8\x34\x3a\xa6\x3d\x75\x29\x5e\x61\xee\xaa\x09\xf7\xca\x65\x8c\x33\xf3\xf9\x9d\x03\x0a\x89\x58\x7e\x96\x24\xf0\xfe\x08\x67\x1d\x51\x0c\x64\x1c\x16\x24\xa5\xbc\x38\x80\x15\x60\x6e\x5f\xdb\x8d\xce\x0b\xc3\x2b\xd1\xa7\x4c\x80\x56\x72\x35\x18\x8b\x82\x9f\x9a\xf9\x0d\xf7\x73\x18\xd8\x70\xa6\xed\xa9\xd5\x71\x95\xbf\x4f\xda\x53\xf8\x9c\x46\x95\x88\x4c\x8c\x53\x2c\x16\xed\x7f\x61\x4d\x98\xcc\x13\x32\xab\x61\x8e\x94\x23\xa9\xb6\xad\x0b\x0d\xb0\x99\x30\x5e\x68\xd4\xc1\x51\xe0\x48\xe2\x46\x24\x16\x0b\x1c\x63\x8e\xd0\x93\x75\xe6\x7b\x31\xbb\xe0\xac\xb6\x14\x2b\xae\xe1\x02\x07\x15\xe1\x10\x6b\xc6\xa0\xad\x60\x8e\xa2\x96\xec\x40\x23\x10\xb1\x81\x97\x79\xc0\x01\x7e\x5e\x81\x9c\xd5\x5a\xbe\x8a\x14\xe8\xc0\x9b\x16\x29\x97\x5a\x12\x1a\xc3\x8c\x1f\xa2\x23\xcc\x3e\x90\x84\x60\x29\xf3\x97\x82\xc0\xad\x7b\x52\x62\x8a\x9a\x6b\x9c\x8e\x1d\x0a\xa5\xfd\x83\xc7\xcd\x16\xfe\xed\x1f\x1d\x1e\xb6\x1e\x19\x05\x3c\x92\x4b\x1b\x05\xd6\xa5\x42\x64\xc6\xa4\xed\x38\xcf\xba\xca\x2e\x3d\x5a\xa8\xb2\x6c\x1c\xad\xeb\x8c\x97\x50\xa8\x83\x92\x76\x96\xf2\x57\x79\x98\x16\x2a\x02\x72\xc2\xf9\xba\x31\xcf\xa3\xa8\x86\x48\x1e\x6c\x60\x50\x8f\x2f\xc5\x96\xfb\x57\x52\x0d\x7d\x14\x8c\xf4\x57\x41\xd6\x0c\x2e\x60\x0e\x2f\x58\x85\xf1\xb9\x42\x32\x3f\x4f\xc3\x0c\xd0\x69\x8d\x70\x82\x83\x01\xc2\xb9\x73\x56\x39\x8c\x7b\xf7\x74\x22\xd1\x79\x66\x3a\x66\x67\xa6\x39\x61\xcf\xc7\x33\x9b\x29\xdd\xba\xed\x69\x9b\x39\xed\x9e\x79\xef\x9e\xe1\x98\x1d\xdb\x9c\xba\xf0\x42\x08\xb8\xf7\xde\xa7\xbd\xae\xf9\xcc\xc6\xff\x3f\xfc\xa3\xfb\xe4\x0b\x79\x26\xe8\x18\xe1\xef\x29\x5f\x71\x05\xc3\x81\x87\xa0\x00\x80\x58\x23\xd7\x36\x87\xe6\xf0\x04\x78\xd2\x6d\x3f\x77\x30\xff\xb1\xd1\x19\x8f\xcf\x2c\x53\xa5\x8b\x8a\x49\x5d\xef\x9a\x4b\x3a\xd4\xa2\x7b\x33\xaf\x3a\x26\x8c\xfd\x94\x07\xa1\xb6\x8a\x4d\x49\x4c\x52\x00\x8b\x9b\x35\xf3\x72\x58\x39\xce\x4a\xaf\x5c\x72\x2f\xc0\x46\x54\xea\x43\x40\x90\x7f\xa9\x17\xc3\xa6\x24\xeb\x00\xfd\xed\xf1\xe7\xcf\xdd\xf6\x6c\x7a\x6a\x8e\xe0\xe0\x70\xf2\xf1\x26\x85\x7d\xde\x78\x66\x9e\x50\x57\x83\x1a\x8a\xc4\x00\x47\x39\x37\xda\x9d\xa9\xf5\xd4\x74\x3b\x38\x21\x77\x40\x4f\x43\x6b\x04\xb4\x24\xc5\xf6\x9f\xb4\x20\xdc\x31\x29\x4c\xc8\x21\xbe\x73\x10\xa2\x55\xed\x86\xc3\xef\x01\x45\xbe\x88\xe7\x61\xba\x62\xbc\xb1\x02\xc4\xab\xc0\x48\xf9\x22\x94\x99\x46\x49\xc8\xec\x5b\x0e\x01\xb2\x89\xac\x32\x70\x55\x7e\xb7\x87\x95\xa3\xec\x0a\xa4\x3b\x95\x23\xa2\x48\x5c\x17\x93\xb1\x00\xc5\xbe\x72\x08\x06\xa3\x29\x30\xf0\x7d\x91\xc7\x99\x76\xa0\x0d\xda\x2b\xf1\xb6\xd2\xbf\x22\x54\x6d\x71\x05\xb0\x61\x32\x5c\xa8\xfc\x81\xad\x5e\x85\xfc\x1a\x62\xd7\xd9\x12\x71\xdc\xc4\xce\x3e\x9b\x59\x36\x32\x91\xd5\x1f\xe1\xa4\x9f\x5a\xe6\xb3\x8a\x84\x8e\xe7\x03\x5a\x90\xb7\x32\x0f\x7b\x91\x2c\x09\x7d\x4a\x69\x25\x38\x74\xda\x9d\x53\xd3\x6d\x3f\x85\x9f\xd9\x95\x59\x43\xb2\x01\x94\xd1\x10\x4e\xfa\x17\xe3\x47\xe3\x29\x68\x91\x4b\x36\xa8\x0e\x27\x80\x0f\x78\x86\x59\x47\x2a\x57\x53\x06\x06\x03\x59\xe6\x17\x94\x3f\x28\x34\xc2\x4c\xea\xf4\xa4\x89\xc1\xde\xfe\xa3\x87\xa5\xcc\x77\xf9\xc2\x66\x91\xef\x1a\x3b\xfe\x2e\xd3\x75\x85\x3a\x0d\x68\xef\x5f\x32\x98\x3f\x5c\xe5\x2b\x02\x7f\x58\xf2\xc7\xc8\xe8\xd8\x1c\xce\x3c\x05\x40\x24\x42\x03\x62\xb6\x4e\xb6\xd9\x17\xbe\x62\x0d\x67\x43\x8a\x36\x18\xf6\x0b\x18\xea\xd4\xac\x44\xae\xf1\xe2\x9a\x5f\x2c\x85\xb8\x24\xc4\xeb\xa4\xf0\xf4\xcc\x93\x97\x38\x1f\x9c\xf8\x95\x17\xd1\x41\x61\x49\x20\xb7\x34\xa6\x6d\xe7\xcc\xb5\x46\x70\x9d\xa7\x6d\xb2\xd9\x3e\xed\x8d\x47\x21\xa2\x06\xa4\x6f\xc5\x29\x27\x61\x38\xa0\x02\xfb\x90\x46\xd7\x24\x5f\xb5\xdd\xa9\x35\x34\xc1\x00\x30\xe1\x21\x45\xb7\xf2\xa9\x30\x56\x80\xc2\x2b\xd9\x95\x8e\xc6\x39\xb3\x26\xee\x74\xe0\xb8\x98\x47\x9c\x75\xbb\x49\x72\x65\x62\x52\xda\x78\xdd\x8a\x75\x4e\xf2\xf9\x5c\xa5\xaa\x78\x01\x43\x20\x34\x7d\xf0\xca\x98\x47\x75\x98\x88\x27\x44\x2f\xe1\x2b\xa1\x4a\x4d\x05\xcf\x0c\x44\xfc\x01\xb2\x67\x8c\x7d\x5c\x13\xa9\x53\x9d\x4d\xa0\xd2\xa8\xeb\x9e\xcc\x7a\x3d\xe2\x2a\xe6\x48\x73\x38\x10\x41\x8a\x78\x40\x27\xf2\xdf\x5a\xd3\x3e\x15\x56\x9a\xe5\x3a\xb3\x93\x1f\x99\x9d\xa9\x22\x6d\x25\xe3\x7d\x20\x4b\xb7\xd3\xf4\x8f\xc8\xce\x4a\xf9\x93\x5c\x65\x49\x73\x41\xcf\xe4\x4b\x47\x0f\x9f\x3c\x46\xdf\x67\x9f\x15\x1d\xaf\x5e\xa9\xd6\x03\xb2\xd2\x48\x64\xbc\x4e\xfb\x55\xd9\x94\x98\x05\x87\x49\xf5\x59\xd7\x3e\x7c\xf4\x10\x98\xef\x0c\xa7\x13\x07\x2d\x51\x44\x19\x0e\x78\x14\x34\x11\x64\x74\xfc\xc0\x67\x7b\x0a\x2b\x12\x2f\x57\x73\xb1\x10\xa9\x9f\xe2\x60\x56\x2b\x08\x82\x1a\x94\xdd\xed\x5e\x87\x3d\xfa\xb0\xf5\x51\x93\x59\x7a\x21\xbd\xdf\x32\xeb\xca\xad\x20\x58\x48\x2d\xe4\x45\xd7\x00\xe2\xcd\x7a\x65\x5e\xab\x10\xc4\x53\x73\x30\x26\xe6\xa2\xb1\x46\xd3\x4d\x22\x61\x0a\x37\x89\x3d\x07\x21\x1d\x17\x80\xb5\xb9\xf1\x50\x35\x47\x49\xe9\x28\x32\xb2\x9d\x40\xd8\xb5\x2b\x71\x87\xe8\x2b\xae\x26\xd7\x00\xa7\x15\xf6\x82\x71\x2e\x6d\xa8\xc0\xf7\x6d\xe0\xe8\x7c\xa8\x34\xac\x92\x39\x51\x55\xba\xc9\xc6\x00\x31\x52\x0b\x8d\x24\x1a\x2b\x4b\x1e\xcd\x1b\x84\x56\xb0\x57\x65\xa2\xd4\x6e\xba\x71\x51\x0d\x6e\xcc\x8f\x42\x68\x55\x1d\x48\x49\xdd\x25\x32\x66\xf5\x08\x03\xb6\xc4\xf8\x0e\x82\xa6\xfd\xfb\x5d\x0c\xad\x18\xb1\xa5\x68\xca\xc5\x34\x91\x0d\x02\x44\x3f\xe8\x0e\x9d\xe8\xc3\xc3\x83\x83\x26\x9b\x92\x12\x05\xfb\xf9\x92\x50\x17\x8f\x5c\x39\xee\x66\x30\x34\x24\xfd\x6b\xe4\xe0\x35\xf6\x89\xea\xfd\xb4\xc2\x95\xff\x98\x8c\xb0\x42\x7c\x18\x3d\x1b\x75\xe0\x71\xb1\x24\x1c\x64\x93\xfc\x54\x4a\x48\x3c\x29\xaf\x45\x1a\x14\x1c\x66\x4b\x5f\x8c\x17\x82\x92\xe8\xdb\x41\x5b\x74\x34\x35\xae\xbe\xdd\xdf\x19\x58\xc0\x4d\xd7\x22\x21\xc5\xb3\xa6\x0c\xaa\x64\x1b\x4f\x54\xe6\x2b\xc1\xd9\x4b\xc2\x66\x05\xa0\x69\x6f\x06\x21\x6f\x51\x4c\xdd\x81\xe1\x8a\x5b\xec\xa9\x2d\xec\xd1\x1f\x91\x02\x47\x8d\xe9\xf8\xcc\x1c\x7d\xcf\x49\xbe\x0f\x0b\xba\x19\xb8\x7a\x6c\xa8\x5a\x26\x2b\x8f\x3f\x0c\x34\x45\xe6\x48\x91\x99\x3a\x1d\xf4\x97\xe2\x80\x8b\x52\xc0\xb8\x01\x31\x5c\x72\x69\xd9\x5c\x08\xb1\xd0\xe6\xde\x03\xed\xf8\x92\xfb\xd9\xc6\x38\xaa\xe7\xff\x68\x9c\xeb\xeb\xeb\x42\x10\xcc\x24\xd5\x32\x4a\x03\xb2\x52\x18\xcf\x45\x53\xfb\xc4\xf7\x1e\x8e\x3d\x12\xed\xbf\xcb\xc0\x05\x19\xd8\x51\x49\x68\x83\x1d\x28\x29\x77\x5a\xf8\x9d\xb3\x0a\x03\x17\x06\x79\xf5\xea\x07\x1a\x03\x25\x9a\x4b\x1a\xb8\xa4\x82\x42\x5c\xf6\xcd\xaf\xfe\xf2\x37\x5f\xfd\xf4\x4e\x3f\x49\xbd\x64\x59\x60\x71\xb1\x8f\x66\xeb\xb7\xb9\xc9\x9d\x73\x76\x77\x7f\xcd\xc3\x0b\xf1\x03\x15\x00\x0f\xbb\xd3\xe2\xf0\x7c\x25\xb6\xb2\xee\x6f\xd9\xe9\xdd\x53\x76\xdc\xf9\x85\x4f\x3c\x6b\xa7\xfe\xe1\x2b\x91\xae\x75\x99\x81\x44\x58\x53\xd0\x41\xad\x6a\xe4\xad\xbb\x97\x62\xb0\xd1\xee\xb6\x27\x53\x45\x7e\x75\x4b\x59\x75\x14\xfd\x45\x29\xd3\xef\xec\x30\x8d\x82\x3a\xec\x48\x7c\xd4\x32\x2a\x9c\xe3\x51\xab\x14\xa4\xf7\xa2\xa2\xad\xba\x17\x08\x88\x11\x45\x8a\xb2\x0b\xc2\x3d\x0d\x77\x98\xa5\x26\x1c\x81\x26\x67\x40\xab\xcb\xe3\xcc\x4f\xea\xd4\x79\x7c\xf4\xe8\xf0\xf1\x47\xf5\x12\xc5\x8e\x57\x9e\xef\x81\x06\xd5\x83\x8b\xe3\x56\x3d\x11\x22\x72\x89\x66\x1d\xef\xb7\x5a\xf5\x30\x88\xb8\x5b\x30\x9d\x63\xcd\xbc\xcb\x95\x8f\xd8\xcb\x6d\x75\xb7\xbf\x7f\xb0\xbf\xff\xb2\xc8\x8e\x8a\xed\x4b\x89\x0d\xdd\x6d\x53\x8a\xa7\xad\x6d\xb5\x69\x8b\x82\xf3\x2e\xbb\x82\x2e\x3e\xb5\xba\xbb\x86\x9d\xa4\xe2\x2a\xa4\xea\x44\x51\xff\x05\xb2\x25\xe9\x2f\xf5\xf6\x30\xe4\x48\xa5\xc1\xa5\x77\x45\x80\xbd\x2e\x47\xad\x39\xdd\xab\xd1\xf2\x20\x20\x7a\x87\xdb\x9a\x1e\x55\x66\x73\xd1\x64\x2f\x55\x3d\x58\xf4\xca\x97\xbf\x37\x2b\x92\xc2\x47\x28\xc9\x1a\xf8\x6d\x04\x29\x51\xca\x3d\xd5\xc8\x02\x19\x97\x1b\x46\x05\x03\x7a\x53\xee\x8c\x4a\xe5\xa3\x72\xbd\x4f\xcb\x3d\xba\x19\xd1\x90\x97\x1b\x33\xb9\xc5\xf5\x65\x51\xd9\x96\x9a\x60\x4d\xa7\x50\xd9\x07\xf7\x0d\xb9\xae\xe5\x8a\x52\xb1\x60\x10\xa1\x1b\x85\x97\xdc\xd5\x94\x1f\x33\x2c\x4d\x1f\x89\x23\x94\xf6\x82\xcf\xaa\xd0\x2a\xdc\xb9\xca\x4d\x74\x78\x6b\x81\x08\xe9\x99\x6d\x56\x48\xab\x19\x2b\xb6\x24\x29\x71\xa8\xf5\x77\xe6\xd2\xb5\x56\x59\x26\x50\xfd\xa7\xa5\x60\xba\xea\xd8\x6e\x1d\xd1\x43\x76\xdc\x84\xd0\x8e\x90\x27\xa0\x76\x2d\xa3\xdf\xd9\x30\x76\x45\xc4\x21\x44\x77\x6c\xa5\x44\xe1\x9c\x2b\x39\x77\x4c\x77\x4c\xc7\xa1\x3a\x76\x60\xf5\xcc\xdd\xf9\xc6\x8b\xa2\xfe\x22\xaf\x9e\x12\x4b\x8d\x3c\x9f\x53\x51\x57\xb4\x2b\x83\x6f\x2f\x2b\x34\xcd\xd2\xfe\xfd\x0a\x35\x4c\x7e\xcb\xbf\x8b\x7e\xac\x68\x3f\xb5\x3a\xb4\x4e\xc1\x9e\x75\x45\xe7\xce\x26\x83\x71\xbb\xeb\x56\xaf\x29\x74\x29\x28\xd5\x55\x72\x18\x73\xc9\xf5\xad\x8f\xa2\x3d\x3e\x4a\x1a\x34\xd4\x82\x5c\xc8\x65\x2e\x6a\x46\xdf\x2e\x04\x39\xe3\x99\xad\xe4\x03\xb5\x95\x80\x0d\x0f\x2d\x87\x54\x78\x8a\x97\x65\x88\x6e\x70\xe6\x8c\xd4\x7c\xb6\xe4\x4a\x99\x6d\xab\x54\x9c\x96\xab\xd3\x04\xff\xee\x6a\x85\x24\x99\xe1\x25\x1d\xd6\xcb\xe2\x18\xb7\x67\x37\xa1\xab\x31\x62\x97\x15\x21\xb7\x26\x6a\xe5\xb6\xdd\x2f\x77\x2e\x67\x2a\x1d\x74\x97\x19\x73\x32\xe9\x8a\xca\x56\x55\xae\xd3\x1d\x00\xca\x3f\x59\x84\x49\xb8\xf2\x16\x7c\xef\xcb\x84\x2f\xfe\x54\x3f\x26\xf1\xc2\x68\x0f\x06\xe3\x67\x66\x57\xdd\x51\x51\x7e\xb9\x73\x10\xb1\xbd\x1b\x5d\x62\x82\x29\x73\xac\xa9\xd0\x61\x77\xaf\x87\x07\xc3\x13\x63\xd8\xfe\x5c\x55\x96\x74\xf3\x7c\x50\xcc\x8b\x37\xd7\xe7\x34\x49\xaa\x7a\x23\x4f\x22\xe1\xdd\xb2\x12\x4a\x2c\x9a\x4e\x54\xd7\x29\x6f\xcd\xc9\x17\xc9\xdc\x4e\xc2\x7d\x50\x69\xae\xef\x14\x0b\x32\x4a\xa6\xa3\x9b\xad\x35\x03\x7c\x24\x74\xa3\x48\x66\xe1\xb7\x6c\x08\x22\x0c\x10\x3e\x2c\x85\x20\xbb\x14\x45\x0d\x86\x23\x50\xe8\x3e\x9f\x0e\xae\x3d\x72\xac\x4e\x9d\xcd\xe2\xf0\xa6\xeb\x51\xc5\x65\xe7\x17\xeb\xe2\xa9\xd7\x79\x72\x70\x50\xfe\x7e\xa1\x1f\x1e\xb6\xea\xa5\xe8\xcd\x83\xee\x3a\x3c\x3c\xfc\x68\xf3\x30\xf2\x62\x51\x67\x67\x61\x86\xc4\x80\x8a\xc5\xc9\xc0\xa9\x8b\x9f\x21\xca\xa8\x70\xf3\xec\xa7\x42\x25\x30\xf5\x4a\xb3\x8a\xe4\xa6\x8e\x93\xd8\x0a\xa9\x4c\x31\xea\x5d\x50\x71\x5d\x31\x83\xe4\x5c\x21\x0f\xb1\x0f\x11\x79\xf1\xa2\x29\xd2\xc5\x5e\x72\xb9\xd8\x23\xeb\xed\xbd\x87\xa7\x06\xd1\xcd\xcc\x23\x3f\xe9\x8d\xed\x61\x5b\xe7\x22\xf0\x58\xfd\xf9\x63\x7b\xf9\x5a\xe6\xa4\x82\x9e\x56\x93\x12\x65\x53\xfa\xa5\x02\x55\xc7\x6e\x79\x41\x7a\x2b\x7c\xcb\xb9\x65\x31\x84\x42\xd3\xa3\x83\x90\x3c\xf1\xd4\x35\xff\x0a\x23\x43\x54\x16\xea\x7b\x41\xe9\x9d\xe5\xb4\xba\xf2\x92\x9a\x51\x5c\x54\x16\xad\xff\x9f\xc5\xfd\xad\xba\x5e\x7f\x20\x29\x15\x9f\xa6\x80\x2e\x52\xb3\xcb\x2f\xf2\x05\x3d\x58\xb0\x3d\xfd\x3e\xf3\x52\xa5\xbf\x99\xa6\x22\xa5\x87\x4e\x1a\xd2\x95\xe0\xed\xec\xac\x25\x18\x03\xf3\xa9\x49\x2c\x45\xbd\x1a\x25\x53\x29\x6d\xa3\x54\xd7\x97\x65\x74\x0c\xcd\xa2\xfd\xbc\x9c\xb6\x99\xa0\x8c\x71\x7b\x34\x35\x6e\x87\x7e\xac\x2b\x3c\x8d\x3c\x92\x2e\x2b\x05\xdc\x02\xde\x8d\xa1\x2c\x15\x19\x9e\xef\xcb\x6b\xf2\x40\x15\x83\x82\xa0\x81\xee\x06\x0a\x6a\xf0\xe0\xed\x7c\x33\x18\xf7\x5d\x7b\x3c\xd5\x75\x6a\x01\x56\x14\xc9\x11\xa0\xb5\x12\xce\x74\xc3\x80\x53\xa4\xdd\xec\xc8\x50\x36\x6d\xe9\x68\xa6\x4f\x41\x4e\x69\x67\x65\xe9\x0d\x94\xc8\x65\x38\xcf\xde\x25\xe7\xe0\x09\x48\x8b\x17\x43\x20\xfb\xe4\x13\xbc\xd5\xd9\xc1\xc3\x47\x15\x90\x71\x9d\x53\xab\xa7\xbe\x4b\x3d\x51\x39\x6c\x41\x48\xa8\xb4\x0e\x50\xc9\xac\xdf\xd6\xab\xdb\xb6\x06\xcf\xdf\xd2\xcc\xbc\x49\xc2\x54\x61\xc7\x5a\xd2\x76\x48\x00\xed\xe5\x7e\xc0\x23\x4e\x57\x9b\x73\xba\xf1\x5c\x61\xdb\x34\x62\xd7\x5c\x8f\xd5\x66\x36\xd7\xcf\x95\x63\x8e\xef\x3a\xe3\xb8\x7a\x6a\x36\x2f\x08\xaa\x66\xa7\x84\x66\xfa\xd3\x69\x61\x8f\x15\x92\x32\x10\xf8\x0e\x2a\x61\x9b\xa0\x32\x23\xb3\x33\x75\x91\x8f\x87\x4e\xf5\x5b\xda\x14\xf3\x11\x6b\xe9\x46\xb6\xba\x76\xa9\x30\x61\x08\x89\xb0\xdc\xbb\xa4\x56\xc9\x49\x11\x16\xe0\x76\xe4\xf2\x39\xd0\x51\xc7\x7e\x1e\x24\xb7\xfc\x9e\x86\x54\xbf\x6e\xe2\x1d\x02\x4e\xab\xc4\xbb\xf8\x3e\xb9\xf9\xea\xa0\x90\xe4\x96\x95\xa8\xb1\x6a\xa5\x77\xdd\xb9\xed\x6e\xa0\x1b\x7a\x8b\x18\xcb\x85\x7e\x69\xba\xe2\x56\x88\xc8\x43\xad\x72\x3f\xf7\xce\x81\xb7\x2e\xec\x0a\xe2\xfe\xbb\xde\x77\xa8\xd3\xe5\xc4\x5d\xb7\x5f\x9e\xc4\x36\x3f\x17\x98\xf7\xa2\xb6\x5f\xbd\x65\xa9\xd5\x6b\x07\x3b\xef\xe7\x74\x26\x26\xdd\x9c\x3a\x15\xb3\x6d\x60\xf7\xb6\xe9\xb6\x1f\xac\xb6\xe6\xdb\xfd\x70\xc5\x76\xbe\x21\x19\x5d\x9b\x64\xab\x71\x27\x98\x17\xd0\x2d\xe1\x0d\x92\x8a\xde\xde\x91\xfa\x04\x75\x44\x7f\x3e\xdd\x7c\x9c\x56\xd7\xdd\x7f\x02\xe8\x4d\x41\x58\x8f\xf3\x6c\xfe\xc4\x20\xaf\x51\xf9\x04\xdc\xf8\x5c\xc5\x43\xdf\x9a\xba\x5d\xab\xd7\xdb\x8d\x7e\xba\xf1\x4d\x17\xb9\xe6\x4a\xe4\xed\x2a\x33\xc0\x8a\x1f\x60\x22\x5b\xf8\x1f\x94\xcb\xd6\x1a\x0d\x6f\x41\x3b\x94\x30\x20\xc3\x0b\x10\x8d\xb2\x09\x25\x3a\x95\x0e\x45\xbc\x49\x78\x61\xd6\x90\xfe\x4a\x95\xb0\x81\xf0\xa5\x6a\x58\xf8\x7b\xfb\xcd\xc7\xcd\x87\xc4\x78\xdb\x76\x9f\x36\xa0\xae\x66\xb0\xca\x92\x7b\x11\xdd\x91\xd3\xfd\x79\x53\xed\xb8\x39\x97\xfe\xe5\xf9\x5b\xdc\xcc\x54\xdf\x28\x35\xaf\xdf\x16\xa5\x4b\x91\xa7\x5b\x7a\xa1\x30\xea\xc3\x66\xb5\x26\x3d\xf8\xf0\xdd\x5a\xd2\x62\x55\x3d\xf3\x38\x25\x3a\xa5\x2a\x80\x46\x23\xf3\x16\xf2\x77\x51\x94\xa4\x15\xaa\x6e\xf4\x7c\x11\xee\x3f\x21\x98\x69\x8f\x54\x03\x8f\x1b\x33\xa7\xfe\xe3\x65\xa3\x33\xa2\xbf\xa7\x67\xf5\x80\x37\xba\x66\x7d\x9e\x36\x7a\x76\x3d\x8e\x1a\xa3\x41\x3d\xba\x6a\x0c\x9e\xd6\xd3\xbc\x61\xcf\xea\x5f\x7a\x8d\x1f\x4d\xea\x5c\x36\x4c\xa7\x9e\x64\x8d\x13\xbb\x9e\x44\x8d\xc9\xa0\x7e\xb1\x68\x9c\xf4\xd5\x67\x4a\x92\x6a\x02\xa0\x42\xb9\xac\xff\xfa\x5f\x7f\xf2\xcd\x7f\xfd\xd5\x37\xbf\xf8\xd9\xb7\x7f\xfd\xe7\xf5\x5f\xff\xf2\xab\xff\xf9\xe7\x9f\x16\x2f\x5d\x9e\x67\xd2\x5f\xd6\x7b\xa9\x17\x7f\xfd\x8f\x5e\x28\xeb\x23\x8e\xb2\x14\xf4\x04\x35\xfd\xc0\xcb\xae\x42\xfe\xdf\x7f\x9f\xd7\x5f\xff\xdd\x9b\x3f\x7b\xf3\xd5\x9b\xaf\x5e\xff\xea\xf5\x2f\x5e\xff\xb2\xfe\xed\xdf\xfc\xc3\xb7\x7f\xfb\x2f\xbf\xf9\xb7\x9f\xd5\x4d\x99\x78\x5f\xff\x5c\x44\xf5\x09\x98\x5a\xbe\xc8\xbf\xfe\x27\x89\xc7\x48\x5e\x86\xf5\xd7\x3f\x7f\xf3\x17\xaf\xff\xf3\xf5\x7f\xbc\xfe\xf7\x37\x3f\xd1\x33\xe9\x66\x85\xdc\xfc\xdc\x70\x4e\xc7\xcf\xdc\x1e\x28\x0d\x12\xfc\x89\xad\x3f\xeb\x96\x70\xf6\xbf\x01\x00\x00\xff\xff\x23\x26\x74\xa7\x0a\x23\x00\x00") +var _confAppIni = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\xb4\x59\x4f\x93\xdb\x46\x76\xbf\xe3\x53\xb4\xe8\x38\x96\x52\x24\xe7\x9f\xf5\xc7\x63\x4f\x62\x0e\x09\x72\xb0\x22\x09\x1a\x20\x25\xcb\xaa\x29\x08\x03\x34\x49\x78\x40\x34\x84\x06\x66\xc4\xad\x1c\xd6\x95\x43\xaa\x72\x4c\xb6\x92\x4b\x0e\xc9\x21\x95\xaa\x24\x9b\x64\x2b\x97\xdd\x4d\xe5\xe4\xca\x5d\xfa\x0e\x2e\xef\xe6\x5b\xe4\xf7\xba\x01\x12\x1c\x8d\xb5\x5e\x27\x5b\x52\x0d\x81\xfe\xf3\xba\xdf\xeb\xf7\x7e\xef\xf7\x1a\xef\xb1\xb1\xf9\xc4\x74\x98\xfa\x33\xb2\x7b\x56\xff\x19\x9b\x9e\x59\x2e\xeb\x5b\x43\xd3\x78\x8f\x4d\x86\x66\xc7\x35\xd9\xa8\xf3\xd8\x64\xdd\xb3\xce\x78\x60\xba\xcc\x1e\xb3\xae\xed\x38\xa6\x3b\xb1\xc7\x3d\x6b\x3c\x60\xdd\x99\x3b\xb5\x47\x68\x1c\xf7\xad\x81\x9e\x69\x7c\xcc\x3a\x69\xca\x12\x7f\xc5\x59\xbe\xf4\x73\x26\x97\xe2\x5a\x32\x91\x30\x7e\xc5\xb3\x35\x4b\xfd\x05\x3a\xa2\x3c\xe6\x46\x67\x32\xf1\xc6\x9d\x91\xc9\x4e\xd8\x40\x2c\xe4\x31\xfe\xb2\x41\x94\x33\x97\x67\x57\x51\xc0\x21\xa9\xbb\xf4\x13\x0c\x47\x5b\x34\x67\x6b\x51\xb0\xac\x48\x58\x2c\x02\x3f\x8e\xd7\x86\x33\x1b\x7b\x33\x17\xbb\x3f\x61\x8b\x28\xc7\x68\x33\xca\x97\x3c\x63\x8d\x90\x5f\x35\x9a\xac\x91\x66\x22\x6c\x30\x81\x86\x9c\xcb\x1c\x2d\x21\x9f\xfb\x45\x0c\x59\x52\x8f\x51\x12\xa0\x3a\x6d\x00\xef\x86\xf1\x3c\xe3\xa9\x90\x51\x2e\xb2\xf5\xb9\xe1\xd8\xf6\x94\x9d\x18\x6e\xd7\xb1\x26\x53\x6f\xfa\x6c\x42\xc3\x2e\x7c\xb9\xc4\xb8\x22\x3a\xc7\x7a\xe3\x62\x75\x81\xf5\xc4\x1c\x12\x65\xc1\xa5\xd6\xd7\xcf\xb8\xd2\x99\x87\x2c\x4a\xa0\x37\x57\x2a\x1b\x96\xeb\xce\x4c\x6f\xd2\x19\xc0\x6e\xde\x78\x36\x82\xb0\x83\x7d\x88\x92\x50\x96\x67\xe7\xc6\xc4\xb1\xa7\x76\xd7\x1e\xa2\x7d\x99\xe7\xa9\xd1\xb3\x47\x1d\x6b\x8c\x37\xa5\xee\x52\xc8\x5c\xed\xc8\x9b\x39\x34\xe4\xfd\xbb\xd5\xf8\x7b\xf2\x78\x6f\xef\xfd\xbb\x7a\x38\x5e\xde\xbf\x7b\x36\x9d\x4e\xbc\x89\xed\x4c\xef\xc9\x3d\x43\xbd\x74\x7a\x3d\x58\xc9\xd8\x74\x40\xc0\xd1\xfe\xfe\x3e\x54\xe8\x45\xd2\xbf\x88\x39\x73\xdd\x33\x36\xe7\x7e\x5e\x60\xf3\xd7\x4b\x9e\xb0\x44\x40\x93\x2b\x3f\x8a\xa9\xdb\xe8\x59\x6e\xe7\x74\x68\x7a\x34\xec\x84\xcd\xfd\x58\x72\x03\xcf\x95\xb0\xc3\xc3\x9a\xa8\x6e\x6f\x4c\x47\x9d\x90\xf6\xe5\x19\xac\x44\xc8\x0d\xbb\xdf\x1f\x5a\x63\xb3\x32\xb8\x16\x52\x09\x76\xec\xd9\xd4\x74\xbc\xa1\x3d\xd8\x74\x7d\xcc\x06\x3c\xe1\x99\x9f\xc3\x9c\x39\x4f\xe5\x31\x5a\xfe\x80\x05\x21\xcc\x99\x2f\xf7\x72\xb1\xb7\x80\xcf\xec\x05\x85\xcc\xc5\x6a\x8f\x4c\x26\xd5\x80\xb6\x6a\x67\x01\xcf\x72\xd6\x0a\xfc\x93\x3c\x2b\x38\x6b\x85\x05\x04\x45\x22\x39\x79\xf4\xf0\xc1\xfe\x72\x7f\xb5\x2f\x59\x8b\x6c\x7a\xb2\x5a\xd3\x4f\x9b\xbf\xf2\x57\x69\xcc\xdb\x81\x58\x19\x1f\x43\x8e\x9d\xb1\x79\x26\x56\xcc\x67\xed\x74\xfe\x8a\xcd\x23\x28\xc6\x5f\xa5\x22\xcb\x71\xac\xaa\x07\xae\xc6\x9e\x46\x49\x48\xce\x4d\x8b\x45\xf3\x28\xd0\x7b\x15\xb0\xe1\xdd\x50\x40\x0a\x19\x71\x2e\xb2\x05\xcf\x59\x2e\xca\xf9\x6a\x62\x9a\x45\x57\x34\xf8\x92\xaf\xef\x69\xbd\x44\xca\x13\x29\x63\x96\x5e\x06\xf2\xe0\x90\xb5\x60\x3c\x92\xaa\x56\x6f\x89\x22\x2f\xdf\xf8\x8a\xb5\x12\x81\x69\xf2\xfb\xcd\xc2\xc8\x6a\x12\x75\x48\x7a\x08\xb9\x34\xba\xa6\x33\xf5\x28\x5e\x61\xee\xba\x09\xf7\xaa\x65\x8c\xc7\xe6\xb3\x5b\x07\x94\x12\xb1\xfc\x2c\x4d\xe1\xfd\x31\xce\x3a\xa6\x18\xc8\x39\x2c\x48\x4a\xf9\x49\x08\x2b\xc0\xdc\x81\xb6\x1b\x9d\x17\x86\xd7\xa2\x4f\x99\x00\xad\xe4\x6a\x30\x16\x05\x3f\x35\xf3\x57\x3c\x28\x60\x60\xc3\x9d\x76\xa6\x56\xd7\x53\xfe\x3e\xe9\x4c\xe1\x73\x1a\x55\x62\x32\x31\x4e\xb1\x5c\x74\xf0\x85\x35\x61\xb2\x48\xc9\xac\x86\x39\x56\x8e\xa4\xda\xb6\x2e\x34\xc4\x66\xa2\x64\xa1\x51\x07\x47\x81\x23\x49\x5a\xb1\x58\x2c\x70\x8c\x05\x42\x4f\x36\x59\xe0\x27\xec\x82\xb3\xc6\x52\xac\xb8\x86\x0b\x1c\x54\x8c\x43\x6c\x18\xc3\x8e\x82\x39\x8a\x5a\xb2\x03\x8d\x40\xc4\x86\x7e\xee\x03\x07\xf8\x79\x0d\x72\x56\x6b\xf9\x32\x56\xa0\x03\x6f\x5a\x64\x5c\x6a\x49\x68\x8c\x72\x7e\x84\x8e\x28\xff\x40\x12\x82\x65\x2c\x58\x0a\x02\xb7\xde\x69\x85\x29\x6a\xae\x71\x66\xbb\x14\x4a\x07\x87\x0f\xdb\xfb\xf8\x77\x70\x7c\x74\xb4\xff\xc0\x28\xe1\x91\x5c\xda\x28\xb1\x2e\x13\x22\x37\x26\x1d\xd7\x7d\xda\x53\x76\xe9\xd3\x42\xb5\x65\x93\x78\xdd\x64\xbc\x82\x42\x1d\x94\xb4\xb3\x8c\xbf\x2c\xa2\xac\x54\x11\x90\x13\xcd\xd7\xad\x79\x11\xc7\x0d\x44\xf2\x70\x03\x83\x7a\x7c\x25\xb6\xda\xbf\x92\x6a\xe8\xa3\x60\xa4\xbf\x0a\xb2\x76\x78\x01\x73\xf8\xe1\x2a\x4a\xce\x15\x92\x05\x45\x16\xe5\x80\x4e\x6b\x8c\x13\x1c\x0e\x11\xce\xdd\xc7\xb5\xc3\xb8\x73\x47\x27\x12\x9d\x67\xa6\x36\x7b\x6c\x9a\x13\xf6\xcc\x9e\x39\x4c\xe9\xd6\xeb\x4c\x3b\xcc\xed\xf4\xcd\x3b\x77\x0c\xd7\xec\x3a\xe6\xd4\x83\x17\x42\xc0\x9d\xf7\x3e\xed\xf7\xcc\xa7\x0e\xfe\xff\xe1\x1f\xdd\x25\x5f\x28\x72\x41\xc7\x08\x7f\xcf\xf8\x8a\x2b\x18\x0e\x7d\x04\x05\x00\xc4\x1a\x7b\x8e\x39\x32\x47\xa7\xc0\x93\x5e\xe7\x99\x8b\xf9\x0f\x8d\xae\x6d\x3f\xb6\x4c\x95\x2e\x6a\x26\xf5\xfc\x6b\x2e\xe9\x50\xcb\xee\xcd\xbc\xfa\x98\x28\x09\x32\x1e\x46\xda\x2a\x0e\x25\x31\x49\x01\x2c\x5e\xad\x99\x5f\xc0\xca\x49\x5e\x79\xe5\x92\xfb\x21\x36\xa2\x52\x1f\x02\x82\xfc\x4b\xbd\x18\x0e\x25\x59\x17\xe8\xef\xd8\x9f\x3f\xf3\x3a\xb3\xe9\x99\x39\x86\x83\xc3\xc9\xed\x4d\x0a\xfb\xbc\xf5\xd4\x3c\xa5\xae\x16\x35\x94\x89\x01\x8e\x72\x6e\x74\xba\x53\xeb\x89\xe9\x75\x71\x42\xde\x90\x9e\x46\xd6\x18\x68\x49\x8a\x1d\x3c\xda\x87\x70\xd7\xa4\x30\x21\x87\xf8\xce\x41\x88\x56\xb5\x1b\x0e\xbf\x07\x14\x05\x22\x99\x47\xd9\x8a\xf1\xd6\x0a\x10\xaf\x02\x23\xe3\x8b\x48\xe6\x1a\x25\x21\x73\x60\xb9\x04\xc8\x26\xb2\xca\xd0\x53\xf9\xdd\x19\xd5\x8e\xb2\x27\x90\xee\x54\x8e\x88\x63\x71\x5d\x4e\xc6\x02\x14\xfb\xca\x21\x18\x8c\xa6\xc0\x20\x08\x44\x91\xe4\xda\x81\x36\x68\xaf\xc4\x3b\x4a\xff\x9a\x50\xb5\xc5\x15\xc0\x86\xc9\x68\xa1\xf2\x07\xb6\x7a\x15\xf1\x6b\x88\x5d\xe7\x4b\xc4\x71\x1b\x3b\xfb\x6c\x66\x39\xc8\x44\xd6\x60\x8c\x93\x7e\x62\x99\x4f\x6b\x12\xba\x7e\x00\x68\x41\xde\xca\x7d\xec\x45\xb2\x34\x0a\x28\xa5\x55\xe0\xd0\xed\x74\xcf\x4c\xaf\xf3\x04\x7e\xe6\xd4\x66\x8d\xc8\x06\x50\x46\x43\x38\xe9\x5f\x8e\x1f\xdb\x53\xd0\x22\x8f\x6c\x50\x1f\x4e\x00\x1f\xf2\x1c\xb3\x8e\x55\xae\xa6\x0c\x0c\x06\xb2\x2c\x2e\x28\x7f\x50\x68\x44\xb9\xd4\xe9\x49\x13\x83\xbd\x83\x07\xf7\x2b\x99\xef\xf2\x85\xcd\x22\xdf\x35\xd6\xfe\x2e\xd3\xf5\x84\x3a\x0d\x68\x1f\x5c\x32\x98\x3f\x5a\x15\x2b\x02\x7f\x58\xf2\xc7\xc8\xe8\xd8\x1c\xce\x3c\x03\x40\xa4\x42\x03\x62\xbe\x4e\xb7\xd9\x17\xbe\x62\x8d\x66\x23\x8a\x36\x18\xf6\x0b\x18\xea\xcc\xac\x45\xae\xf1\xfc\x9a\x5f\x2c\x85\xb8\x24\xc4\x3b\xc3\x2f\xcb\x7d\x79\xc9\x5e\x16\x1c\xa9\x35\xe6\xc9\x02\xf8\xfe\xd9\xcc\x04\xbd\x19\x9a\xe3\x81\xc2\x88\x83\x92\x5e\xf0\x38\x42\xc0\x80\xef\xad\x38\xa5\x23\x1c\x29\x50\x02\x5b\x90\x46\xcf\x24\x37\x75\xbc\xa9\x35\x32\x91\xfc\x31\xe7\x3e\x05\xb6\x72\xa7\x28\x51\x58\xc2\x6b\x89\x95\x4e\xc5\x7d\x6c\x4d\xbc\xe9\xd0\xf5\x30\x8f\xe8\xea\x76\x7f\xe4\xc5\x44\xa2\xb4\xdd\x7a\x35\xc3\x9c\x16\xf3\xb9\xca\x52\xb4\x4b\x8a\xca\x00\x94\x32\xe1\x71\x13\xd6\xe1\x29\x31\x4b\xb8\x49\xa4\xb2\x52\x49\x31\x43\x91\x7c\x80\xc4\x99\x60\x1f\xd7\xc4\xe7\x54\x67\x1b\x80\x34\xee\x79\xa7\xb3\x7e\x9f\x68\x8a\x39\xd6\xf4\x0d\x1c\x90\x82\x1d\xa8\x89\xd4\xb7\xd6\x8c\x4f\x45\x94\x26\xb8\xee\xec\xf4\x47\x66\x77\xaa\xf8\x5a\x45\x76\xef\xc9\xca\xe3\x34\xf3\x23\x9e\xb3\x52\xae\x24\x57\x79\xda\x5e\xd0\x33\xb9\xd1\xf1\xfd\x47\x0f\xd1\xf7\xd9\x67\x65\xc7\xcb\x97\xaa\xf5\x90\xac\x34\x16\x39\x6f\xd2\x7e\x55\x22\x25\x52\xc1\x61\x52\x7d\xcc\x8d\x0f\x1f\xdc\x07\xdc\xbb\xa3\xe9\xc4\x45\x4b\x1c\x53\x72\x03\x14\x85\x6d\xc4\x17\x9d\x3c\xa0\xd9\x99\xc2\x8a\x44\xc9\xd5\x5c\x2c\x44\xea\x67\x38\x98\xd5\x0a\x82\xa0\x06\x25\x76\xa7\xdf\x65\x0f\x3e\xdc\xff\xa8\xcd\x2c\xbd\x90\xde\x6f\x95\x70\xe5\x56\x10\x2c\xa4\x16\xf2\xe3\x6b\x60\xf0\x66\xbd\x2a\xa5\xd5\xb8\xe1\x99\x39\xb4\x89\xb4\x68\x98\xd1\x4c\x93\xf8\x97\x82\x4c\x22\xce\x61\x44\xc7\x05\x4c\x6d\x6f\x9c\x53\xcd\x51\x52\xba\x8a\x87\x6c\x27\x10\x6c\xed\x4a\xdc\xe1\xf8\x8a\xa6\xc9\x35\x70\x69\x85\xbd\x60\x9c\x47\x1b\x2a\xa1\x7d\x1b\x33\x3a\x15\x2a\x0d\xeb\x3c\x4e\xd4\x95\x6e\x33\x1b\xf8\x45\x6a\xa1\x91\x44\x63\x65\xc9\xe3\x79\x8b\x80\x0a\xf6\xaa\x4d\x94\xda\x4d\x37\x2e\xaa\x71\x8d\x05\x71\x04\xad\xea\x03\x29\x9f\x7b\xc4\xc3\xac\x3e\x85\xff\x96\x13\xdf\xc2\xcd\xb4\x7f\xbf\x8b\x9c\x95\x23\xb6\xec\x4c\xb9\x98\xe6\xb0\x61\x88\xc0\x07\xd3\xa1\x13\xbd\x7f\x74\x78\xd8\x66\x53\x52\xa2\x24\x3e\x5f\x12\xe0\xe2\x91\x2b\xc7\xdd\x0c\x86\x86\xa4\x7f\x83\x1c\xbc\xc1\x3e\x51\xbd\x9f\xd6\x68\xf2\x1f\x93\x11\x56\x88\x0f\xa3\xef\xa0\x04\x3c\x29\x97\x84\x83\x6c\xf2\x9e\xca\x06\xa9\x2f\xe5\xb5\xc8\xc2\x92\xbe\x6c\x99\x8b\xf1\x5c\x50\xfe\x7c\x3b\x68\xcb\x8e\xb6\x86\xd4\xb7\xfb\xbb\x43\x0b\x90\xe9\x59\x24\xa4\x7c\xd6\x6c\x41\x55\x6b\xf6\x44\x25\xbd\x0a\x97\xfd\x34\x6a\xd7\xb0\x99\xf6\x66\x10\xe8\x96\x75\xd4\x2d\xf0\xad\x68\xc5\x9e\xda\xc2\x1e\xfd\x11\x19\x20\xd4\x98\xda\x8f\xcd\xf1\xf7\x9c\x14\x04\xb0\xa0\x97\x83\xa6\x27\x86\x2a\x63\xf2\xea\xf8\xa3\x50\xb3\x63\x8e\xec\x98\xab\xd3\x41\x7f\x25\x0e\xb8\x28\x05\x8c\x1b\x12\xb9\x25\x97\x96\xed\x85\x10\x0b\x6d\xee\x3d\x30\x8e\x2f\x79\x90\x6f\x8c\xa3\x7a\xfe\x8f\xc6\xb9\xbe\xbe\x2e\x05\xc1\x4c\x52\x2d\xa3\x34\x20\x2b\x45\xc9\x5c\xb4\xb5\x4f\x7c\xef\xe1\xd8\x23\x31\xfe\xdb\x0c\x5c\xf2\x80\x1d\x95\x84\x36\xd8\xa1\x92\x72\xab\x85\xdf\x39\xab\x34\x70\x69\x90\x97\x2f\x7f\xa0\x31\x50\x9d\x79\xa4\x81\x47\x2a\x28\xc4\x65\xdf\xfc\xea\x2f\x7f\xf3\xd5\x4f\x6f\xf5\x93\xcc\x4f\x97\x25\x16\x97\xfb\x68\xef\xff\x36\x37\xb9\x75\xce\xee\xee\xaf\x79\x74\x21\x7e\xa0\x02\xa0\x60\xb7\x5a\x1c\x9e\xaf\xc4\xd6\xd6\xfd\x2d\x3b\xbd\x7d\xca\x8e\x3b\x3f\x0f\x88\x62\xed\x94\x3e\x7c\x25\xb2\xb5\xae\x30\x90\x08\x1b\x0a\x3a\xa8\x55\x8d\xbc\x71\xed\x52\x0e\x36\x3a\xbd\xce\x64\xaa\x78\xaf\x6e\xa9\x0a\x8e\xb2\xbf\xac\x62\x06\x5d\x24\x54\xd0\xca\x2b\x3f\xae\x51\x87\x1d\x89\x0f\xf6\x51\x6d\x40\xd2\x93\x0e\x29\xf2\x60\xbf\x12\xa4\xf7\xa2\xa2\xad\xbe\x17\x08\x48\x10\x45\x8a\xad\x0b\xc2\x3d\x0d\x77\x98\xa5\x26\x1c\x83\x21\xe7\x40\xab\xcb\x93\x3c\x48\x9b\xd4\x79\x72\xfc\xe0\xe8\xe1\x47\xcd\x0a\xc5\x4e\x56\x7e\xe0\x67\x48\x34\xe1\xc5\xc9\x7e\x33\x15\x22\xf6\x88\x61\x9d\x80\xef\x34\xa3\x30\xe6\x5e\xc9\x74\x4e\x34\xe9\xae\x56\x3e\x66\x2f\xb6\x85\xdd\xc1\xc1\xe1\xc1\xc1\x8b\x32\x3b\x2a\xa2\x2f\x25\x36\x74\xbb\x4d\x29\x9e\xb6\xb6\xd5\xa6\x2d\x6b\xcd\xdb\xec\x0a\xa6\xf8\xc4\xea\xed\x1a\x76\x92\x89\xab\x88\x0a\x13\xc5\xfa\x17\xc8\x96\xa4\xbf\xd4\xdb\xc3\x90\x63\x95\x06\x97\xfe\x15\x01\xf6\xba\x1a\xb5\xe6\x74\xa5\x46\xcb\x83\x80\xe8\x1d\x6e\xcb\x79\x14\x98\xed\x45\x9b\xbd\x50\xa5\x60\xd9\x2b\x5f\xfc\xde\xac\x48\x0a\x1f\xa3\x1a\x6b\xe1\xb7\x15\x66\x44\x29\xf7\x54\x23\x0b\x65\x52\x6d\x18\xc5\x0b\xe8\x4d\xb5\x33\xaa\x92\x8f\xab\xf5\x3e\xad\xf6\xe8\xe5\x44\x43\x5e\x6c\xcc\xe4\x95\x37\x97\x65\x51\x5b\x69\x82\x35\xdd\x52\xe5\x00\x74\x37\xe2\xba\x8c\x2b\xab\xc4\x92\x41\x44\x5e\x1c\x5d\x72\x4f\xb3\x7d\xcc\xb0\x34\x7d\x24\x8e\x50\xd9\x0b\x3e\xab\x42\xab\x74\xe7\x3a\x37\xd1\xe1\xad\x05\x22\xa4\x67\x8e\x59\x23\xad\x66\xa2\xd8\x92\xa4\xc4\xa1\xd6\xdf\x99\x4b\x37\x5a\x55\x85\x40\xa5\x9f\x96\x82\xe9\xaa\x63\xbb\x75\x44\x0f\xd9\x71\x13\x42\x3b\x42\x1e\x81\xda\xed\x1b\x83\xae\x57\x45\x8f\x22\xe2\x10\xa2\x3b\xb6\x52\xe2\x68\xce\x95\x9c\x5b\xa6\xbb\xa6\xeb\x52\x09\x3b\xb4\xfa\xe6\xee\x7c\xe3\x79\x59\x7a\x91\x57\x4f\x89\xa5\xc6\x7e\xc0\xa9\x9e\x2b\xdb\x95\xc1\xb7\xf7\x14\x9a\x66\x69\xff\x7e\x89\xf2\xa5\xb8\xe1\xdf\x65\x3f\x56\x74\x9e\x58\x5d\x5a\xa7\x64\xcf\xba\x98\xf3\x66\x93\xa1\xdd\xe9\x79\xf5\x1b\x0a\x5d\x05\x4a\x75\x8b\x1c\x25\x5c\x72\x7d\xe1\xa3\x68\x4f\x80\x6a\x06\x0d\x8d\xb0\x10\x72\x59\x88\x86\x31\x70\x4a\x41\xae\x3d\x73\x94\x7c\xa0\xb6\x12\xb0\xe1\xa1\xd5\x90\x1a\x4f\xf1\xf3\x1c\xd1\x0d\xce\x9c\x93\x9a\x4f\x97\x5c\x29\xb3\x6d\x95\x8a\xd3\x72\x75\x9a\xe0\xdf\x3d\xad\x90\x24\x33\xbc\xa0\xc3\x7a\x51\x1e\xe3\xf6\xec\x26\x74\x2b\x46\xec\xb2\x26\xe4\xc6\x44\xad\xdc\xb6\xfb\xc5\xce\xbd\x4c\xad\x83\xae\x31\x13\x4e\x26\x5d\x51\xc5\xaa\x2a\x75\x2a\xff\x51\xf9\xc9\x32\x4c\xa2\x95\xbf\xe0\x7b\x5f\xa6\x7c\xf1\xa7\xfa\x31\x4d\x16\x46\x67\x38\xb4\x9f\x9a\x3d\x75\x3d\x45\xf9\xe5\xd6\x41\xc4\xf6\x5e\xe9\xea\x12\x4c\x99\x63\x4d\x85\x0e\xbb\x7b\x3d\x3a\x1c\x9d\x1a\xa3\xce\xe7\xaa\xa8\xa4\x4b\xe7\xc3\x72\x5e\xb2\xb9\x39\xa7\x49\x52\xd5\x1b\x45\x1a\x0b\xff\x86\x95\x50\x62\xd1\x74\xa2\xba\x6e\x75\x61\x4e\xbe\x48\xe6\x76\x53\x1e\x80\x4a\x73\x7d\x9d\x58\x92\x51\x32\x1d\x5d\x6a\xad\x19\xe0\x23\xa5\xcb\x44\x32\x0b\xbf\x61\x43\x10\x61\x80\xf0\x51\x25\x04\xd9\xa5\x2c\x6a\x30\x1c\x81\x42\x57\xf9\x74\x70\x9d\xb1\x6b\x75\x9b\x6c\x96\x44\xaf\x7a\x3e\x55\x5c\x4e\x71\xb1\x2e\x9f\xfa\xdd\x47\x87\x87\xd5\xef\x17\xfa\xe1\xfe\x7e\xb3\x12\xbd\x79\xd0\x5d\x47\x47\x47\x1f\x6d\x1e\xc6\x7e\x22\x9a\xec\x71\x94\x23\x31\xa0\x62\x71\x73\x70\xea\xf2\x67\x84\x32\x2a\xda\x3c\x07\x99\x50\x09\x4c\xbd\xd2\xac\x32\xb9\xa9\xe3\x24\xb6\x42\x2a\x53\x8c\xfa\x17\x54\x5c\xd7\xcc\x20\x39\x57\xc8\x43\xec\x43\xc4\x7e\xb2\x68\x8b\x6c\xb1\x97\x5e\x2e\xf6\xc8\x7a\x7b\xef\xe1\xa9\x45\x74\x33\xf7\xc9\x4f\xfa\xb6\x33\xea\xe8\x5c\x04\x1e\xab\xbf\x7c\x6c\xef\x5d\xab\x9c\x54\xd2\xd3\x7a\x52\xa2\x6c\x4a\xbf\x54\xa0\xea\xd8\xad\xee\x46\x6f\x84\x6f\x35\xb7\x2a\x86\x50\x68\xfa\x74\x10\x92\xa7\xbe\xba\xe1\x5f\x61\x64\x84\xca\x42\x7d\x2a\xa8\xbc\xb3\x9a\xd6\x54\x5e\xd2\x30\xca\x3b\xca\xb2\xf5\xff\xb3\xb8\xbf\x51\xd7\xeb\xcb\x8b\x4a\xf1\x69\x06\xe8\x22\x35\x7b\xfc\xa2\x58\xd0\x83\x05\xdb\xd3\xef\x53\x3f\x53\xfa\x9b\x59\x26\x32\x7a\xe8\x66\x11\xdd\x06\xde\xcc\xce\x5a\x82\x31\x34\x9f\x98\xc4\x52\xd4\xab\x51\x31\x95\xca\x36\x4a\x75\x7d\x4f\x46\xc7\xd0\x2e\xdb\xcf\xab\x69\x9b\x09\xca\x18\x37\x47\x53\xe3\x76\xe8\xc7\xba\xc2\xd3\xc8\x23\xe9\x9e\x52\xc0\x2d\xe0\xdd\x18\xca\x32\x91\xe3\xf9\xae\xbc\x26\x0f\x54\x31\x28\x08\x1a\xe8\x6e\xa0\xa4\x06\xf7\xde\xce\x37\x43\x7b\xe0\x39\xf6\x54\xd7\xa9\x25\x58\x51\x24\xc7\x80\xd6\x5a\x38\xd3\x0d\x03\x4e\x91\x76\xb3\x23\x43\xd9\x74\x5f\x47\x33\x7d\x05\x72\x2b\x3b\x2b\x4b\x6f\xa0\x44\x2e\xa3\x79\xfe\x2e\x39\x87\x8f\x40\x5a\xfc\x04\x02\xd9\x27\x9f\xe0\xad\xc9\x0e\xef\x3f\xa8\x81\x8c\xe7\x9e\x59\x7d\xf5\x49\xea\x91\xca\x61\x0b\x42\x42\xa5\x75\x88\x4a\x66\xfd\xb6\x5e\xbd\x8e\x35\x7c\xf6\x96\x66\xe6\xab\x34\xca\x14\x76\xac\x25\x6d\x87\x04\xd0\x5e\xee\x86\x3c\xe6\x74\xab\x39\xa7\xcb\xce\x15\xb6\x4d\x23\x76\xcd\xf5\x50\x6d\x66\x73\xf3\x5c\x3b\xe6\xe4\xb6\x33\x4e\xea\xa7\xe6\xf0\x92\xa0\x6a\x76\x4a\x68\xa6\xbf\x9a\x96\xf6\x58\x21\x29\x03\x81\x6f\xa1\x12\x8e\x09\x2a\x33\x36\xbb\x53\x0f\xf9\x78\xe4\xd6\x3f\xa3\x4d\x31\x1f\xb1\x96\x6d\x64\xab\x6b\x97\x1a\x13\x86\x90\x18\xcb\xbd\x4b\x6a\x9d\x9c\x94\x61\x01\x6e\x47\x2e\x5f\x00\x1d\x75\xec\x17\x61\x7a\xc3\xef\x69\x48\xfd\xc3\x26\xde\xd5\x0d\x62\x8d\x78\x97\x9f\x26\x37\x1f\x1c\x14\x92\xdc\xb0\x12\x35\xd6\xad\xf4\xae\x3b\xb7\xdd\x0d\xf4\x22\x7f\x91\x60\xb9\x28\xa8\x4c\x57\xde\x0a\x11\x79\x68\xd4\xee\xe7\xde\x39\xf0\xc6\x85\x5d\x49\xdc\x7f\xd7\xfb\x0e\x75\xba\x9c\xb8\xeb\xf6\xa3\x93\xd8\xe6\xe7\x12\xf3\x9e\x37\x0e\xea\xb7\x2c\x8d\x66\xe3\x70\xe7\xfd\x9c\xce\xc4\xa4\x9b\x53\xb7\x66\xb6\x0d\xec\xde\x34\xdd\xf6\x5b\xd5\xd6\x7c\xbb\xdf\xac\xd8\xce\xe7\x23\xa3\xe7\x90\x6c\x35\xee\x14\xf3\x42\xba\x25\x7c\x85\xa4\xa2\xb7\x77\xac\xbe\x3e\x1d\xd3\x9f\x4f\x37\xdf\xa5\xd5\x4d\xf7\x9f\x00\x7a\x33\x10\xd6\x93\x22\x9f\x3f\x32\xc8\x6b\x54\x3e\x01\x37\x3e\x57\xf1\x30\xb0\xa6\x5e\xcf\xea\xf7\x77\xa3\x9f\x6e\x7c\xb3\x45\xa1\xb9\x12\x79\xbb\xca\x0c\xb0\xe2\x07\x98\xc8\x16\xc1\x07\xd5\xb2\x8d\x56\xcb\x5f\xd0\x0e\x25\x0c\xc8\xf0\x02\x44\xa3\x6c\x42\x89\x4e\xa5\x43\x91\x6c\x12\x5e\x94\xb7\x64\xb0\x52\x25\x6c\x28\x02\xa9\x1a\x16\xc1\xde\x41\xfb\x61\xfb\x3e\x31\xde\x8e\x33\xa0\x0d\xa8\xab\x19\xac\xb2\xe4\x7e\x4c\xd7\xe3\x74\x75\xde\x56\x3b\x6e\xcf\x65\x70\x79\xfe\x16\x37\x33\xd5\xe7\x49\xcd\xeb\xb7\x45\xe9\x52\x14\xd9\x96\x5e\x28\x8c\xfa\xb0\x5d\xaf\x49\x0f\x3f\x7c\xb7\x96\xb4\x58\x5d\xcf\x22\xc9\x88\x4e\xa9\x0a\xa0\xd5\xca\xfd\x85\xfc\x5d\x14\x25\x69\xa5\xaa\x1b\x3d\x9f\x47\x07\x8f\x08\x66\x3a\x63\xd5\xc0\x93\xd6\xcc\x6d\xfe\x78\xd9\xea\x8e\xe9\xef\xd9\xe3\x66\xc8\x5b\x3d\xb3\x39\xcf\x5a\x7d\xa7\x99\xc4\xad\xf1\xb0\x19\x5f\xb5\x86\x4f\x9a\x59\xd1\x72\x66\xcd\x2f\xfd\xd6\x8f\x26\x4d\x2e\x5b\xa6\xdb\x4c\xf3\xd6\xa9\xd3\x4c\xe3\xd6\x64\xd8\xbc\x58\xb4\x4e\x07\xea\x0b\x25\x49\x35\x01\x50\x91\x5c\x36\x7f\xfd\xaf\x3f\xf9\xe6\xbf\xfe\xea\x9b\x5f\xfc\xec\xdb\xbf\xfe\xf3\xe6\xaf\x7f\xf9\xd5\xff\xfc\xf3\x4f\xcb\x97\x1e\x2f\x72\x19\x2c\x9b\xfd\xcc\x4f\xbe\xfe\x47\x3f\x92\xcd\x31\x47\x59\x0a\x7a\x82\x9a\x7e\xe8\xe7\x57\x11\xff\xef\xbf\x2f\x9a\xaf\xff\xee\xcd\x9f\xbd\xf9\xea\xcd\x57\xaf\x7f\xf5\xfa\x17\xaf\x7f\xd9\xfc\xf6\x6f\xfe\xe1\xdb\xbf\xfd\x97\xdf\xfc\xdb\xcf\x9a\xa6\x4c\xfd\xaf\x7f\x2e\xe2\xe6\x04\x4c\xad\x58\x14\x5f\xff\x93\xc4\x63\x2c\x2f\xa3\xe6\xeb\x9f\xbf\xf9\x8b\xd7\xff\xf9\xfa\x3f\x5e\xff\xfb\x9b\x9f\xe8\x99\x74\xb3\x42\x6e\x7e\x6e\xb8\x67\xf6\x53\xaf\x0f\x4a\x83\x04\x7f\xea\xe8\x2f\xba\x15\x9c\xfd\x6f\x00\x00\x00\xff\xff\x50\xfb\xbf\xa5\x05\x23\x00\x00") func confAppIniBytes() ([]byte, error) { return bindataRead( @@ -126,7 +126,7 @@ func confAppIni() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "conf/app.ini", size: 8970, mode: os.FileMode(420), modTime: time.Unix(1437763990, 0)} + info := bindataFileInfo{name: "conf/app.ini", size: 8965, mode: os.FileMode(420), modTime: time.Unix(1437828956, 0)} a := &asset{bytes: bytes, info: info} return a, nil } diff --git a/modules/cron/manager.go b/modules/cron/manager.go index 91ae16be2..da485d23a 100644 --- a/modules/cron/manager.go +++ b/modules/cron/manager.go @@ -15,7 +15,6 @@ var c = New() func NewCronContext() { c.AddFunc("Update mirrors", "@every 1h", models.MirrorUpdate) - c.AddFunc("Deliver hooks", fmt.Sprintf("@every %dm", setting.Webhook.TaskInterval), models.DeliverHooks) if setting.Git.Fsck.Enable { c.AddFunc("Repository health check", fmt.Sprintf("@every %dh", setting.Git.Fsck.Interval), models.GitFsck) } diff --git a/modules/setting/setting.go b/modules/setting/setting.go index b2ab3b460..2364c313a 100644 --- a/modules/setting/setting.go +++ b/modules/setting/setting.go @@ -76,7 +76,7 @@ var ( // Webhook settings. Webhook struct { - TaskInterval int + QueueLength int DeliverTimeout int SkipTLSVerify bool } @@ -555,7 +555,7 @@ func newNotifyMailService() { func newWebhookService() { sec := Cfg.Section("webhook") - Webhook.TaskInterval = sec.Key("TASK_INTERVAL").MustInt(1) + Webhook.QueueLength = sec.Key("QUEUE_LENGTH").MustInt(1000) Webhook.DeliverTimeout = sec.Key("DELIVER_TIMEOUT").MustInt(5) Webhook.SkipTLSVerify = sec.Key("SKIP_TLS_VERIFY").MustBool() } diff --git a/routers/install.go b/routers/install.go index 055c1ccd8..58c38c312 100644 --- a/routers/install.go +++ b/routers/install.go @@ -68,6 +68,7 @@ func GlobalInit() { models.HasEngine = true cron.NewCronContext() + models.InitDeliverHooks() log.NewGitLogger(path.Join(setting.LogRootPath, "http.log")) } if models.EnableSQLite3 { diff --git a/routers/repo/http.go b/routers/repo/http.go index 8395d1c04..4e5aba04e 100644 --- a/routers/repo/http.go +++ b/routers/repo/http.go @@ -190,7 +190,10 @@ func Http(ctx *middleware.Context) { refName := fields[2] // FIXME: handle error. - models.Update(refName, oldCommitId, newCommitId, authUsername, username, reponame, authUser.Id) + if err = models.Update(refName, oldCommitId, newCommitId, authUsername, username, reponame, authUser.Id); err == nil { + models.HookQueue.AddRepoID(repo.Id) + } + } lastLine = lastLine + size } else { diff --git a/routers/repo/setting.go b/routers/repo/setting.go index 756f29792..c37148081 100644 --- a/routers/repo/setting.go +++ b/routers/repo/setting.go @@ -634,3 +634,7 @@ func GitHooksEditPost(ctx *middleware.Context) { } ctx.Redirect(ctx.Repo.RepoLink + "/settings/hooks/git") } + +func TriggerHook(ctx *middleware.Context) { + models.HookQueue.AddRepoID(ctx.Repo.Repository.Id) +} diff --git a/templates/.VERSION b/templates/.VERSION index 76191dfa0..fe3aa1abf 100644 --- a/templates/.VERSION +++ b/templates/.VERSION @@ -1 +1 @@ -0.6.2.0725 Beta \ No newline at end of file +0.6.3.0725 Beta \ No newline at end of file